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:latest
    container_name: open-match-backend
    volumes:
      - ./matchmaker_config_default.yaml:/app/matchmaker_config_default.yaml
      - ./matchmaker_config_override.yaml:/app/matchmaker_config_override.yaml
    ports:
      - "50505:50505"  # gRPC
      - "51505:51505"  # HTTP
    environment:
      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:
      - redis

  open-match-frontend:
    image: open-match-frontend:latest
    container_name: open-match-frontend
    ports:
      - "50504:50504"  # gRPC
      - "51504:51504"  # HTTP
    volumes:
      - ./matchmaker_config_default.yaml:/app/matchmaker_config_default.yaml
      - ./matchmaker_config_override.yaml:/app/matchmaker_config_override.yaml
    environment:
      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:
      - redis

  open-match-query:
    image: open-match-query:latest
    container_name: open-match-query
    ports:
      - "50503:50503"  # gRPC
      - "51503:51503"  # HTTP
    environment:
      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.yaml
    depends_on:
      - redis

  open-match-synchronizer:
    image: open-match-synchronizer:latest
    container_name: open-match-synchronizer
    volumes:
      - ./matchmaker_config_default.yaml:/app/matchmaker_config_default.yaml
      - ./matchmaker_config_override.yaml:/app/matchmaker_config_override.yaml
    ports:
      - "50506:50506"  # gRPC
      - "51506:51506"  # HTTP
    environment:
      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:
      - redis

  open-match-swaggerui:
    image: open-match-swaggerui:latest
    container_name: open-match-swaggerui
    ports:
      - "51500:51500"  # HTTP for Swagger UI
    volumes:
      - ./matchmaker_config_default.yaml:/app/matchmaker_config_default.yaml
      - ./matchmaker_config_override.yaml:/app/matchmaker_config_override.yaml
    environment:
      API_SWAGGERUI_HOSTNAME: "open-match-swaggerui"
      API_SWAGGERUI_HTTP_PORT: "51500"
    depends_on:
      - open-match-backend
      - open-match-frontend
      - open-match-query
      - open-match-synchronizer

  redis:
    image: redis:alpine
    container_name: open-match-redis
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data

volumes:
  redis-data:

matchmaker_config_default.yaml 的内容和 matchmaker_config_override.yaml的内容是一致的,目的就是override可以覆盖default中的值(猜的),这部分内容从k8s的yaml文件中copy过来,内容如下
 

logging:
  level: debug
  format: text
  rpc: 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 interval
  maxInterval: 500ms
  # The next retry interval is multiplied by this multiplier
  multiplier: 1.5
  # Randomize the retry interval
  randFactor: 0.5
  # maxElapsedTime caps the retry time (in milliseconds)
  maxElapsedTime: 3000ms

api:
  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 setups
  hostname: open-match-redis
  # source value: open-match-core.redis.port = 6379
  port: 6379
  usePassword: false
  passwordPath: /redis-password
  pool:
    maxIdle: 200
    maxActive: 0
    idleTimeout: 0
    healthCheckTimeout: 300ms

telemetry:
  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的职责范围


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/890094.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

grpc的python使用

RPC 什么是 RPC ? RPC(Remote Procedure Call)远程过程调用,是一种计算机通信协议,允许一个程序(客户端)通过网络向另一个程序(服务器)请求服务,而无需了解…

【Matlab】Matlab 导入数据.csv或者.xlsx文件,然后使用这些数据来绘制图表

Matlab 导入数据.csv或者.xlsx文件,然后使用这些数据来绘制图表 初始数据 filename C:\Users\jia\Desktop\yadian\data\1Hz 2024_09_12 17_10_06.csv; 代码: clc;clear close all; % 读取Excel文件 filename C:\Users\jia\Desktop\yadian\data\1Hz …

【EXCEL数据处理】保姆级教程 000016案例 EXCEL的vlookup函数。

【EXCEL数据处理】000016案例 vlookup函数。 前言:哈喽,大家好,今天给大家分享一篇文章!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 【EXCEL数据处理】保姆级教…

Flutter包管理(三)

1、作用 在APP的实际开发过程中往往会依赖很多包,而这些包之间存在着交叉依赖、版本依赖,由开发者自己管理手动管理会非常麻烦,每种开发生态或编程官方会提供一些包的管理工具,在Flutter中我们在pubspec.yaml文件中来管理第三方依…

机器学习/数据分析--用通俗语言讲解时间序列自回归(AR)模型,并用其预测天气,拟合度98%+

时间序列在回归预测的领域的重要性,不言而喻,在数学建模中使用及其频繁,但是你真的了解ARIMA、AR、MA么?ACF图你会看么?? 时间序列数据如何构造???,我打过不少…

GS-SLAM论文阅读笔记-MGSO

前言 MGSO首字母缩略词是直接稀疏里程计(DSO),我们建立的光度SLAM系统和高斯飞溅(GS)的混合。这应该是第一个前端用DSO的高斯SLAM,不知道这个系统的组合能不能打得过ORB-SLAM3,以及对DSO会做出怎么样的改进以适应高斯地图,接下来…

Android一个APP里面最少有几个线程

