golang游戏服务器框架有没有好的开源游戏框架

golang 手游框架设计 - 本人浅陋的见解, 求达人指正
- Go语言中文网 - Golang中文社区
<meta name="author" content="polaris ">
golang 手游框架设计 - 本人浅陋的见解, 求达人指正
· 4890 次点击 ·
开始浏览 & &
如有错误的地方,请同仁指正,非常感谢
第一种方式:
Login: 登陆服(同时用于聊天系统)
socket长连接
Game: 游戏服(游戏逻辑处理)
http短连接
Mysql: 数据库回写 socket
客户端socket连接login,保持长连接,验证成功后,向game服以http方式请求数据
game服向login服http方式验证该客户端是否已经正常登陆, 1: 没有登录则,game返回数据给客户,没有登录状态. 2: 已经登陆,则game返回所需数据给客户端.
game将修改后的数据以sql语句形式发送给mysql服,同时记录当前sql到文件中用于备查.
使用单独login服的好处在于 客户端可以一直保持连接,并且login服逻辑处理少. 服务器压力小.同时在game服有问题需要闪断时,还能继续保持玩家登陆状态,在紧急更新game服后,客户端不需要重新连接登陆游戏. 并且因为login较少的逻辑处理, 各个socket共存连接能力相应变强.可以提高同时在线玩家数. 使用socket连接,便于服务端主动向客户端发送聊天,公告等信息.
与game服连接方式不同,主要是因为两个进程间功能不同导致.
game服使用http方式,http处理能力相较于socket更好,使用更方便,基本不需要去考虑网络连接的状态问题.客户端需要什么数据,可以直接Get请求. 对于每次请求数据,都是单独一个go程, http并发处理也会更好.
login服只读取玩家的Account信息用于验证.不生成新sql数据. 如果新用户登陆,则生成一份临时数据用于表示新用户登陆成功.返回给客户端一个uid.作为客户端登陆的标记. 客户端向game服请求数据时,再由game生成sql数据,同时get方式通知login服临时数据为永久数据. sql语句通知mysql服回写数据.
客户端每次向game请求数据都需要带上参数uid, game服使用uid向login服通过http方式验证客户端是否已经登陆成功. 1:没有登录则提醒登陆 2.已经登陆,则处理逻辑数据
(这里有个问题,game与login直接的验证会非常频繁)
game服的数据处理,则使用内存共享方式.
game服启动时将mysql数据库中的数据全部读取到内存中. 结构如下:
type UserData struct{//单个玩家的结构数据
Account Account //单个玩家的账号信息,元宝,铜钱等属性
Bag []Bag //单个玩家的背包物品数据. 多个物品
Friend []Friend //单个玩家的好友 多个好友
sync.RWMutex //单个玩家的数据锁
UserDatas = make(map[int32]UserData)
//全服所有玩家数据
type Shop struct{ //商店表 配置表
ShopInfo = make(map[int32] Shop) //商店的配置表数据
说明a: 玩家的信息,统一放在UserData中,多条数据使用slice结构,尽量减少&#34;对象&#34;数量.
不能统一的数据则单独一个结构.
game服在游戏过程中,只要数据变化则生成优化后的sql语句,通知mysql服回写到数据库
mysql服只负责接收sql语句, 并写入到数据库,记录下当前写成功的sql语句第几条.用于数据出错时. 对比sql文件,已经写到哪一条语句.便于恢复数据库. 如果一旦数据回写错误,则停止接下去的语句回写, 需要记录下后续语句的数量即可, 并马上通知dba管理员.
说明b: 如果一个玩家操作需要影响到其它玩家,则由game服请求login服,由login服主动通知客户端数据.免去了客户端定时请求某些操作的麻烦.
例如: A玩家在地图上移动,需要通知周边其它玩家,A玩家新的坐标点. 此时由game服请求login服,login服通知在线玩家A的新数据.
第二种方式:
纯http连接.
game服: http连接
mysql服:数据回写处理.
A玩家向game请求登陆,game验证成功后,记录A玩家登陆成功,并返回给客户端uid.则此后3分钟都认为该uid的玩家处于登陆状态. A客户端每次请求数据都更新A玩家的最后时间.
其中uid为加密后的数据. 每次重新验证则生成不同的uid.
纯http的弊端: 服务器不能实时通知客户端信息.
游戏中建立玩家数据更新标志位. 如A玩家定时2-5秒请求公告标志位,发现公告标志位是新的,则读取.
A玩家移动,需要通知其它周边玩家, 则向其它玩家的移动处理队列中添加新数据,并更新通知标志位, B玩家每1-2秒请求检查标志位状态,有新数据则获取.
以上两种方式,其中数据传输该加密的方式则需要加密.
本人新手,求达人指正
4890 次点击 &
2 回复 &| &直到
请尽量让自己的回复能够对别人有帮助
支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
支持 @ 本站用户;支持表情(输入 : 提示),见
图片支持拖拽、截图粘贴等方式上传
记住登录状态
如有错误的地方,请同仁指正,非常感谢
第一种方式:
Login: 登陆服(同时用于聊天系统)
socket长连接
Game: 游戏服(游戏逻辑处理)
http短连接
Mysql: 数据库回写 socket
客户端socket连接login,保持长连接,验证成功后,向game服以http方式请求数据
game服向login服http方式验证该客户端是否已经正常登陆, 1: 没有登录则,game返回数据给客户,没有登录状态. 2: 已经登陆,则game返回所需数据给客户端.
game将修改后的数据以sql语句形式发送给mysql服,同时记录当前sql到文件中用于备查.
使用单独login服的好处在于 客户端可以一直保持连接,并且login服逻辑处理少. 服务器压力小.同时在game服有问题需要闪断时,还能继续保持玩家登陆状态,在紧急更新game服后,客户端不需要重新连接登陆游戏. 并且因为login较少的逻辑处理, 各个socket共存连接能力相应变强.可以提高同时在线玩家数. 使用socket连接,便于服务端主动向客户端发送聊天,公告等信息.
与game服连接方式不同,主要是因为两个进程间功能不同导致.
game服使用http方式,http处理能力相较于socket更好,使用更方便,基本不需要去考虑网络连接的状态问题.客户端需要什么数据,可以直接Get请求. 对于每次请求数据,都是单独一个go程, http并发处理也会更好.
login服只读取玩家的Account信息用于验证.不生成新sql数据. 如果新用户登陆,则生成一份临时数据用于表示新用户登陆成功.返回给客户端一个uid.作为客户端登陆的标记. 客户端向game服请求数据时,再由game生成sql数据,同时get方式通知login服临时数据为永久数据. sql语句通知mysql服回写数据.
客户端每次向game请求数据都需要带上参数uid, game服使用uid向login服通过http方式验证客户端是否已经登陆成功. 1:没有登录则提醒登陆 2.已经登陆,则处理逻辑数据
(这里有个问题,game与login直接的验证会非常频繁)
game服的数据处理,则使用内存共享方式.
game服启动时将mysql数据库中的数据全部读取到内存中. 结构如下:
type UserData struct{//单个玩家的结构数据
Account Account //单个玩家的账号信息,元宝,铜钱等属性
Bag []Bag //单个玩家的背包物品数据. 多个物品
Friend []Friend //单个玩家的好友 多个好友
sync.RWMutex //单个玩家的数据锁
UserDatas = make(map[int32]UserData)
//全服所有玩家数据
type Shop struct{ //商店表 配置表
ShopInfo = make(map[int32] Shop) //商店的配置表数据
说明a: 玩家的信息,统一放在UserData中,多条数据使用slice结构,尽量减少&#34;对象&#34;数量.
不能统一的数据则单独一个结构.
game服在游戏过程中,只要数据变化则生成优化后的sql语句,通知mysql服回写到数据库
mysql服只负责接收sql语句, 并写入到数据库,记录下当前写成功的sql语句第几条.用于数据出错时. 对比sql文件,已经写到哪一条语句.便于恢复数据库. 如果一旦数据回写错误,则停止接下去的语句回写, 需要记录下后续语句的数量即可, 并马上通知dba管理员.
说明b: 如果一个玩家操作需要影响到其它玩家,则由game服请求login服,由login服主动通知客户端数据.免去了客户端定时请求某些操作的麻烦.
例如: A玩家在地图上移动,需要通知周边其它玩家,A玩家新的坐标点. 此时由game服请求login服,login服通知在线玩家A的新数据.
第二种方式:
纯http连接.
game服: http连接
mysql服:数据回写处理.
A玩家向game请求登陆,game验证成功后,记录A玩家登陆成功,并返回给客户端uid.则此后3分钟都认为该uid的玩家处于登陆状态. A客户端每次请求数据都更新A玩家的最后时间.
其中uid为加密后的数据. 每次重新验证则生成不同的uid.
纯http的弊端: 服务器不能实时通知客户端信息.
游戏中建立玩家数据更新标志位. 如A玩家定时2-5秒请求公告标志位,发现公告标志位是新的,则读取.
A玩家移动,需要通知其它周边玩家, 则向其它玩家的移动处理队列中添加新数据,并更新通知标志位, B玩家每1-2秒请求检查标志位状态,有新数据则获取.
以上两种方式,其中数据传输该加密的方式则需要加密.
本人新手,求达人指正
159 人在线
&最高记录 1364
&2012- Go语言中文网,中国 Golang 社区,致力于构建完善的 Golang 中文社区,Go语言爱好者的学习家园。
Powered by
&o&服务器由
赞助 &·&CDN 由
VERSION: V3.0.0&·&4.546168ms&·&为了更好的体验,本站推荐使用 Chrome 或 Firefox 浏览器
登录和大家一起探讨吧
记住登录状态
还不是会员问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
请问各位大大leaf、cellnet、mqant 、xingo 有没有使用这些框架有上线的游戏呀? 或者有哪位用这些框架的一种在作游戏开发呢? 目前在选一个可分布式的游戏框架 一直拿不定注意。 我还没有那种水平去写框架。 所以求指导。
同步到新浪微博
分享到微博?
Hi,欢迎来到 SegmentFault 技术社区!⊙▽⊙ 在这里,你可以提出编程相关的疑惑,关注感兴趣的问题,对认可的回答投赞同票;大家会帮你解决编程的问题,和你探讨技术更新,为你的回答投上赞同票。
明天提醒我
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
我要该,理由是:主题信息(必填)
主题描述(最多限制在50个字符)
申请人信息(必填)
申请信息已提交审核,请注意查收邮件,我们会尽快给您反馈。
如有疑问,请联系
CSDN &《程序员》编辑/记者,投稿&纠错等事宜请致邮
你只管努力,剩下的交给时光!
如今的编程是一场程序员和上帝的竞赛,程序员要开发出更大更好、傻瓜都会用到软件。而上帝在努力创造出更大更傻的傻瓜。目前为止,上帝是赢的。个人网站:。个人QQ群:、
个人大数据技术博客:golang开源即时通信框架
golang开源及时通信框架:Lhttp是一个基于websocket服务端框架,提供一个类似http的协议去帮助开发者开发长连接的应用。
使用Lhttp可以大量减少服务端开发的工作量,实现非常好的模块化和业务功能的解耦合。
可以定制任何你想要的功能。
使用简单,功能强大 性能高,使用gnatsd消息队列 publish 10000 条消息耗时0.04s(single-core CPU,1G memory). 支持集群,横向扩展,通过增加服务器来获取更高的服务能力 非常容器进行定制与扩展 可以非常好的与http服务协同工作,如利用http发送消息,将消息转发给上游http服务器等。所以即便你不会go语言也可以开发一些应用。
+--------------------+
+--------------------+
+--------------------+
+--------------------+
+---------------------------------------+
message center cluster (gnatsd)
+---------------------------------------+
........|.................|...............|..................
| +-------------+
+-------------+
+-------------+
| |lhttp server |
|lhttp server |
|lhttp server |
lhttp 服务集群
| +-------------+
+-------------+
+-------------+
.....|..........._____|
|___.............|
|_________......
&----使用websocket链接
+--------+
+--------+
+--------+
+--------+
+--------+
| client |
| client |
| client |
| client |
| client |
+--------+
+--------+
+--------+
+--------+
+--------+
go /nats-io/nats
go /fanux/lhttp
先启动gnatsd:
./gnatsd &
打开另一个终端,执行客户端程序,输入命令码:
./lhttpClient
使用docker快速体验
$ docker build -t lhttp:latest .
$ docker run -p
lhttp:latest
打开,访问: https://localhost:9090.
打开两个窗口就可以聊起来了。
websocket 端口是 8081, 可以使用自己的websocket客户端去连 ws://localhost:8081
也可以从dockerhub上下载镜像:
$ docker run -p
fanux/lhttp:latest
LHTTP/1.0 Command\r\n
--------起始行,协议名和版本,Command:非常重要,标识这条消息的命令码是什么,服务端也是根据命令码注册对应的处理器的。
Header1:value\r\n
--------首部
Header2:value\r\n
--------消息体
LHTTP/1.0 chat\r\n
命令码叫`chat`
content-type:json\r\n
消息体使用json编码
publish:channel_jack\r\n
服务端请把这条消息publish给jack (jack订阅了channel_jack)
from:mike,
message:hello jack,
time::30:48
使用教程,只需三步
定义你的处理器,需要聚合 BaseProcessor
type ChatProcessor struct {
*lhttp.BaseProcessor
实现三个接口,连接打开时干嘛,关闭时干嘛,消息到来时干嘛。
type ChatProcessor struct {
func (p ChatProcessor)OnOpen(h *WsHandler) {
//your logic
func (p ChatProcessor)OnClose(h *WsHandler) {
//your logic
func (p ChatProcessor)OnMessage(h *WsHandler) {
//your logic
注册你的处理器,这里的chat 与消息体中的chat对应,也就是这个处理器仅会处理LHTTP/1.0 chat\r\n....这类消息.
lhttp.Regist(&chat&,&ChatProcessor{&lhttp.BaseProcessor{}})
如果命令码是 &chat& ChatProcessor 会处理它。
这里比如收到消息就直接将消息返回:
func (p *ChatProcessor)OnMessage(h *WsHandler) {
h.Send(h.GetBody())
启动服务器
http.Handler(&/echo&,lhttp.Handler(lhttp.StartServer))
http.ListenAndServe(&:8081&)
一个完整的回射例子:
type ChatProcessor struct {
*lhttp.BaseProcessor
func (p *ChatProcessor) OnMessage (h *lhttp.WsHandler) {
log.Print(&on message :&, h.GetBody())
h.Send(h.GetBody())
func main(){
lhttp.Regist(&chat&, &ChatProcessor{&lhttp.BaseProcessor{}})
http.Handle(&/echo&,lhttp.Handler(lhttp.StartServer))
http.ListenAndServe(&:8081&,nil)
下面来看用Lhttp开发及时通信应用有多简单
假设有两个客户端,这里的客户端比如浏览器应用。
LHTTP/1.0 command\r\n
subscribe:channelID\r\n
body optional
client1通过websocket向Lhttp发送如上字符串,就订阅了channelId
LHTTP/1.0 command\r\n
publish:channelID\r\n
body require
client2通过websocket向Lhttp发送如上字符串,就向channelID发布了一条消息。 因为client1订阅了channelID,所以client1会收到这条消息。
client1不想再收消息,那么发如下字符串给服务端即可:
LHTTP/1.0 command\r\n
unsubscribe:channelID\r\n
body optional
订阅/发布 是lhttp内置功能,服务端一行代码不用写即可获取这种服务,只需要使用特定首部subscribe,publish 和unsubscribe
同时订阅多个,如同时订阅多个聊天室。
LHTTP/1.0 chat\r\n
subscribe:channelID1 channelID2 channelID3\r\n
使用http发布消息
URL: /publish .
方法: POST .
http body: 整个lhttp消息
for example I want send a message to who subscribe channel_test by HTTP.
如我想发送一条消息给订阅了channel_test的人。
resp,err := http.POST(&/publish&, &text/plain&,
&LHTTP/1.0 chat\r\npublish:channel_test\r\n\r\nhello channel_test guys!&)
这里封装好了一个更好用的工具 Publish tools.go
//func Publish(channelID []string, command string, header map[string]string, body string) (err error) {
//send message to who subscribe mike.
Publish(&mike&, &yourCommand&, nil, &hello mike!&)
上游服务器
upstream首部可以让lhttp向上游的http服务器发送一条消息。
LHTTP/1.0 command\r\n
upstream:POST \r\n
如果是POST方法,lhttp会把整个消息体当作http的body发送给
如果是GET,lhttp会忽略消息体
LHTTP/1.0 command\r\n
upstream:GET ?user=user_a&age=26\r\n
upstream有什么用:
如我们不想改动lhttp的代码,但是想存储聊天记录。
通过upstream可以实现很好的解耦:
并且http server可以用其它语言实现.
|_____________
+------------+
|lhttp server|
+------------+
|(http request with chat record)
+------------+
| http server|
upstream server(/record)
+------------+
(save chat record)
LHTTP/1.0 chat\r\n
upstream:POST /record\r\n
publish:channel_mike\r\n
hello mike,I am jack
LHTTP/1.0 chat\r\n
subscribe:channel_mike\r\n
这样jack publish消息时不仅mike可以收到,后端的upstream server也可以收到,我们可以在后端服务器中处理消息存储的逻辑,如将消息
存储到redis的有序集合中。
试想一下,一条消息中既有图片也有文字还有语音怎么办? lhttp的multipart首部解决这个问题
LHTTP/1.0 upload\r\n
multipart:0 56\r\n
content-type:text/json\r\n
{filename:file.txt,fileLen:5}
content-type:text/plain\r\n
content-type:text/json\r\n\r\n{filename:file.txt,fileLen:5}content-type:text/plain\r\n\r\nhello
|&---------------------first part-------------------------&|&---------second part------------&|
http中是使用boundry实现的,lhttp使用偏移量标识分块,这样效率更高,不需要遍历整个消息体。
如何获取分块消息
如客户端消息如下:
LHTTP/1.0 upload\r\nmultipart:0 14\r\n\r\nk1:v1\r\n\r\nbody1k2:v2\r\n\r\nbody2
服务端代码,消息存在链表中:
type UploadProcessor struct {
*lhttp.BaseProcessor
func (*UploadProcessor) OnMessage(ws *lhttp.WsHandler) {
for m := ws.GetMultipart(); m != m = m.GetNext() {
log.Print(&multibody:&, m.GetBody(), & headers:&, m.GetHeaders())
//don&#39;t forget to tegist your command processor
lhttp.Regist(&upload&, &UploadProcessor{&lhttp.BaseProcessor{}})登录以解锁更多InfoQ新功能
获取更新并接收通知
给您喜爱的内容点赞
关注您喜爱的编辑与同行
966,690 九月 独立访问用户
语言 & 开发
架构 & 设计
文化 & 方法
您目前处于:
网易NodeJS开源游戏框架pomelo访谈
网易NodeJS开源游戏框架pomelo访谈
0&他的粉丝
日. 估计阅读时间:
硅谷人工智能、机器学习、互联网金融、未来移动技术架构 ,
Author Contacted
语言 & 开发
25 他的粉丝
架构 & 设计
168 他的粉丝
49 他的粉丝
1 他的粉丝
19 他的粉丝
0 他的粉丝
20 他的粉丝
游戏服务器
0 他的粉丝
0 他的粉丝
相关厂商内容
相关赞助商
告诉我们您的想法
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p
当有人回复此评论时请E-mail通知我
赞助商链接
架构 & 设计
文化 & 方法
<及所有内容,版权所有 &#169;
C4Media Inc.
服务器由 提供, 我们最信赖的ISP伙伴。
北京创新网媒广告有限公司
京ICP备号-7
找回密码....
InfoQ账号使用的E-mail
关注你最喜爱的话题和作者
快速浏览网站内你所感兴趣话题的精选内容。
内容自由定制
选择想要阅读的主题和喜爱的作者定制自己的新闻源。
设置通知机制以获取内容更新对您而言是否重要
注意:如果要修改您的邮箱,我们将会发送确认邮件到您原来的邮箱。
使用现有的公司名称
修改公司名称为:
公司性质:
使用现有的公司性质
修改公司性质为:
使用现有的公司规模
修改公司规模为:
使用现在的国家
使用现在的省份
Subscribe to our newsletter?
Subscribe to our industry email notices?
我们发现您在使用ad blocker。
我们理解您使用ad blocker的初衷,但为了保证InfoQ能够继续以免费方式为您服务,我们需要您的支持。InfoQ绝不会在未经您许可的情况下将您的数据提供给第三方。我们仅将其用于向读者发送相关广告内容。请您将InfoQ添加至白名单,感谢您的理解与支持。}

我要回帖

更多关于 golang 开源框架 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信