DockerCompose 启动 open-match
背景介绍
open-match是Google和unity联合开源的支持实时多人匹配的框架,已有多家游戏厂商在生产环境使用,官网 https://open-match.dev/site/ 。原本我们使用的是UOS上提供的匹配能力,但是UOS目前不支持自建的Dedicated servers 集群,只能上传镜像,UOS会自动完成分配以及创建,灵活性就不是那么高了,按照open-match的官方教程,需要有k8s的环境。但是小公司就是不想要k8s,我就想单机部署,可以使用docker-compose。open-match本身的镜像build 提供了dockerfile文件。把项目clone到本地,然后在 tm中以此使用以下命令构建对用的image
tip:该方案只是启动了 core 部分要求的组件即
搭建步骤
Install with YAML | Open Match
后面的部分,需要自行探索了,现在也在学习中,欢迎交流讨论
先构建一个中间镜像base builder,然后一次构建对应的component即可,需要修改Dockerfile.cmd中的
FROM open-match-base-build as builder
为,目的是指定使用本地的version版本,否则会远程拉取镜像,网络问题会导致不成功,需要开梯子
FROM open-match-base-build:latest as builder
docker build -f .\Dockerfile.base-build -t open-match-base-build .
docker build --build-arg IMAGE_TITLE=synchronizer -f .\Dockerfile.cmd -t open-match-synchronizer .
接着使用docker-compose.yaml 来控制启动过程,内如如下
version: '3'
services:open-match-backend:image: open-match-backend:latestcontainer_name: open-match-backendvolumes:- ./matchmaker_config_default.yaml:/app/matchmaker_config_default.yaml- ./matchmaker_config_override.yaml:/app/matchmaker_config_override.yamlports:- "50505:50505" # gRPC- "51505:51505" # HTTPenvironment:API_BACKEND_HOSTNAME: "open-match-backend"API_BACKEND_GRPC_PORT: "50505"API_BACKEND_HTTP_PORT: "51505"REDIS_HOSTNAME: "open-match-redis"REDIS_PORT: "6379"depends_on:- redisopen-match-frontend:image: open-match-frontend:latestcontainer_name: open-match-frontendports:- "50504:50504" # gRPC- "51504:51504" # HTTPvolumes:- ./matchmaker_config_default.yaml:/app/matchmaker_config_default.yaml- ./matchmaker_config_override.yaml:/app/matchmaker_config_override.yamlenvironment:API_FRONTEND_HOSTNAME: "open-match-frontend"API_FRONTEND_GRPC_PORT: "50504"API_FRONTEND_HTTP_PORT: "51504"REDIS_HOSTNAME: "open-match-redis"REDIS_PORT: "6379"depends_on:- redisopen-match-query:image: open-match-query:latestcontainer_name: open-match-queryports:- "50503:50503" # gRPC- "51503:51503" # HTTPenvironment:API_QUERY_HOSTNAME: "open-match-query"API_QUERY_GRPC_PORT: "50503"API_QUERY_HTTP_PORT: "51503"REDIS_HOSTNAME: "open-match-redis"REDIS_PORT: "6379"volumes:- ./matchmaker_config_default.yaml:/app/matchmaker_config_default.yaml- ./matchmaker_config_override.yaml:/app/matchmaker_config_override.yamldepends_on:- redisopen-match-synchronizer:image: open-match-synchronizer:latestcontainer_name: open-match-synchronizervolumes:- ./matchmaker_config_default.yaml:/app/matchmaker_config_default.yaml- ./matchmaker_config_override.yaml:/app/matchmaker_config_override.yamlports:- "50506:50506" # gRPC- "51506:51506" # HTTPenvironment:API_SYNCHRONIZER_HOSTNAME: "open-match-synchronizer"API_SYNCHRONIZER_GRPC_PORT: "50506"API_SYNCHRONIZER_HTTP_PORT: "51506"REDIS_HOSTNAME: "open-match-redis"REDIS_PORT: "6379"depends_on:- redisopen-match-swaggerui:image: open-match-swaggerui:latestcontainer_name: open-match-swaggeruiports:- "51500:51500" # HTTP for Swagger UIvolumes:- ./matchmaker_config_default.yaml:/app/matchmaker_config_default.yaml- ./matchmaker_config_override.yaml:/app/matchmaker_config_override.yamlenvironment:API_SWAGGERUI_HOSTNAME: "open-match-swaggerui"API_SWAGGERUI_HTTP_PORT: "51500"depends_on:- open-match-backend- open-match-frontend- open-match-query- open-match-synchronizerredis:image: redis:alpinecontainer_name: open-match-redisports:- "6379:6379"volumes:- redis-data:/datavolumes:redis-data:
matchmaker_config_default.yaml 的内容和 matchmaker_config_override.yaml的内容是一致的,目的就是override可以覆盖default中的值(猜的),这部分内容从k8s的yaml文件中copy过来,内容如下
logging:level: debugformat: textrpc: false
# Open Match applies the exponential backoff strategy for its retryable gRPC calls.
# The settings below are the default backoff configuration used in Open Match.
# See https://github.com/cenkalti/backoff/blob/v3/exponential.go for detailed explanations
backoff:# The initial retry interval (in milliseconds)initialInterval: 100ms# maxInterval caps the maximum time elapsed for a retry intervalmaxInterval: 500ms# The next retry interval is multiplied by this multipliermultiplier: 1.5# Randomize the retry intervalrandFactor: 0.5# maxElapsedTime caps the retry time (in milliseconds)maxElapsedTime: 3000msapi:backend:hostname: "open-match-backend"grpcport: "50505"httpport: "51505"frontend:hostname: "open-match-frontend"grpcport: "50504"httpport: "51504"query:hostname: "open-match-query"grpcport: "50503"httpport: "51503"synchronizer:hostname: "open-match-synchronizer"grpcport: "50506"httpport: "51506"swaggerui:hostname: "open-match-swaggerui"httpport: "51500"# Configurations for api.test and api.scale are used for testing.test:hostname: "open-match-test"grpcport: "50509"httpport: "51509"scale:httpport: "51509"redis:# Open Match's default Redis setupshostname: open-match-redis# source value: open-match-core.redis.port = 6379port: 6379usePassword: falsepasswordPath: /redis-passwordpool:maxIdle: 200maxActive: 0idleTimeout: 0healthCheckTimeout: 300mstelemetry:reportingPeriod: "1m"traceSamplingFraction: "0.01"zpages:enable: "true"prometheus:enable: "false"endpoint: "/metrics"serviceDiscovery: "true"stackdriverMetrics:enable: "false"gcpProjectId: "replace_with_your_project_id"prefix: "open_match"
然后就可以启动了
运行demo
如果要运行open-match的 demo-first-match,还要一个组件
evaluator
该组件的目的是对所有的matches进行评估,并返回得分,open-match会保留评分最高的组合,比如我们以 战力相差的相近为评估规则,假定 abc,三个玩家的战力分值分配时 10 20 25,则abc三人同时匹配在1v1的条件选,应当尽可能的选择20 25这个相近的评分,评分组件evaluator这个需要开始自行实行,通过synchronizer进行调用,open-match 提供了一个default实现 即default-evaluator,使用以下命令进行构建即可
docker build --build-arg IMAGE_TITLE=default-evaluator -f .\Dockerfile.cmd -t open-match-default-evaluator .
如果开发环境存在需要平凡需求的情况,直接ide环境启动即可,但是需要在 matchmaker_config_default.yaml中指明 evaluator的位置信息
api:evaluator:hostname: "open-match-default-evaluator"httpport: "5499"grpcport: "5498"
接着需要修改几个demo的hostname地址,一个是frontend的hostname,位置在
open-match/examples/demo/components/clients/clients.go:84
//修改前
conn, err := grpc.Dial("open-match-frontend.open-match.svc.cluster.local:50504", grpc.WithInsecure())//修改后
conn, err := grpc.Dial("localhost:50504", grpc.WithInsecure())
另外一个是 backend的hostname
open-match/examples/demo/components/director/director.go:71
//修改前
conn, err := grpc.Dial("open-match-backend.open-match.svc.cluster.local:50505", grpc.WithInsecure())//修改后
conn, err := grpc.Dial("localhost:50505", grpc.WithInsecure())
然后还需要部署一个组件mmf,负责判断给定的组合是否符合要求,可以直接启动 cmd/scale-mmf,或者build镜像,一样的需要修改query的hostname,位置信息如下
open-match/examples/scale/mmf/mmf.go:42
//修改前
conn, err := grpc.Dial("open-match-query.open-match.svc.cluster.local:50503", utilTesting.NewGRPCDialOptions(logger)...)//修改后
conn, err := grpc.Dial("localhost:50503", utilTesting.NewGRPCDialOptions(logger)...)
mmf的服务地址,是由director在fetchMatches指定的,相关的代码位置在
open-match/examples/demo/components/director/director.go:82
不同版本可能会有所变化,当前提及的代码内容来源于open-match的最新master代码,2024年10月9日
req := &pb.FetchMatchesRequest{Config: &pb.FunctionConfig{Host: "om-function.open-match-demo.svc.cluster.local",Port: 50502,Type: pb.FunctionConfig_GRPC,},Profile: &pb.MatchProfile{Name: "1v1",Pools: []*pb.Pool{{Name: "Everyone",},},},}
所以我们需要改掉这里Host所指定的值,修改为mmf的实际地址即可,最后更新docker-compose.yaml并执行 docker-compose -f docker-compose.yaml up,在cmd/demo-first-match/main.go 文件中运行main函数即可成功运行demo程序
demo程序的执行成功后会返回一个虚拟的链接地址,该链接地址由director组件返回,可以理解为在director中返回具体的dedicated server的ip地址,demo中是随机产生的代码位置在
examples/demo/components/director/director.go:132
如果不正确可以搜索2222作为线索定位
for _, match := range matches {ids := []string{}for _, t := range match.Tickets {ids = append(ids, t.Id)}req := &pb.AssignTicketsRequest{Assignments: []*pb.AssignmentGroup{{TicketIds: ids,Assignment: &pb.Assignment{Connection: fmt.Sprintf("%d.%d.%d.%d:2222", rand.Intn(256), rand.Intn(256), rand.Intn(256), rand.Intn(256)),},},},}resp, err := be.AssignTickets(ds.Ctx, req)if err != nil {panic(err)}_ = resp}
匹配成功后返回的链接地址
open-match对mmf,evaluator,director 提供了多种游戏场景的默认实现,可以在亦有模板的基础上结合业务进行开发,具体内容可以查看examples/scale/README.md
感觉联机几千人同时在线这种方式应该够够吧,先这样,散会
补一张open-match 时序图,看懂这个业务开发层面知道各个component的职责范围
相关文章:

