题目描述 游戏很多服务—匹配系统 不同服务在不同服务器上,不同服务器之间通信用thrift( rpc框架 远程函数调用)
一)
1)其他知识点 抽象 支持非常多语言
2)多线程 加锁 cpp编译 原理
3)百度 不难
4)恢复出厂设置 数据 不会丢
二)thrift 非常重要的应用
1.基本概念
homework 4 getinfo
不止一个服务
多个服务
分配到不同服务器上
微服务
写了一个game 运行到一个服务器,匹配自己的对手-----------匹配服务 (写一个服务 游戏客户端 游戏后台 匹配系统)
3个节点 + 1:thrift 接口文件夹
匹配系统节点 cpp (服务端 match-server + save client)Ac Terminal 可以让 客户端调用我的函数
游戏节点 python (客户端 match-client 匹配玩家)同时实现两个需求,其他应用也可以酱紫~)Ac Terminal
数据存储 (已经帮助我们实现)------My server 端口:9090 save-server
游戏节点 到 匹配节点 一条有向边
为了方便用两个不同的文件夹表示两个不同的节点-------两个节点可以放到不同服务器上
画图学乱服务
thrift 接口文件夹
1.如何实现?
a.自己定义一个添加玩家 删除玩家的接口。教程看官网tutorial.thrift
用户名
定义结构体定义传输用户信息 i32表示int
定义函数 传一个额外信息多么重要,不用更改接口,可以把额外信息放到info 序列化jason
定义类?看文档细节
在git上看代码更清晰
如何用接口实现具体节点?
1)先去实现服务端 官网 教程 cpp
src 文件夹 放置 源文件
2)
匹配系统功能*3 (匹配 评测 都可以)
1.匹配系统添加一名玩家(add_user函数)-----数据存储服务器(应用模型 游戏模型)
2.匹配系统删除玩家(remove_user函数)
3.分数相近的玩家安排一起 安排一局游戏
匹配结果写到另一个服务器上
thrift 有向边
结点 进程 不同语言实现
根据定义的接口实现对应的请求操作
1.定义接口
2.服务端 server
3.请求client
rpc框架 远程函数调用 调用另外一个服务器的函数
acgit支持markdown 语法
使用cpp编写服务器端
问题 :非正常退出,遇到端口被占用的解决办法
1)netstat -antp |grep 9090
2)kill -9 4122
3)netstat -antp |grep 9090
return :[1]+ Killed ./main
ctrl + c 正常退出
接口生成之后,使用接口生成cpp版本的服务器:看官网 tutorial cpp
进入 match_system mkdir src 源文件
方便 改名 match_server只定义好接口,但是业务逻辑没有定义
先编译跑通,然后逐步往里添加模块
cpp 编译需要两步:
1)编译 g++ -c file.cpp match_server/*.cpp
2)链接g++ *.o -o main -lthrift
可执行文件 和 编译文件 最好不要加入暂存区
只加源文件
py编写客户端
官网:https://thrift.apache.org/
tutorial
python -- client copy 下来 改改使用
thrift -r –gen py ../../thrift/match.thrift 生成py的服务器端:gen-py –rename :match_client
match-remote 用py实现服务器端 –rm
client.py 官网例子 黏贴
改1) 删除
前四行将当前路径加到python的环境变量
改2)
from match_client.match import Match
from match_client.match.ttypes import User
改3)删除无用代码
改4)client = Match.Client(protocol)
5)if name== “main” 好习惯
main()
6)user = User(1,‘koko’,1000)
client.add_user(user, “”)
pythin3 client.py
git restore –stage .pyc
git restore – stage .swp
进阶:
def operate (op,user_id,username,score
)
根据参数创建一个用户 connet
user = User(user_id,username,score)
if op == “add”:
client.add_user(user,“”)
else op == “remove”:
client.remove_user(user,“”)
py从终端读取东西 from sys import stdin
def main():
for line in stdin:
op,user_id,username,score = line.split(‘’)
operate(op,int(user_id),username,int(score))
业务模型:线程1)不停的做匹配 + 线程2)读取用户进来 (两个独立的操作 : 并行操作)
1)给匹配(简单 复杂) 单开一个线程
并行 1 2 生产者 消费者 模型
匹配完毕传给另一个服务器
a. 消费者 线程 *n
0)cpp 里有一个#include[HTML_REMOVED]库用来开线程
1)线程操作函数 消费者模型 消耗任务 看有没有玩家匹配到一起 死循环
2)死循环单开一个线程:thread matching_thread(函数指针传入:consume_task);
生产者 与 消费者 之间 有 通信媒介
b. 生产者模型
add user
remove user
c.### 生产者消费者之间通信媒介:之一 消费队列(很多语言有自己实现的 ,自己实现需要锁)
消费者 和 生产者 同时用到这个队列q
消费者 用到这个队列的头节点 head 冲突 报错 不能同时 操作
保证 同时 只能有一个进程 去写这个队列
等待线程 获得 这个锁 再去执行
锁 mutex m #include [HTML_REMOVED] 并行编程重要概念 操作系统 大二
p(m)操作 获取锁 保证其他进程不会并行执行这一段 其他函数阻塞在这一段上
v(m)操作
条件变量 #include [HTML_REMOVED]配合锁 实现 消费队列更容易一些
对锁进行一个封装
条件标量 和 锁 把 普通队列(#include queue) 包装成 一个消费队列
do task
匹配池玩家池 维护所有的玩家
无符号整数类型 .size 如果写int 报wearning
写工程 0 wearning
g++ *.o -o main -lthrift -pthread
链接 + 链接线程的动态链接库
链接
-lthrift
-pthread
.o可执行文件不要上传git 不专业 专业应该只有代码
(三)将数据存储服务节点
方法:在当前节点实现 服务有向边 client 的端
服务端不需要我们实现
服务这条有向边接口
已经定义好的
homework 4 getinfo
如何求一个字符串的md5值 :1)md5sum 2)回车 3)crl+d结束回车 4)前8 位 5)记录下
thrift -r –g cpp ../../thrift/save.thrift : gen - cpp
服务端删除,否侧出现两个main函数
将save client端 存储到服务器
1)打开main.cpp:有技巧的从官网抄
头文件 少了什么
2) 自己的头文件使用“”,系统头文件使用<>
自己的命名空间 :看下thrift 接口
将官网代码进入黏贴模式贴上,退出黏贴模式,格式化
crt - 缩小字体
crt shift + 放大字体
本地 127.0.0.1 9090 连接到本地client
数据存储到 myserver
删除到close()
transport->open();
client.save_date(“acs_***”, “md5sum”);
transport->close();
`` 登出myserver :logout
git --help
存储未来有自己的数据库,存储到数据库(不需要自己写,用框架写)里
强迫自己把思路过一遍 因为thrift很重要 没有只能在一个服务器上死磕 很难扩展 工程部分难点 -- 业务部分难点
升级匹配系统
shooting :现在匹配逻辑有点弱智:每次匹配前两个人 1000 2000都可以匹配,很不合适
tar :升级 分差50以内才可以匹配
一般些项目流程:
1)先写一个跑通:每次匹配前两个人
2)逐步完善
3)数据库不需要自己学,各种框架已经帮我做好了,用框架对接就可以
4) 面向对象,每次改一个逻辑
本题思路:分差匹配
1)先把所有用户按分差排个序,每次匹配相近的人
2) 找到第一对分差50以内的玩家 匹配到一起
尽量多用工具,少自己造轮子,官方文档非常详细看文档
多线程服务器 每次调用一个函数就开一个线程
thrift官网教程
1)先开 100个
1)int main() {
TThreadedServer server(
2)class CalculatorCloneFactory
3)simpleserver 删除干净
4)替换calculator 替换
5)Match
多线程 锁 操作系统
时间 匹配范围扩大
等待描述 百度c++ 如何读取时间