博客好久没打理了,今天有时间,把在公司wiki上写的一些东西移植一下吧
我们的游戏至今已经上线第四个同步玩法了
有点想法,也有些疑惑,在这里发一下,欢迎各位tx各抒己见
准确点说,这里所谓的“同步服务器”其实包括两个部分的内容,第一是说明通信方式是长连接,第二是服务器不具有动态扩容的能力,也就是说想增加用户数不能通过增加机器的方式来做
当然,同步服务器按道理说只包含第一部分的内容,但在这里算是一个特殊的语境吧
1.区别(主要区别于普通的web服务器)
a.通信模式很显然的,不多说了
b.冲突的解决方式
(这里的特殊语境,是指做游戏常用的数据库:腾讯的cmem,redis)
现在我所知道的冲突解决方案有这么几种
一致性缓存锁:这种锁的劣势是没有普通锁的notify机制,也就是说,必须事先加锁,锁失败了只能退出,一些在逻辑中间的事务性操作用这种方式就不能实现了
一致性缓存cas:cas是cpu操作原语,也就是compare and swap,通常在一致性缓存中是基于乐观锁的方式(对比版本号)来实现的
redis作者曾说了这种方式性能是非常不好的,但是如果我们在程序逻辑做一些优化,也未尝不可
普通锁:这种锁也不好:很不优雅,必须将逻辑框在一个个的try finally中,而且容易出错,而且一旦在逻辑中作为一个常态出现了,那么就不得不把整个逻辑当做了一个巨大的耦合体(除非规范定得很好,能将锁分离,但大部分情况下貌似很难,起码我做不到)
cpu cas:比较推荐这种方式,优点很明显,风险低,效率高,缺点也很明显,通常cas只能用于解决单个变量的冲突,一旦涉及到了多个变量,代码就很难写了
同步服务器比较偏向于使用后两种,而普通的web则一般只会用前两种
c.思维方式
这方面其实我一直都没想透
比如通常我们写功能都习惯于使用请求响应模式,但显然这种模式用户体验是偏差的
实际应用中,同步服务器其实能给予更好的用户体验,也就是由服务器去驱动一些事件,注意,这里说的是事件
也就是说服务端给前端返回的不是状态了,而是事件,去驱动前端
虽然写了第四个了,但是由于种种原因,一直都逃离不开请求响应模式,主要不知道前端应该怎么改变它的架构
只是在局部做了一些服务器驱动的功能
2.协议
(指的是flash做客户端,java做服务器端的特殊场景)
由于个人经验也不是太足,这里只讨论两种协议,protobuf跟amf,而也只考虑跟flash进行交互
之前仔细斟酌过amf好还是protobuf好的问题
首先先做一个对比
数据大小:
protobuf无疑是最小的,除了数据,它只多了一个类型编号,跟一个位置索引,当然,该压缩的都压缩了
amf:amf对数据也会做压缩,而对string还会进行重用(这点有可能如果传输大量的类似的文本信息,amf的压缩比会更高),编码方式跟protobuf差别不大
但是有一点很致命,它会将对象的类型信息加进去,包括变量名等信息,也就是说,如果是数组,可能会好一点,如果是每个对象只用一次,传n个对象,无疑这部分的数据量是很大的
效率:
由于游戏服务器基本都是出流量远远高于入流量,这里只考虑服务器向客户端发的情况
protobuf用的方式是生成代码,而amf是反射,虽然没做具体的测试,但无疑,差距应该是很大的,由于是同步服务器一般给前端发的都是短消息,频度高
易用性:
flash默认兼容amf协议,从通道中可以直接简单地解析出对象,非常方便,protobuf则需要编写文件,生成代码,重新编译,数据转换,等等
但是否amf真的完胜了?
经过与我们的首席架构师跟前端的讨论,其实不是这样的
同步服务器一般需要比普通的web更严谨的编码风格,在协议上也是这样的
protobuf定义了前后端交互的协议,非常明确,再也不需要前端debug,查看这样的方式,也就是说,即使我们用amf,我们也需要一份这样的协议,而且是纯手工写的(如一样的dto),个人觉得,会比protobuf产生的更麻烦
当然,为了使用protobuf,还需要一些额外的编码,但这些是一次性的
一比较之下,显然protobuf更好,更优秀,但如果是非常简单的应用,用amf也未尝不可
再补充一点
最近发现前端非常依赖于数据,归根到底其实是amf惹的祸,因为amf返回给前端的是一个动态对象,所以前端想要知道对象里面的值,都习惯性的debug,所以每次,都必须得后端写完,提供数据,前端才能开始做一些事情
这样的前后端合作模式显然是有问题的
相对而言,protobuf会给他们生成一个类文件,对象里面的变量都是确定的,能一定程度上的改变前端这个坏习惯
3.业务架构
现在4个同步项目的业务架构,都沿用了三国里面的面向服务的架构方式,也就是service,bo,这样的方式,在现在所写的4种业务中,这样的方式挺好用的
大体的区别是:
service后面默认都添加了一个参数:“连接上下文”
增加了两个配置文件
把返回的map去掉了,返回数据通过“连接上下文”发送
多了一种叫task的东西,跟bo同一层次,是一种主动运行的事件(这到底在我们业务模型里面应该是一个什么东西呢?之前考虑过让他居于服务层,让他去调用服务,但貌似也不好,因为task调用的逻辑与前端调用的逻辑没有任何地方可重用的,而且会破坏endpoint调用service的方式)
现在有一个问题是:这样的架构如果用于复杂的游戏,例如mmo,能不能用,可用性怎么样?
我们知道,像我们社交游戏的业务,都有一个特点,层次简单,比如过:用户,下一层是兵营,将领,客栈……都处于同一层次上,就没有更深入的层次了
然而复杂的游戏,显然会有很多层,比如说之前写的同步战棋战场,整个服务器有多个战场房间,战场包含着小据点,据点中又包含用户,用户带着将领,都是一层嵌套一层的,这就会我们拿数据的时候,每一个service都需要一层一层地找到数据,然后操作,我们看到的也许就是多个大bo,我们写方法可能都是Abo.doSomething,然后Abo又在方法内调Bbo,这样其实是挺不好的
还有一点,越复杂的业务,task的逻辑就会越多,最后task会越来越多,越来越乱
跟我们的首席架构师多次讨论过这个问题,虽然看法不一致,但我还是觉得,这种业务模型应该还是适用的,起码在有新的方式之前,个人感觉还是利大于弊的
4.异常
在同步服务器中,异常的控制很关键,必须考虑所有可能的情况,定义异常,并捕获,比如之前我在写cas避免冲突的时候,考虑到必须限制cas的次数,否则会造成数据库压力,但是当cas连续失败多次之后,怎么办呢?
以前是直接抛出一个异常,就不管了
但显然,在同步服务器中,这是有严重问题的
我们之所以用同步的方式,除了数据及时性,有一个很重要的部分:通常我们需要写的业务存在着大量的数据竞争。显然用非同步服务器来解决冲突是很困难,并且很不靠谱的一件事,它往往只适合数据分离的业务。
基于这一点,我们如果也像之前一样,抛出一个异常,那很可能会引起数据的不一致,然后是迅速地连锁反应,蔓延,相对而言,我们普通的业务对数据一致性的要求低很多,因为影响的最多是1,2个用户而已
5.同步模型
同步1v1,3v3,老-虎-机用的方式都是房间内单线程,将同步相关的操作封装在了线程池内
国战用的则是锁,所有都是显式加锁,写得很麻烦,而且不好看
总的来说,能不用锁最好还是不用的好,房间内单线程模型,既不用考虑可见性,也不用考虑冲突,而且可以没有限制地使用jdk的集合类,相对起来编码简单很多,房间内操作在锁的层次基本没有任何的耦合,而且不容易错,之前也考虑过,如果写复杂的游戏,也许我们可以把所有场景都抽象成一个个房间,这样,我们只需要考虑房间之间的切换就可以了,然后其他的都是房间内操作,这样的话,我们大部分业务都不需要考虑同步问题了
6.服务器组
我们知道,单服,又不可扩容,对游戏的限制是很大的,于是,有了服务器组的实现(现在做的新游戏原计划是做多区多服的,全部请求都用长连接实现(最后改变了初衷))
所以我们一个区,其实会需求一个服务器组,按业务去划分,比如说:场景1服务器,场景2服务器,交易服务器,战斗服务器,用户状态服务器,等
这其实会有个很关键的需求:网关服务器
既然用了java,肯定希望要用就用全套的,网关服务器也不会考虑用c的实现了
大家都说java比c慢,但慢多少?大家都没有个准确的说法,网上的文章看了几篇,不是测试错误就是检测方法有问题,没有可参照性
按之前在做消息服务器时,与我们的架构师tx做的c版本的比较
c版本:单线程,cpu100%,极限大概是32000qps
java版本:4核多线程,cpu60%-70%,极限大概是68000qps
如果按这个看的话,其实没有太大的区别(个人认为,如果每组能撑10w同时在线,那改为撑7,8w,也不是什么大不了的事情,也就是说性能如果没达到150%,可以忽略不计)
后来也试着在内网做了下压力测试,可是没把服务器压死,先把公司的路由器压死了,后来就没测了
出于这个计划,仔细研究了下mina,netty(还sb兮兮去看了下的游戏开源服务器darkstar,想去看看别人怎么设计网关服务器的,谁知道就一个分布式的业务框架,跟游戏没一毛钱的关系)
发现一个问题,在decoder的时候,mina都会将byte[]从directbuff拷贝一遍到heapbuff中(而且这块代码是写死的,很难动)
如果我们用netty或者mina做这个网关服务器,无疑,我们的做法大部分应该是将byte[]从入口拷贝到出口去,然后发送,这样就会涉及到byte[]的2次拷贝,相当于netty和mina中做的大量的细节优化,都被这简单的两次拷贝给抹杀了
当试着去修改netty的源码时,资料片改为了用类似普通社交的玩法实现,这个计划就不了了之了
之后也去问了下别的公司的开发者(java的),都是说现在这浮躁的网页游戏行业很少有服务器组的实现了,都是单服务器,撑3,5千人就差不多了
c++的代码很多这样的源码,像传奇,魔兽世界,等等,java难道做不了么?
7.时间问题
在同步服务器中,时间是个很恶心的东西,因为客户端是有渲染时间的,但后端没有时间的概念, 后端是按事件去触发,去响应的,
举个简单的例子,一个简单的限制,A从x点移动到y点,时间,距离,后端其实是需要检测的,不然就各种外挂,但是如果前端每走一步又跟后端请求一遍,玩家会疯掉的
还有像资料片中的连招的释放,你必须在固定时间内按键,才算正确,又还有国战中我们需要按各自战斗时间决定排队顺序(谁跟谁打,什么时候打)
关于移动网上有的是各式各样的算法,这里就不罗嗦了
说一下在国战中和在资料片中是怎么解决这个问题的
(待续)
分享到:
相关推荐
标题中的“网络游戏-可利用无线网络连接到邮件服务器和利用本地链路同步连接到PC的手持式装置”指的是一个特定的技术方案,它涉及到网络游戏、无线网络通信、邮件服务器交互以及手持设备与个人计算机(PC)之间的...
《网络游戏-基于Web+Element机制的微博与社交网络信息同步系统与方法》是一个关于现代网络游戏与社交媒体信息同步的深入探讨。这个压缩包包含的核心文件是“基于Web+Element机制的微博与社交网络信息同步系统与方法....
本文将详细探讨网络游戏中的线上线下游戏连接方法、装置、系统和服务器的相关知识点,旨在帮助读者理解这一复杂而精彩的技术领域。 首先,我们要明白网络游戏的基本构成。网络游戏的核心是服务器,它是游戏世界的...
标题中的“网络游戏-用于基于计算机的社交网络的设备之间的路由的方法和服务器”表明了这个主题主要涉及网络游戏领域,特别是与计算机社交网络相关的设备间通信技术。这个话题涵盖了几大关键知识点,包括网络游戏、...
在社交游戏中部署这种分布式缓存,不仅能够提升数据访问速度,还能在服务器出现故障时,快速实现数据的恢复和重建,保证了游戏的高可用性和稳定性。 综上所述,分布式Memcached技术为社交游戏服务器端的高负载问题...
《网络游戏-社交网络信息流的显示方法、装置及服务器》这一资料主要探讨的是网络游戏与社交网络结合中的一个重要问题,即如何有效地展示社交网络中的信息流,以提升用户体验和互动性。这一主题涉及到多个IT领域的...
网络服务器在游戏行业中扮演着至关重要的角色,它负责处理玩家的交互数据、游戏状态同步、逻辑运算以及存储玩家信息等多种任务。让我们深入探讨网络游戏中的多功能网络服务器。 一、服务器架构 1. C/S架构:客户端...
4. **游戏状态同步**:在网络游戏中,服务器需要同步所有玩家的游戏状态,确保每一步棋的合法性。这通常通过状态机和一致性算法(如乐观锁或MVCC)来实现。 5. **匹配与对战系统**:服务器需要设计匹配算法,将玩家...
网络游戏服务器不仅要能够处理大量的并发连接,保证数据的准确性和一致性,同时还需要具备良好的扩展性和稳定性。 Java语言由于其跨平台、对象导向等特性,成为了开发网络游戏服务器的一个流行选择。Java虚拟机...
在网络游戏领域,游戏系统、服务器装置以及控制方法是构建稳定且高效游戏环境的关键要素。这份“网络游戏-游戏系统、服务器装置以及控制方法”的资料详细探讨了这些关键知识点,旨在为开发者提供深入的理解和实践...
服务器是连接所有玩家的中枢,负责处理游戏数据的交换、存储玩家进度、实现多人在线同步游戏。服务器系统的稳定性、安全性和可扩展性至关重要,因为它们直接影响到游戏的运行质量和玩家的满意度。此外,服务器还需要...
4. **地图服务器**:负责游戏世界中不同区域的地图逻辑,管理玩家的位置和移动,同步玩家之间的交互,以及与逻辑地图服务器的数据同步。 5. **角色服务器**:处理特定角色的操作,如角色创建、删除、属性更新等,...
Go语言以其高效的并发处理和轻量级线程(goroutines)而闻名,这在处理大量并发连接的场景中尤其有用,如多人在线游戏。 Nakama的核心特性包括: 1. **实时通信**:Nakama支持WebSocket和HTTP协议,允许用户进行低...
网络游戏是当今数字时代的一种热门娱乐形式,它将成千上万的玩家聚集在一起,共同体验虚拟世界中的冒险、竞技和社交。"通过网络将设备耦合到管理服务器的方法"是网络游戏实现这一壮丽景象的关键技术之一。在此,我们...
数据互通,简单来说,就是让不同服务器的玩家能够在一个统一的环境中交互,打破服务器之间的壁垒,提高游戏的社交性和趣味性。本资料主要探讨了游戏服务器的数据互通方法与装置,以下将详细阐述这一主题。 首先,...
在Android平台上,开发一个应用程序来连接服务器并读取联系人信息是一个常见的需求,尤其是在构建社交应用或者需要同步用户数据的场景下。这个过程涉及到多个关键的技术点,包括网络通信、数据解析、权限管理以及...
10. **游戏服务器架构**:服务器端可能包含多个子系统,如游戏逻辑服务器、计费服务器、社交服务器等,它们协同工作以支持整个游戏的运行。 总结来说,网络游戏在多机种IP网络中的通信涉及网络协议选择、跨平台开发...
然后,需要创建端点来实现主备连接,用于数据的传输和同步。 在主机和备机上,需要创建LOGIN和USER来实现身份验证和权限控制。同时,需要备份证书来实现互换主机和备机的证书。最后,需要将主机和备机的证书复制到...
- C/S模式中,服务器是中央权威,所有操作通过服务器转发,保证游戏世界的同步和公平。 - P2P模式下,玩家之间直接通信,服务器主要负责协调和验证,降低服务器压力,但可能增加网络延迟问题。 4. **终端设备**:...
其次,服务器在联网游戏中起着至关重要的作用,它是连接所有玩家的桥梁。游戏服务器需要处理玩家的交互数据,如角色动作、战斗结果、交易信息等,并实时同步到所有相关玩家,确保游戏世界的公平性和一致性。服务器...