RPC和Dubbo简介

RPC协议

RPC:远程过程调用,原则上来说系统间跨进程的调用都属于RPC范畴

RMI/HTTP/dubbo/Spring Cloud/thrift

RPC框架如何实现分布式环境下的远程调用

在一个典型的RPC的使用场景中,包含了服务发现,负载,容错,网络传输,序列化等组件,其中RPC协议指明了程序如何进行网络传输和序列化。


RPC协议的组成

RPC协议的组成

1. 地址:服务提供者地址

2.端口:协议指定开放的端口

3.报文编码:协议报文编码,分为请求头和请求体两部分

4.序列化方式:将请求体序列化成对象,具体的方式有Hessian2Serialization,DubboSerialization,JavaSerialization,JsonSerization等

5.运行服务:网络传输实现,实现方式主要有netty,mina,RMI服务,Servlet容器(jetty,tomcat,jboss)

RPC协议报文编码与实现

RPC传输实现

基于TCP/IP作为基础使用Socket或Netty或者Mina等网络编程组件实现。TCP是面向字节流的无边界协议,其只管负责数据传输并不会区分每次请求锁对应的消息,这样就会出现TCP协议中的拆包和粘包的问题。

粘包的原因:TCP协议中发送端和接收端都会有缓冲区

粘包的解决办法:(1)消息固定长度(2)基于特殊字符进行标识分割(3)使用带消息头的协议,消息头中标识消息体的大小,然后根据长度去读取消息的内容,类似于HTTP协议中的content-length

Dubbo支持的协议

Dubbo框架支持dubbo、rmi、hessian、http、webservice、thrift、redis等多种协议,但是Dubbo官网是推荐我们使用Dubbo协议的,采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。Hessian底层采用HTTP通讯(同步),采用Servlet暴露服务。适用于传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。下面重点介绍Dubbo协议:

Dubbo协议头格式

如上图可知header总包含了16个字节的数据,其中前两个字节为魔数,类似Class类文件里面的作用,这里用来标识一个帧的开始,固定为0xdabb其中第一个字节固定为0xda,第二个字节固定为0xbb

后面紧这的一个字节是请求和序列化标记的组合结果requstflag|serializationId。其中高四位表示请求的requstflag,低四位是序列化的方式:

DubboSerialization:0001

FastJsonSerialization:0110

Hessian2Serialization:0010

JavaSerialization:0011

response status:是响应报文里面才设置(请求报文里面不设置),用来标识响应的结果码

request id:消息请求ID,long类型,每一个请求的唯一识别id(采用异步通讯的方式,用来把请求request和返回的response对应上)

body length:消息体body长度,int类型

Dubbo简介

Dubbo提供了三个关键功能:基于接口的远程调用,容错与负载均衡,服务自动注册与发现。

Dubbo的结构图

节点角色说明

      Provider: 暴露服务的服务提供方。

      Consumer: 调用远程服务的服务消费方。

      Registry: 服务注册与发现的注册中心。

      Monitor: 统计服务的调用次调和调用时间的监控中心。

      Container: 服务运行容器。

这点我觉得非常好,角色分明,可以根据每个节点角色的状态来确定该服务是否正常。

调用关系说明

0. 服务容器负责启动,加载,运行服务提供者。

1. 服务提供者在启动时,向注册中心注册自己提供的服务。

2. 服务消费者在启动时,向注册中心订阅自己所需的服务。

3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

连通性

1. 注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小

2. 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示

3. 服务提供者向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销

4. 服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,同时汇报调用时间到监控中心,此时间包含网络开销

5. 注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外

6. 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者

7. 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表

8. 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者

健壮性

1. 监控中心宕掉不影响使用,只是丢失部分采样数据

2. 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务

3. 注册中心对等集群,任意一台宕掉后,将自动切换到另一台

4. 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯

5. 服务提供者无状态,任意一台宕掉后,不影响使用

6. 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

Dubbo模型


Transporter:mina, netty, grizzy

Serialization:dubbo, hessian2, java, json

Dispatcher:all, direct, message, execution, connection

ThreadPool:fixed, cached

特点:Dubbo缺省协议采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。

缺点:Dubbo缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。

Dubbo协议

缺省协议,使用基于mina1.1.7+hessian3.2.1的tbremoting交互。