Android一个APP里面最少有几个线程 参考 https://www.jianshu.com/p/92bff8d6282f https://www.jianshu.com/p/8a820d93c6aa 线程查看 Android一个进程里面最少包含5个线程,分别为: main线程(主线程)FinalizerDaemon线程 终结者守护线程…

Golang | Leetcode Golang题解之第462题最小操作次数使数组元素相等II

题目&#xff1a; 题解&#xff1a; func partition(a []int, l, r int) int {x : a[r]i : l - 1for j : l; j < r; j {if a[j] < x {ia[i], a[j] a[j], a[i]}}a[i1], a[r] a[r], a[i1]return i 1 }func randomPartition(a []int, l, r int) int {i : rand.Intn(r-l1…

Android车载——VehicleHal运行流程(Android 11)

1 概述 本篇主要讲解VehicleHal的主要运行流程&#xff0c;包括设置属性、获取属性、订阅属性、取消订阅、持续上报属性订阅等。 2 获取属性流程 2.1 获取属性流程源码分析 作为服务注册到hwServiceManager中的类是VehicleHalManager&#xff0c;所以&#xff0c;CarServic…

【Qt】控件概述(2)—— 按钮类控件

控件概述&#xff08;2&#xff09; 1. PushButton2. RadioButton——单选按钮2.1 使用2.2 区分信号 clicked&#xff0c;clicked(bool)&#xff0c;pressed&#xff0c;released&#xff0c;toggled(bool)2.3 QButtonGroup分组 3. CheckBox——复选按钮 1. PushButton QPushB…

简单粗暴理解GNN、GCN、GAT

GNN 思想&#xff1a;近朱者赤近墨者黑 GNN的流程&#xff1a; 聚合&#xff08;把邻居的信息贴到自己身上来&#xff0c;作为它自己特征的补足&#xff09;更新循环&#xff08;为什么要多次&#xff1f;看以下例子&#xff09; GNN能干嘛&#xff1f; 1.结点分类&#xf…

动态规划lc

先找到规律&#xff0c;然后找边界情况&#xff1b;部分特殊情况分类讨论 *递归 70.爬楼梯 简单 提示 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a…

基于yolov8、yolov5的PCB板缺陷检测系统(含UI界面、数据集、训练好的模型、Python代码)

blog.csdnimg.cn/direct/6f53422ed9fd44dc8daad6dc5481c4c9.png) 项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov8、yolov8 SE注意力机制 或 yolov5、yolov5 SE注意力机制 &#xff0c; 直接提供最少两个训练好的模型…

第十八届 图像像素类型转化于归一

知识点&#xff1a;像素归一化 opencv中提供四种归一的方法 -NORM_MINMAX -NORM_INF -NORM_L1 -NORM_L2 最常用的就是NORM_MINMAX归一的方法 相关的API normalize&#xff1a;void normalize(InputArray src, OutputArray dst, double alpha 1, double beta 0, int n…

关于C语⾔内存函数 memcpy memmove memset memcmp

memcpy使⽤和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 这个函数在遇到 \0 的时候并不会停下来。 如果source和destination有任何的重叠&am…

树莓派3b安装ubuntu18.04服务器系统server配置网线连接

下载ubuntu镜像网址 img镜像&#xff0c;即树莓派官方烧录器使用的镜像网址 ubuntu18.04-server&#xff1a;ARM/RaspberryPi - Ubuntu Wiki 其他版本&#xff1a;Index of /ubuntu/releases 下载后解压即可。 发现使用官方烧录器烧录配置时配置wifi无论如何都不能使用&am…

linux入门——“权限”

linux中有权限的概念&#xff0c;最常见的就是安装一些命令的时候需要输入sudo来提权&#xff0c;那么为什么要有这个东西呢&#xff1f; linux是一个多用户操作系统&#xff0c;很多东西看起来是有很多分&#xff0c;但是实际的存储只有一份&#xff08;比如命令&#xff0c;不…

小程序知识付费的优势 知识付费服务 知识付费平台 知识付费方法

在信息爆炸的时代&#xff0c;知识如同繁星点点&#xff0c;璀璨而散落。如何在这片知识的海洋中精准捕捞&#xff0c;成为现代人追求自我提升的迫切需求。小程序知识付费&#xff0c;正是这样一座桥梁&#xff0c;它以独特的优势&#xff0c;让智慧触手可及&#xff0c;轻触未…

【C++差分数组】P1672何时运输的饲料

本文涉及知识点 C差分数组 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 P1672何时运输的饲料 原文比较啰嗦&#xff0c;我简述一下&#xff1a; 第x天运来F1(1<F1<1e6)千克的饲料&#xff0c;第D&#xff08;1<2e3)天还剩F2&…

数论与同余 - 离散数学系列(七)

目录 1. 整数的性质 整除与因数 最大公约数与最小公倍数 2. 欧几里得算法 算法步骤 3. 模运算与同余 模运算 同余关系 同余的性质 4. 数论在密码学中的应用 RSA 加密算法 5. 实际应用场景 1. 数字签名 2. 哈希函数与数据完整性 3. 密钥交换 6. 例题与练习 例题…