在这部分,我们将讨论关于rpc调用相关的问题。在pomelo中rpc的调用主要是通过proxy组件和remote组件实现,其中proxy组件主要负责创建rpc客户端代理,让开发者在pomelo中更方便地进行rpc调用;remote组件主要负责加载rpc服务,包括系统的rpc服务和用户的rpc服务。Pomelo的rpc框架主要解决了两个问题,第一个就是进程间的路由策略,第二个则是rpc底层的通信协议的选择。对于第一个问题,pomelo提供了一套灵活的路由机制,并允许开发者根据需要自由地控制路由信息;对于第二个问题,pomelo现在支持基于socket.io的通信机制和基于原生socket的通信机制。下面我们就分别介绍rpc客户端和服务端的具体实现:

RPC客户端

rpc客户端主要负责产生代理对象,加载路由策略和进行消息的转发。

proxy组件

在进行pomelo开发的过程中,进行rpc调用的代码如下:

app.rpc.chat.chatRemote.add(session, uid, serverId, param, cb);

在pomelo中之所以能够如此简洁地进行rpc调用是因为javascript的语言特性和pomelo底层对rpc客户端进行的封装。proxy组件在启动时首先会生成一个rpc client,同时监听系统中服务器增加、服务器移除、服务器替换事件;当这些事件被触发时,proxy组件会根据相应的事件信息对服务器代理对象进行相应的动态变化。例如,当有新的服务器增加时,proxy组件会增加该服务器的代理对象;当有服务器被移除后,proxy组件会移除该服务器的代理对象。在proxy组件启动完成时会将rpc client生成的代理对象挂载到app.rpc下,这样开发者在进行rpc调用时就可以匹配到对应的代理对象,从而通过rpc client进行相应的rpc调用。

RPC client

对于rpc client,其整体架构图如下所示:

在最底层,使用mail box的抽象隐藏了底层通讯协议的细节。一个mail box对应一个远程服务器的连接。Mail box对上提供了统一的接口,如:连接,发送,关闭等。Mail box内部则可以提供不同的实现,包括底层的传输协议,消息缓冲队列,传输数据的包装等。开发者可以根据实际需要,实现不同的mail box,来满足不同的底层协议的需求。现在pomelo提供基于socket.io的mail box和基于原生socket的mail box,默认使用socket.io。

在mail box上面,是mail station层,负责管理底层所有mail box实例的创建和销毁,以及对上层提供统一的消息分发接口。上层代码只要传递一个目标mail box的id,mail station则可以知道如何通过底层相应的mail box实例将这个消息发送出去。开发者可以给mail station传递一个mail box的工厂方法,即可以定制底层的mail box实例的创建过程了,比如:连接到某个服务器,使用某一类型的mail box,而其他的服务器,则使用另外一个类型的mail box。

再往上的是路由层。路由层的主要工作就是提供消息路由的算法。路由函数是可以从外面定制的,开发者通过注入自定义的路由函数来实现自己的路由策略。每个rpc消息分发前,都会调用路由函数进行路由计算。容器会提供与该rpc相关的玩家会话对象(当中包含了该玩家当前的状态)和rpc的描述消息(包含了rpc的具体信息),通过这两个对象,即可做出路由的决策。路由的结果是目标mail box的id,然后传递给底下的mail station层即可。

最上面的是代理层,其主要作用是隐藏底层rpc调用的细节。Pomelo会根据远程接口生成代理对象,上层代码调用远程对象就像调用本地对象一样。但这里对远程代理对象有两个约定的规则,即第一个参数必须是相关玩家的session对象,如果没有这么一个对象可以填充null,在路由函数中需做特殊处理。还有就是最后一个参数是rpc调用结果的回调函数,调用的错误或是结果全部通过该回调函数返回,且这个参数不能省略。而在远程服务的提供端,方法的声明与代理端的声明相比,除了不需要第一个session参数,其余的参数是一样的。

rpc请求流程

对于发送rpc请求,rpc客户端采用了一种懒加载的机制,其主要实现思路是客户端与服务端的连接并不是在服务器启动后就创建,而是当客户端第一次向服务端发起rpc请求时才真正建立连接。当客户端与相应的服务端建立连接后,以后有从该客户端到对应服务端的请求就无需再建立连接,消息可以直接发送。消息的发送过程类似前面介绍的handler-filter链处理模式,同样在rpc请求过程开发者可以添加before和after filter对消息进行相应的处理,现在pomelo内建的rpc filter包括rpcLog和toobusy。

RPC服务端

rpc服务端主要负责接收客户端的rpc请求后将相应的消息转给客户端请求的rpc服务中,同时将rpc服务处理完成的消息返回给rpc客户端。

remote组件

remote组件在启动时会创建一个rpc server,同时加载系统中所有的rpc服务;remote组件在关闭时会停止rpc server的所有服务。

RPC server

对于rpc server,其整体架构图如下所示:

最底下的是acceptor层,主要负责网络监听,消息的接收和解析。Acceptor层与mail box层相对应,可以看成是网络协议栈上同一层上的两端,即从mail box层传入的消息与acceptor层上传出的消息应该是同样的内容。所以这两端的实例必须一致,使用同样的底层传输协议,对传输的数据使用同样格式进行封装。在客户端替换了mail box的实现,则在服务提供端也必须替换成对应的acceptor实现。同mail box一样,pomelo提供基于socket.io的acceptor和基于原生socket的acceptor。

