谈谈游戏服务器中RPC模块的设计

💡 原文中文,约4300字,阅读约需11分钟。
📝

内容提要

作者回顾了十多年的RPC模块设计与使用经历,指出早期设计的不足。通过参与不同游戏开发,逐步改进RPC接口,解决了超时和请求响应区分等问题,最终提出基于workerid的新设计思路,强调了分布式系统中链接管理的抽象化。

🎯

关键要点

  • 作者回顾了十多年的RPC模块设计与使用经历,指出早期设计的不足。

  • 早期RPC设计简陋,序列化方式依赖手工编码,回调函数设计局限。

  • 超时处理机制简单,使用session字段来管理请求与响应。

  • 参与SLG游戏开发时,决定将核心玩法逻辑独立到单独进程中运行。

  • 设计新的RPC接口,修改超时功能以便处理超时后的逻辑。

  • 解决双向通信中请求与响应的区分问题,选择独立连接的方案。

  • 独立连接导致消息顺序问题,项目后期不得不绕过限制。

  • 在Go语言环境中开发RPC模块,采用消息传递方式解决跨服通信问题。

  • 通过协议ID区分请求与响应包,维护成本逐渐增加。

  • 最终通过未使用的bit位区分响应包和请求包,简化了处理逻辑。

  • 新的RPC模块设计几乎解决了以往经历中的所有痛点。

  • 反思RPC模块是否需要关注链接,探索更抽象的设计思路。

  • 为每个进程分配唯一标识workerid,重新设计RPC接口。

  • 通过抽象链接管理,将其从业务逻辑中剥离,关注workerid与业务的关系。

🔎

延伸解读

RPC模块设计的演变

作者回顾了十多年的RPC模块设计历程,强调了早期设计的局限性,如手工编码的序列化和简单的超时处理。这些不足促使作者在后续开发中不断探索和改进,最终形成了更高效的RPC接口设计,反映了技术进步对游戏开发的重要影响。

独立连接的挑战

在新的RPC设计中,作者选择了独立连接的方案以区分请求与响应,但这也带来了消息顺序的问题。在高并发场景下,消息顺序的破坏可能导致客户端与服务器之间的状态不一致,开发者需对此保持警惕,确保设计能够适应复杂的通信需求。

workerid的关键作用

作者提出为每个进程分配唯一的workerid,以重新设计RPC接口。这一设计思路不仅简化了链接管理,还将业务逻辑与底层连接状态剥离,使得分布式系统的资源调度与业务需求更加紧密结合。开发者在设计RPC模块时应考虑workerid的使用,以提升系统的灵活性和可维护性。

延伸问答

RPC模块的早期设计存在哪些不足?

早期RPC设计简陋,序列化方式依赖手工编码,回调函数设计局限,超时处理机制简单。

作者在SLG游戏开发中如何改进RPC模块?

作者将核心玩法逻辑独立到单独进程中运行,并设计新的RPC接口以简化进程间通信。

新的RPC模块设计是如何解决请求与响应区分问题的?

新的设计通过为每个进程建立独立连接来区分请求与响应,避免了消息顺序问题。

在Go语言环境中,RPC模块的设计有什么特点?

在Go语言环境中,RPC模块采用消息传递方式,设计了超时逻辑,并通过协议ID区分请求与响应包。

作者如何处理RPC模块中的超时逻辑?

作者修改超时功能,使得超时后仍调用回调函数,但参数置为nullptr,以便处理超时逻辑。

RPC模块设计中workerid的作用是什么?

workerid为每个进程分配唯一标识,决定了进程处理的特定数据范围,是数据路由与处理的关键。

🏷️

标签

➡️

继续阅读