RPC原理

服务调用

由于各服务部署在不同机器,服务间的调用免不了网络通信过程,服务消费方每调用一个服务都要写一坨网络通信相关的代码,不仅复杂而且极易出错。
如果有一种方式能让我们像调用本地服务一样调用远程服务,并且让调用者对网络通信这些细节透明,那么将大大提高生产力,比如服务消费方在调用本地 的一个接口时,实质上调用的是远端的服务。这种方式其实就是RPC(Remote Procedure Call Protocol),如今rpc在各大互联网公司中被广泛使用,如阿里巴巴的hsf、dubbo(开源)、Facebook的thrift(开源)、Google grpc(开源)、Twitter的finagle(开源)等。当然,也可以通过HTTP + JSON的方式来进行服务间的调用,本质上HTTP的方式也是属于RPC的一种实现,但是HTTP的方式并不会像调用本地服务一样那么直观,同时也有一定的性能问题。
服务调用方式
服务的调用方式,主要有三种:
同步服务调用:最常见、简单的服务调用,即同步等待服务方返回。为了防止服务端长时间不返回应答消息导致客户端线程被挂死,用户线程等待的时候需要设置超时时间。
异步服务调用:异步服务调用有两种实现方式:一种是只通过Future来实现,还有一种是通过构造Listener对象并将其添加到Future中,用于服务端应答的异步回调。通过Future方式时,线程会阻塞在get结果的操作上;而使用Listener的方式是监听器异步的获取执行结果。
并行服务调用:提升服务调用的并行度,降低时延。比如在结算时,会分别调用短信通知服务,订单详细服务,经验增长服务等等。这些服务即可通过并行服务调用来降低端到端的时延,最后只需对执行结果进行汇聚即可。并行服务最常见的技术实现方案是使用Fork/Join框架实现子任务的并行执行和结果汇聚。

RPC通信细节

要让网络通信细节对使用者透明,我们需要对通信细节进行封装,我们先看下一个RPC调用的流程涉及到哪些通信细节:

  • 服务消费方(client)调用以本地调用方式调用服务;
  • client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
  • client stub找到服务地址,并将消息发送到服务端;
  • server stub收到消息后进行解码;
  • server stub根据解码结果调用本地的服务;
  • 本地服务执行并将结果返回给server stub;
  • server stub将返回结果打包成消息并发送至消费方;
  • client stub接收到消息,并进行解码;
  • 服务消费方得到最终结果。
    RPC的目标就是要2~8这些步骤都封装起来,让用户对这些细节透明。有以下的一些技术细节:
  • 如何做到透明化远程过程调用:使用代理,代理分为两种:1. jdk 动态代理 2.字节码生成。jdk代理的方式是对接口做代理,所以必须先定义接口;字节码生成方式一般使用的是cglib代理,cglib代理使用的是asm字节码框架,可以直接对类生成代理对象;虽然字节码生成的方式更加方便和高效,但是由于代码维护不易,一般还是采取jdk动态代理的方式。
  • 消息的数据结构:通信的第一步就是要确认客户端和服务端相互通信的消息结构
    客户端的请求消息一般需要包括以下内容:
  • 接口名称:用于确定调用哪个接口
  • 方法名:确定调用接口中哪个方法
  • 参数类型&参数值:
  • 超时时间
  • requestID:请求唯一标识

服务器返回消息一般需要包括:

  1. 返回值
  2. 状态code
  3. requestID
  • 序列化:序列化类型包括基于文本和基于二进制方式。在分布式服务通信框架中,序列化方式应该包含以下特性:

    • 通用性:比如能否支持Map等复杂数据结构
    • 性能:包括时间复杂度和空间复杂度,通信框架被会公司全部服务使用,即使性能提升一点也会引起质变
    • 可扩展性:比如支持自动增加新的业务字段
    • 多语言支持:通过定义idl,生成方式为静态编译和动态编译
  • 通信:通信框架需要支持同步(BIO)和异步(NIO)方式,一般底层使用Netty

  • RequestID:如果请求时异步的,对于客户端来说请求发出后线程即可向下执行。服务端处理完成后再以消息的形式发送给客户端。于是这里会出现以下两个问题:

    • 如何让当前线程“暂停”,等待到结果后,再向后执行
    • 如果多个线程同时进行远程方法调用,这时建立在client server之间的socket连接上会有很多双方发送的消息传递,前后顺序也可能是随机的,server处理完结果后将结果发送给client,client收到很多的消息,怎么知道哪个消息是原先哪个线程调用的?

    这时即可通过唯一自增的一个RequestID来解决这两个问题:

    • 在调用callback的get方法时,在get内部获取callback的锁,如果没有获取就等待
    • 以RequestID为Key将callback对象存放在全局ConcurrentHashMap中,先通过RequestID获取callback对象,然后再获取callback的锁,获取之后再调用notify
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容