调用关系说明
服务容器负责启动,加载,运行服务提供者。 服务提供者在启动时,向注册中心注册自己提供的服务。 服务消费者在启动时,向注册中心订阅自己所需的服务。 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。 Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。
连通性
注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示 服务提供者向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销 服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,同时汇报调用时间到监控中心,此时间包含网络开销 注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者 健状性
监控中心宕掉不影响使用,只是丢失部分采样数据 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务 注册中心对等集群,任意一台宕掉后,将自动切换到另一台 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯 服务提供者无状态,任意一台宕掉后,不影响使用 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复 伸缩性
注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心 服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者
配置覆盖关系 以 timeout 为例,显示了配置的查找顺序,其它 retries, loadbalance, actives 等类似: 法级优先,接口级次之,全局配置再次之。 如果级别一样,则消费者优先,提供者次之。 作服务的提供者,比服务使用方更清楚服务性能参数建议由服务提供方设置超时,合理的重试次数,版本号,负载均衡策略,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置。 在 Provider 配置后,Consumer 不配置则会使用Provider 的配置值,即 Provider 配置可以作为 Consumer 的缺省值 。否则,Consumer 会使用 Consumer 端的全局设置,这对于 Provider 不可控的,并且往往是不合理的Provider 上尽量多配置 Consumer 端的属性,让 Provider 实现者一开始就思考 Provider 服务特点、服务质量的问题。
配置覆盖策略 jvm启动参数 >>xml配置 >> properties配置 只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,如应用名。
集群容错cluster Failover Cluster 失败自动切换,当出现失败,重试其它服务器 。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次 Failfast Cluster 快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,如新增记录。 Failsafe Cluster 失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。 Failback Cluster 失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。 Forking Cluster 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks="2" 来设置最大并行数。 Broadcast Cluster 广播调用所有提供者,逐个调用,任意一台报错则报错 。通常用于通知所有提供者更新缓存或日志等本地资源信息。
负载均衡策略loadbalance Random LoadBalance 随机,按权重设置随机概率。在一个截面上碰撞的概率高,但调用量越大分布越均匀,且按概率使用权重后也比较均匀,有利于动态调整提供者权重。 RoundRobin LoadBalance 轮循,按公约后的权重设置轮循比率。存在慢的提供者累积请求的问题,如:第一台机器很慢,但没挂,当请求调到第一台时就卡在那,久而久之,所有请求都卡在调到第一台上。 LeastActive LoadBalance 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越⼤。 ConsistentHash LoadBalance 一致性 Hash,相同参数的请求总是发到同一提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。算法参见 http://en.wikipedia.org/wiki/Consistent_hashing缺省只对第一个参数 Hash,如果要修改,请配置 <dubbo:parameter key="hash.arguments" value="0,1" />缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key="hash.nodes" value="320" /> 一个应用可以只订阅服务,或者只注册服务 <dubbo:registry address="10.20.153.10:9090" register="false" /> <dubbo:registry id="qdRegistry" address="10.20.141.150:9090" subscribe="false" />
多协议 Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议,不同服务在性能上适用不同协议进行传输,如大数据量用短连接协议,小数据高并发用长连接协议
多注册中心 Dubbo支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。另外,注册中心是支持自定义扩展的 。 并发控制 限制 com.foo.BarService 的每个方法,服务器端并发执行(或占用线程池线程数)不能超过 10 个: <dubbo:service interface="com.foo.BarService" executes="10" /> 限制 com.foo.BarService 的每个方法,每个客户端并发执行(或占用连接的请求数)不能超过 10 个: <dubbo:service interface="com.foo.BarService" actives="10" /> 连接控制 服务端连接控制 限制服务器端接受的连接不能超过 10 个 <dubbo:provider protocol="dubbo" accepts="10" /> 客户端连接控制 限制客户端服务使用连接不能超过 10 个 <dubbo:reference interface="com.foo.BarService" connections="10" /> 延迟连接 延迟连接用于减少长连接数。当有调用发起时,再创建长连接。 <dubbo:protocol name="dubbo" lazy="true" />注意:该配置只对使用长连接的 dubbo 协议生效
Dubbo 缓存文件 提供者列表缓存文件:<dubbo:registry file=”${user.home}/output/dubbo.cache” /> 有多个应用进程注意不要使用同一个文件,避免内容被覆盖 服务分组 当一个接口有多种实现时,可以用 group 区分 <dubbo:service group="feedback" interface="com.xxx.IndexService" /> <dubbo:service group="member" interface="com.xxx.IndexService" /> <dubbo:reference id="feedbackIndexService" group="feedback" interface="com.xxx.IndexService" /> 多版本 当一个接⼝实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。 可以按照以下的步骤进⾏版本迁移: 1. 在低压力时间段,先升级一半提供者为新版本 2. 再将所有消费者升级为新版本 3. 然后将剩下的一半提供者升级为新版本 结果缓存 结果缓存 ,用于加速热门数据的访问速度,Dubbo 提供声明式缓存,以减少用户加缓存的工作量 。 缓存类型 lru 基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。 threadlocal 当前线程缓存,如一个页面渲染,用到很多 portal,每个 portal 都要去查用户信息,通过线程缓存,可以减少这种多余访问。 jcache 与 JSR107 集成,可以桥接各种缓存实现。 <dubbo:reference interface="com.foo.BarService" cache="lru" /> 上下文信息 上下文中存放的是当前调用过程中所需的环境信息。所有配置信息都将转换为 URL 的参数 本地调用 本地调用使用了 injvm 协议,是一个伪协议,它不开启端口,不发起远程调用,只在 JVM 内直接关联,但执行 Dubbo的 Filter 链。服务暴露与服务引用都需要声明 injvm="true" <dubbo:protocol name="injvm" /> <dubbo:provider protocol="injvm" /> <dubbo:service protocol="injvm" /> <dubbo:consumer injvm="true" .../> <dubbo:provider injvm="true" .../> 2.2.0 开始,每个服务默认都会在本地暴露。在引用服务的时候,默认优先引用本地服务 延迟暴露 如果你的服务需要预热时间,如初始化缓存,等待相关资源就位等,可以使用delay 进行延迟暴露。 延迟5秒 <dubbo:service delay="5000" /> spring初始化之后 <dubbo:service delay="-1" />
dubbo:// Dubbo 缺省协议采用单一长连接和 NIO 异步通讯,适合于小数据量高并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。反之,Dubbo缺省协议不适合传送大数据量的服务,如传文件,传视频等,除非请求量很低。
缺省协议,基于 mina 1.1.7 和 hessian 3.2.1 的 tbremoting 交互。 连接个数:单连接 连接方式:长连接 传输协议:TCP 传输口式:NIO 异步传输 序列化:Hessian 二进制序列化 适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者, 尽量不要用 dubbo 协议传输文件件或超大字符串。 适用场景:常规远程服务方法调用 参数及返回值需实现 Serializable 接口 接口增加方法,对客户端无影响,如果该方法不是客户端需要的,客户端不需要重新部署。输入参数和结果集中增加属性,对客户端无影响,如果客户端并不需要新属性,不用重新部署。 输入参数和结果集属性名变化,对客户端序列化无影响.但是如果客户端不重新部署,不管输入还是输出,属性名变化的属性值是获取不到的。 rmi:// RMI 协议采用 JDK 标准的 java.rmi.* 实现,采用阻塞式短连接和 JDK 标准序列化方式。 注意:如果正在使用 RMI 提供服务给外部访问 ,同时应用中依赖了老的 common-collections 包 的情况下,存在反序列化安全风险 。 连接个数:多连接 连接方式:短连接 传输协议:TCP 传输方式:同步传输 序列化:Java 标准⼆进制序列化 适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。 适用场景:常规远程服务方法调用,与原生RMI服务互操作
参数及返回值需实现 Serializable 接口 dubbo 配置中的超时时间对 RMI 无效,需使用 java 启动参数设置: -Dsun.rmi.transport.tcp.responseTimeout=3000 hessian:// Hessian 协议用于集成 Hessian 的服务,Hessian 底层采用 Http 通讯,采用 Servlet 暴露服务,Dubbo 缺省内嵌 Jetty 作为服务器实现。 Dubbo 的 Hessian 协议可以和原生 Hessian 服务互操作,即: 提供者用 Dubbo 的 Hessian 协议暴露服务,消费者直接用标准 Hessian 接口调用 或者提供方用标准 Hessian 暴露服务,消费方用 Dubbo 的 Hessian 协议调用。 连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 序列化:Hessian二进制序列化 适用范围:传入传出参数数据包较大,提供者⽐消费者个数多,提供者压力较大,可传文件。 适用场景:页面传输,文件传输,或与原生hessian服务互操作 参数及返回值需实现 Serializable 接口 http:// 基于 HTTP 表单的远程调用协议,采用 Spring 的 HttpInvoker 实现 连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 序列化:表单序列化 适用范围:传入传出参数数据包大小合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件。 适用场景:需同时给应用程序和浏览器 JS 使用的服务。 参数及返回值需符合 Bean 规范 webservice:// 基于 WebService 的远程调⽤协议, 提供者用 Dubbo 的 WebService 协议暴露服务,消费者直接用标准 WebService 接口调用,或者提供者标准 WebService 暴露服务,消费者用 Dubbo 的 WebService 协议调用。 连接个数:多连接 连接方式:短连接 传输协议:HTTP 传输方式:同步传输 序列化:SOAP 文本序列化 适用场景:系统集成,跨语言调用
参数及返回值需实现 Serializable 接口 参数尽量使用基本类型和 POJO thrift:// memcached:// redis://
Multicast 注册中心 Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现。 1. 提供方启动时广播自己的地址 2. 消费方启动时广播订阅请求 3. 提供方收到订阅请求时,单播自己的地址给订阅者,如果设置了 unicast=false ,则广播给订阅者 4. 消费方收到提供方地址时,连接该地址进行 RPC 调用。 组播受网络结构限制,只适合小规模应用或开发阶段使用。组播地址段: 224.0.0.0 - 239.255.255.255 为了减少广播量,Dubbo 缺省使用单播发送提供者地址信息给消费者,如果一个机器上同时启了多个消费者进程,消费者需声明 unicast=false ,否则只会有一个消费者能收到消息 <dubbo:registry address="multicast://224.5.6.7:1234?unicast=false" /> zookeeper 注册中心 Zookeeper 是 Apacahe Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用。 流程说明: 服务提供者启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址 服务消费者启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向/dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址 监控中心启动时: 订阅 /dubbo/com.foo.BarService 目录下的所有提供者和消费者 URL 地址。 支持以下功能: 当提供者出现断电等异常停机时,注册中心能自动删除提供者信息 当注册中心重启时,能自动恢复注册数据,以及订阅请求 当会话过期时,能自动恢复注册数据,以及订阅请求 当设置 <dubbo:registry check="false" /> 时,记录失败注册和订阅请求,后台定时重试 可通过 <dubbo:registry username="admin" password="1234" /> 设置 zookeeper 登录信息 可通过 <dubbo:registry group="dubbo" /> 设置 zookeeper 的根节点,不设置将使无根树 支持 * 号通配符 <dubbo:reference group="*" version="*" /> ,可订阅服务的所有分组和所有版本的提供者 Redis 注册中心
使用 Redis 的 Key/Map 结构存储数据结构: 主 Key 为服务名和类型 Map 中的 Key 为 URL 地址 Map 中的 Value 为过期时间,用于判断脏数据,脏数据由监控中心删除 使用 Redis 的 Publish/Subscribe 事件通知数据变更:通过事件的值区分事件类型: register , unregister , subscribe , unsubscribe 普通消费者直接订阅指定服务提供者的 Key,只会收到指定服务的 register , unregister 事件 监控中心通过 psubscribe 功能订阅 /dubbo/* ,会收到所有服务的所有变更事件 调用过程: 1. 服务提供方启动时,向 Key:/dubbo/com.foo.BarService/providers 下,添加当前提供者的地址 2. 并向 Channel:/dubbo/com.foo.BarService/providers 发送 register 事件 3. 服务消费方启动时,从 Channel:/dubbo/com.foo.BarService/providers 订阅 register 和 unregister 事件 4. 并向 Key:/dubbo/com.foo.BarService/providers 下,添加当前消费者的地址 5. 服务消费方收到 register 和 unregister 事件后,从 Key:/dubbo/com.foo.BarService/providers 下获取提供者地址列表 6. 服务监控中方启动时,从 Channel:/dubbo/* 订阅 register 和 unregister ,以及 subscribe 和 unsubsribe 事件 7. 服务监控中方收到 register 和 unregister 事件后,从 Key:/dubbo/com.foo.BarService/providers 下获取提供者地址列表 8. 服务监控中方收到 subscribe 和 unsubsribe 事件后,从 Key:/dubbo/com.foo.BarService/consumers 下获取消费者地址列表 Simple 注册中心 本身就是一个普通的Dubbo 服务,可以减少第三方依赖,使整体通讯方式一致