DockerCompose 启动 open-match
背景介绍 open-match是Google和unity联合开源的支持实时多人匹配的框架,已有多家游戏厂商在生产环境使用,官网 https://open-match.dev/site/ 。原本我们使用的是UOS上提供的匹配能力,但是UOS目前不支持自建的Dedicated servers 集群&#x…...

Chainlit集成Dashscope实现语音交互网页对话AI应用
前言 本篇文章讲解和实战,如何使用Chainlit集成Dashscope实现语音交互网页对话AI应用。实现方案是对接阿里云提供的语音识别SenseVoice大模型接口和语音合成CosyVoice大模型接口使用。针对SenseVoice大模型和CosyVoice大模型,阿里巴巴在github提供的有开…...

Canal 扩展篇(阿里开源用于数据同步备份,监控表和表字段(日志))
1.Canal介绍 Canal把自己伪装成从数据库,获取mysql主数据库的日志(binlog)信息,所以要想使用canal就得先开启数据库日志 https://github.com/alibaba/canal Canal 主要用途是基于 MySQL 数据库增量日志解析,提供增量…...

顺序表的定义
一.顺序表的定义 顺序表--用顺序存储的方式实现线性表 顺序存储。把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关 系由存储单元的邻接关系来体现。 二.顺序表的实现--静态分配 #include<stdio.h> #define MaxSize 10 //定义最大长度 …...

