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…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...

有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...