美文网首页
RPC和Dubbo简介

RPC和Dubbo简介

作者: 目睹了整个事件的索先生 | 来源:发表于2018-11-17 13:01 被阅读0次

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超过预期数量而报错。


相关文章

  • RPC和Dubbo简介

    RPC协议 RPC:远程过程调用,原则上来说系统间跨进程的调用都属于RPC范畴 RMI/HTTP/dubbo/Sp...

  • Dubbo 简介和实现原理

    Dubbo简介 是一个RPC框架,SOA框架RPC:支持各种传输协议,如dubbo,hession,json,fa...

  • dubbo源码分析

    dubbo源码中包简介 dubbo-rpc,rpc通讯协议的实现,其中最为核心的就是dubbo协议,以及一些业界主...

  • 基于netty手写rpc

    rpc简介 RPC是远程过程调用(Remote Procedure Call),比如Dubbo框架就是使用rpc原...

  • Dubbo(一)

    简介Dubbo是一个RPC框架 Dubbo使用的协议:dubbo://rmi://http://redis://w...

  • Apache dubbo 分布式框架(一)

    Apache Dubbo Dubbo简介 Apache Dubbo是一款高性能的Java RPC框架。其前身是阿里...

  • 01-Dubbo简介

    1.Dubbo简介: Dubbo是一个分布式,高性能,透明化的RPC服务框架(RPC:远程过程调用协议) SOA:...

  • Dubbo之初体验

    简介 Dubbo 是一款高性能Java RPC框架,官方网站:https://dubbo.apache.org/z...

  • jmeter测试dubbo接口

    一、Dubbo简介 dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服...

  • Dubbo3开发-简介和示例

    1. Dubbo3 简介 Apache Dubbo 是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两...

网友评论

      本文标题:RPC和Dubbo简介

      本文链接:https://www.haomeiwen.com/subject/ylwoiftx.html