青少年编程能力等级测评CPA C++一级试卷(1)
青少年编程能力等级测评CPA C一级试卷(1) 一、单项选择题(共20题,每题3.5分,共70分) CP1_1_1.在C中,下列变量名正确的是( )。 A.$123 B&#…...

R语言中的plumber介绍
R语言中的plumber介绍 基本用法常用 API 方法1. GET 方法2. POST 方法3. 带路径参数的 GET 方法 使用 R 对数据进行操作处理 JSON 输入和输出运行 API 的其他选项其他功能 plumber 是个强大的 R 包,用于将 R 代码转换为 Web API,通过使用 plumber&#x…...

uniapp 设置 tabbar 的 midButton 按钮
效果展示: 中间的国际化没生效(忽略就行) 示例代码: 然后在 App.vue 中进行监听: <script>export default {onLaunch(e) {// #ifdef APPuni.onTabBarMidButtonTap(()>{console.log("中间按钮点击回调…...

php 生成随机数
记录:随机数抽奖 要求:每次生成3个 1 - 10 之间可重复(或不可重复)的随机数,10次为一轮,每轮要求数字5出现6次、数字4出现3次、…。 提炼需求: 1,可设置最小数、最大数、每次抽奖生成随机数的个数、是否允许重复 2,可设置每轮指定数字的出现次数 3,可设置每轮的抽奖…...
MySQL 8.4修改初始化后的默认密码
MySQL 8.4修改初始化后的默认密码 (1)初始化mysql: mysqld --initialize --console (2)之后,mysql会生成一个默认复杂的密码,如果打算修改这个密码,可以先用旧密码登录: mysql -u…...

前端开发笔记--css 黑马程序员1
文章目录 1. css 语法规范2.css的书写风格3.基础选择器选择器的分类标签选择器类选择器类选择器的特殊使用--多类名 id 选择器 字体属性常见字体字体大小字体粗细字体倾斜字体的复合简写字体属性总结 文本属性文本颜色文本对齐装饰文本文本缩进文本间距文本属性总结 css的引入方…...
ORACLE 19C创建多个不同字符集PDB
现在需要在一个测试环境创建1个为AL32UTF8的PDB,2个ZHS16GBK的PDB 这种情况下,必须先创建的CDB为AL32UTF8,下面是具体步骤: 1.AL32UTF8的pdb在建实例的时候一起创建完成 2.创建第一个ZHS16GBK的PDB cdr,通过pdbseed来克隆: SQL> create pluggable database cdr admin us…...

基于协同过滤的景区旅游可视化与景区推荐系统(自动爬虫,地点可换)
文章目录 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主项目介绍过程展示项目移植每文一语 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主 项目介绍 本项目是一个综合性的旅游景区数据管理与分析推荐系统,集成了用…...

ElasticSearch搜索引擎
npm run start ELK: ESLogstashKibana Kibana:端口号5601 elasticSearch是面向文档 Kibana可以将ElasticSearch的数据通过友好的页面展示出来。 Es与Kibana的版本一致 es查询的效率很高,处理大数据 ES和solr的区别: 当单纯的对已有…...
leetcode哈希表(二)-两个数组的交集
题目 . - 力扣(LeetCode) 给定两个数组 nums1 和 nums2 ,返回 它们的交集。输出结果中的每个元素一定是唯一的。我们可以不考虑输出结果的顺序 。 示例 1: 输入:nums1 [1,2,2,1], nums2 [2,2] 输出:[…...

嵌入式硬件设计中EDA布局与布线实现
大家好,今天主要给大家分享一下,如何使用立创EDA进行布局和布线,具体实现过程如下: 第一:PCB概念介绍 在介绍PCB的时候,先来说明一下,电子管的发明史。 贝尔在1876年发明了电话,爱迪生1879年发明了白炽灯、特斯拉于1888年发明了电动机,所有这些,都为电子学的诞生准…...

entity,pojo,vo,dto 详解
在Java项目中,包名通常用于组织代码,使其更加清晰和易于维护。entity、pojo、vo和dto是常见的包名,它们各自有不同的含义和用途。下面将详细解释这些包名的含义,并提供一个示例,帮助你更好地理解它们在项目中的应用。 …...
C语言常见知识点
目录 一、单位 二、变量 三、常量 四、转义字符 五、操作符 六、指针 七、数组 一、单位 在刚接触编程时,肯定会了解到计算机的存储单位,它们由小到大分别为bit(位)、Byte(字节)、KB(千字…...

产品设计——应用架构
我的理解应用架构是业务架构的落地,微服务架构下平台的应用架构设计,实质是根据业务来明确应用微服务的边界。因此业务不同,应用架构图也不同。但是基本框架应该相差不大。 其划分原则莫过于高内聚、低耦合。这个跟接口设计是一致的。我们总是…...
Linux初阶——动静态库
一、静态库(格式:libxxx.a) 1. 原理 在运行之前就已经把函数的实现代码拷进 main.c 文件里了,因此静态库的权限是没有可执行权限的,因为根本不会执行到静态库里的内容。静态库的创建原理本质上就是把所有的函数源文件…...

创建一个c#程序,实现字符串类型转整数类型
首先,创建一个c#程序 在代码编辑器中编写代码,点击Run按钮或者按下F5键来运行程序。 下面,编写将字符串类型转换为整数类型的代码。 sing System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Task…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...