连接个数:单连接

连接方式:长连接

传输协议:TCP

传输方式:NIO异步传输

序列化:Hessian二进制序列化

适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大文件或超大字符串。

适用场景:常规远程服务方法调用

线程模型

首先明确一个基本概念:IO线程和业务线程的区别

IO线程:配置在netty连接点的用于处理网络数据的线程,主要处理编解码等直接与网络数据打交道的事件。Dubbo默认的底层网络通讯使用的是Netty,服务提供方NettyServer使用两级线程池,其中EventLoopGroup(boss)主要用来接受客户端的链接请求,并把接受的请求分发给EventLoopGroup(worker) 来处理,boss和worker线程组我们称之为IO线程。

业务线程:用于处理具体业务逻辑的线程,可以理解为自己在provider上写的代码所执行的线程环境。

事件处理线程说明

如果事件处理的逻辑能迅速完成,并且不会发起新的IO请求,比如只是在内存中记个标识,则直接在IO线程上处理更快,因为减少了线程池调度。

但如果事件处理逻辑较慢,或者需要发起新的IO请求,比如需要查询数据库,则必须派发到线程池,否则IO线程阻塞,将导致不能接收其它请求。

如果用IO线程处理事件,又在事件处理过程中发起新的IO请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。

Dispatcher

all 所有消息都派发到线程池,包括请求/响应/连接事件/断开事件/心跳等。

direct 所有消息都不派发到线程池,全部在IO线程上直接执行。

message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在IO线程上执行。

execution 只将请求消息派发到线程池,响应消息和其它连接断开事件,心跳等消息,直接在IO线程上执行。

connection 在IO线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。

ThreadPool

fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)

cached 缓存线程池,空闲一分钟自动删除,需要时重建。

limited 可伸缩线程池,但池中的线程数只会增长不会收缩。(为避免收缩时突然来了大流量引起的性能问题)。配置如下:

<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />

线程模型其他相关参数

iothreads:指定IO线程池(worker)的线程数量,默认情况下为CPU个数+1,因为这个线程的工作内容比较简单,所以一般情况下我们不会去配置这个值,除非IO线程的响应速度明显拖慢了整个工程的响应,IO线程的默认类型是CacheThreadPool,一分钟的线程死亡时间。

threadpool:业务线程的具体线程类型,默认采用的fixed线程池,即线程数量一定的线程池,这种线程池的好处就是不会频繁创建线程线程,适合线业务比较密集的应用。因为这个数据只管关系到服务的并发情况,所以在需要的时候可以适当调整该数量来增加工程的并发。

threads:该参数就是业务线程池的核心线程数配置,默认情况下为200。如果空间有条件的话可以适当地提升该数量,例如提升至400或者500都是可以的。

queues:该数量指定来在初始化业务线程池时候是否需要排队队列,如果不设置的话,业务线程池的排队队列是SynchronousQueue,即不允许业务事件排队,如果线程池没有空闲线程之后会直接排除异常信息。但是如果配置来queues之后则会使用LinkedBlockingQueue作为排队队列,queues则代表队列的初始队列。因为queues的配置直接关系到排队,所以在一般情况下建议不要配置,因为线程池满的情况下一般期望是直接失败,然后调用其他的机器,而不是再次队列继续等待,继续等待不仅可能会拉低响应时间,而且很有可能会超时。

acceptes:我们知道threadpool,threads和queues都是控制业务线程池的字段,而acceptes就是控制IO线程池的字段。这个字段标示着服务端可接受的最大长连接数,默认情况下为不限制,但是有时候为来保护服务器防止连接数过多导致请求失败率过高,则可以考虑设置该字段为一个定值。

connections:既然服务端可以设置最大接收的连接数,那么客户端也可以设置与服务端建立的连接数。connections可以配置在reference上表示要同对应的服务器建立的长链接数量,默认为只建立一条链接,如果配置来connections的话则会建立N条长链接以提供消费者的吞吐量。但是有一点需要注意是如果conenctions的数量配置大于服务端的accepts的话,超出的部分会直接报错,表示不支持更多的链接,该值不宜配置过多,因为如果多个消费者都配置来该值的话很容易到值服务端的accepts超过预期数量而报错。


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

推荐阅读更多精彩内容