往上是dispatch层。该层主要完成的工作是根据rpc描述消息将请求分发给上层的远程服务。

最上层的是远程服务层,即提供远程服务业务逻辑的地方,由pomelo框架自动加载remote代码来完成。

需要注意的地方

大部分的mailbox序列化使用的是JSON.stringfiy,当消息量过大时(使用bufferMsg时),会导致序列化过程更长,最终可能会发送失败(包太大)。同时由于超时等待时,是需要计算序列化时间的,所以这个超时有可能在消息量较大的情况下直接就在本地发生(内存存在泄漏,并且超时消息会没法取消)。

总结

在本部分,详细介绍了rpc客户端和服务端的通信机制,包括对mail box、mail station、acceptor、gateway的功能进行了阐述,同时分析了pomelo中proxy组件和remote组件的相关功能。

框架分析--proxy组件、remote组件与rpc调用原理相关推荐

  1. Dubbo——远程(RPC)调用原理

    摘要 服务暴露和服务引入两个流程了,而这两个流程就是为了服务的调用,本博文将详细的介绍Dubbo的服务调用流程. PRC架构组件 一个基本的RPC架构里面应该至少包含以下4个组件: 客户端(Clien ...

  2. 深入剖析通信层和RPC调用的异步化(上)

    <Netty 进阶之路>.<分布式服务框架原理与实践>作者李林锋深入剖析通信层和 RPC 调用的异步化.李林锋此后还将在 InfoQ 上开设 Netty 专题持续出稿,感兴趣的 ...

  3. 8.10Dubbo框架里的微服务组件

    title date comments categories tags permalink Dubbo框架里的微服务组件 2020/4/28 true 微服务 微服务 8.10 今天以开源微服务框架 ...

  4. RPC调用框架比较分析--转载

    原文地址:http://itindex.net/detail/52530-rpc-%E6%A1%86%E6%9E%B6-%E5%88%86%E6%9E%90 什么是RPC:  RPC(Remote P ...

  5. RPC调用框架比较分析

    什么是RPC: RPC(Remote Procedure Call Protocol)--远程过程调用协议,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议. 简言之,RPC ...

  6. ORM映射框架总结--SQL 语句生成组件

    1.       SQL 语句生成组建 之前说过ORM框架中有一个非常重要的组件,那就是SQL语句生成组件.SQL语句生成组件,顾名思义就是用于生成sql语句的一个组件.之前的Attribute 是用 ...

  7. Python爬虫框架scrapy的用途及组件认识

    Python爬虫框架scrapy的用途及组件认识 今天简述一下Scrapy框架的大致处理流程,以方便大家更好的理解Scrapy的运行过程. Scrapy是一个快速.高层次屏幕抓取和web抓取pytho ...

  8. Taro框架中 Image 和 Video 组件预览图片/视频时添加明显的关闭按钮以关闭全屏预览

    需求 Taro框架中 Image 和 Video 组件预览图片/视频时 添加明显的关闭按钮 以关闭全屏观看,避免用户直接操作返回后导致页面空白(原有消息记录消失 - 重新进入项目首页) [补充] 全屏 ...

  9. 【前端框架】react框架 第四章 react组件进阶

    目录 1. 组件的props 特点 2. 组件通迅的三种方式 父组件传递数据给子组件 子组件传递数据组父组件 兄弟组件 3. Context Context使用步骤 4. props深入 props校 ...

最新文章

  1. nerdctl命令tab键补齐方法
  2. 1.5 matlab常量与变量
  3. sklearn支持gpu_Keras Sklearn随机搜索GPU OOM
  4. 我在实际工作中用的最多的 git 命令
  5. HTML5 CSS3的新交互特性
  6. 5000字权威指南分享!企业如何正确制定 IT 战略及其路线图
  7. MogoH5+基于Hbuilder做ios真机测试
  8. Markdown中的特殊符号
  9. python不调包实现sobel_python利用百度云接口实现车牌识别的示例
  10. php sqlite存入文件夹,PHP_小文件php+SQLite存储方案,我们草根站长购买的虚拟主机 - phpStudy...
  11. android表白代码大全,微信表白代码汇总:
  12. 卧槽!还有这种事!马斯克的SpaceX-API 竟然开源了!登顶GitHub热榜!
  13. linux4 系统下载,syslinux下载|
  14. 可视化看板:基于电子竞技行业数据大数据可视化分析(详细代码及图文说明)
  15. 50道MySQL面试题,掌握之后你将获得无上法力,一发不可收拾!
  16. 30个真棒的(免费iPhone,iPad IOS)的GUI 界面设计元素模板 做iphone开发的福音
  17. Live Home 3D for Mac汉化破解版永久激活方法
  18. TTS语音播报模块UNV6288的使用方法
  19. 加冕爱情的八枚梦想戒指
  20. Unable to prepare *** iPhone for development

热门文章

  1. [转载] 使用 Yubikey 加固你的系统
  2. 阿江统计拿WebShell
  3. 转载nbsp;MTK存储系统相关
  4. 刘韧:陈一舟要我成为卓有成效的管理者
  5. 解决element UI 表格el-table增加列会震动抖动的问题
  6. 湖南工学院 戴成秋 计算机,计算机与信息科学学院2021届本科毕业设计答辩实施方案...
  7. R语言中的遗传算法详细解析
  8. Delphi XE10.3.1 使用心得-2019-12-08
  9. 手把手教你撸一个小程序带太阳码的海报分享
  10. 东方财富单页tables数据爬取selenium