正文
通过Global server提供路由策略,负载均衡策略,分组策略。具备 Failfast 能力,保障RPC服务一定程度的高可用。
连接池在设计过程中,比较重要的是要考虑请求的顺序性,也就是先请求的先完成。如果玩家的跨服请求通过不同的RPC连接并发执行,就有可能单个玩家请求因错序而导致逻辑矛盾,比如玩家移动,见图2:
玩家移动是很频繁的,如果A请求让玩家从位置1移动到位置2,B请求从位置2移动到位置3,有可能B请求先被跨服接收处理,这就会产生逻辑问题。
那么,如何做到请求的有序性呢?其本质是让同一份数据的访问能串行化,方法就是让同一个玩家的跨服请求通过同一条RPC连接执行,加上逻辑上的有效性验证,如图3所示:
限于篇幅,这里只讲同步请求的RPC连接池实现。同步请求的时序图如图所示:
上图为进入跨服战场的一次同步请求,场景切换控制器StageControllAction发起进入跨服战场的请求applyChangeByBattlefield(),场景管理器StageControllManager首先要调用登录跨服的RPC请求GameRpcClient.loginCrossServer(LoginCrossServerReq),跨服RPC请求的工作流是这样的:
该请求第一步先从连接池里获取一个连接RpcClient rpcClient = rpcClientPool.getResource(roleId),然后发起一个同步请求RpcClient.sendWithReturn(),等待直到结果返回,然后把资源归还连接池。
我们重点来看看sendWithReturn代码实现:
测试场景为分别在连接数在1,8,并发数1,8,数据大小在22byte,94byte,2504byte情况下,做测试,消息同步传输,原样返回,以下是针对同步请求压力测试的结果(取均值):
由于我们的游戏服务器和跨服服务器代码基本一致,所以只要能在跨服中获得游戏功能所要的数据,那么,就能完成任何原有的功能,并且改造成本基本为零,我们选择了被动拉取。
这里要提出一个概念:数据源的相对性。
提供数据方,C向B请求一份数据,B是C的数据源,B向A请求一份数据,A是B的数据源。
一个玩家跨服过去后,往游戏原服拉取数据的细节图如图: