限流
在实际使用场景中,服务提供者一般远少于服务消费者。如果为每个服务消费者创建单一的连接,在服务消费者数量可控的情况下,服务提供者不太容易被轻易压垮。但如果为每个服务消费者创建独立连接,或者当服务消费者的数量爆发性增长时,就需要在服务提供者端限制最大可接收连接数了,防止自身被压垮。
在Dubbo的服务提供者端配置限流参数的代码如下。
<dubbo:providerprotocol="dubbo" accepts="10" threads="10"connections="10" />
其中的accepts、threads和connections分别表示该服务提供者应用实例的最大可接受连接数、最大线程数,以及每个服务提供者可建立的长连接数。
也可以在通信协议部分进行全局配置,配置代码如下。
<dubbo:protocolname="dubbo" port="20880" accepts="1024" />
治理中心
运行时环境的Dubbo只需具有服务提供者、服务消费者和注册中心就可以正常运转,所有的运行时信息都存储在基于ZooKeeper或Redis的注册中心中。可以直接通过命令行对注册中心进行查询以获取系统当前的运行状态,也可以通过直接对注册中心的数据进行修改(例如修改权重、禁用某一服务提供者实例、修改负载均衡策略等)以达到控制服务提供者和服务消费者行为的目的。
但是直接通过ZooKeeper或Redis的原生命令来查询和修改数据并不方便,也容易由于手动失误造成线上事故,因此Dubbo提供了治理中心,可以帮助运维工程师查询和调整系统的运行时状态。
Dubbo治理中心的名字叫作dubbo-admin,它可以被打包为一个独立的war文件,部署至Tomcat这类支持Servlet标准的Web容器中使用。无论是否使用dubbo-admin,都不会对运行时的Dubbo应用产生任何影响,它的作用只是提供一个可视化工具,辅助工程师进行运维相关工作。基于Dubbo开发的应用与Dubbo治理中心并无直接关联,它们之间无须感知对方的存在,它们仅与注册中心建立关联。
Dubbo治理中心为服务提供者和服务消费者提供了分组查询、配置更改、加权/降权、禁用/启用、权限控制、负责人管理等运维功能。
监控中心
在复杂的分布式系统中,Dubbo的服务消费者与服务提供者之间的调用关系相当错综复杂,仅凭治理中心是无法掌握当前系统运行所需的全部数据的。Dubbo提供了监控中心的接口以及一个名为dubbo-monitor的简单实现,dubbo-monitor可以用于统计和分析调用信息。
Dubbo的监控中心采用了与治理中心类似的设计思路,dubbo-monitor宕机不会对线上正在运行的应用产生不良影响。只要监控中心正常运行,就能够以增量的方式统计和分析调用数据。Dubbo应用间的远程调用信息将被发送至监控中心进行统计,采集的调用信息包括调用的发生时间、耗时、成功与否、来源方、目的地等。监控中心将采集到的数据定时汇总,并将统计结果落盘至其所在的服务器。通过监控中心可以清晰地看到服务的访问总数、成功失败次数,以及每个服务调用耗时的最大值、最小值和平均值的聚合图。
监控中心虽然是Dubbo官方提供的一个基于内存计算和本地存储的建议实现版本,但客观来讲,它只适用于演示程序,并不能完全满足线上环境监控和分析的需要。它缺乏完善的调用链路统计功能,因而无法绘制系统的整体调用关系图。对于单次调用而言,它也无法深入钻取Dubbo之外的调用信息,例如服务提供者调用数据库的耗时。仅使用dubbo-monitor难于完成对系统的综合监控以及对事故的复盘解读。
DubboX的扩展
DubboX由当当网开源,X源于extensions一词,是对Dubbo的扩展和有益补充。
- REST协议
虽然Dubbo框架支持多种通信协议,但缺乏对当今较为流行的RESTful风格远程调用的支持,基于Dubbo进行二次开发的DubboX弥补了这一方面的缺憾。
DubboX基于标准的Java REST API——JAX-RS2.0(Java API for RESTful Web Services),为Dubbo提供了透明化的RESTful风格支持。在DubboX中,仅对通过Dubbo开发的应用稍作修改即可支持REST协议。
首先对服务提供者实现类添加JAX-RS的API,核心代码如下。
@Path("foo")
public class FooServiceImpl implements FooService {
@GET
@Path("bar")
@Consumes({MediaType.APPLICATION_JSON})
@Override
public Date bar() {
return new Date();
}
}
再将provider.xml的服务暴露配置修改为REST协议,核心代码如下。
<dubbo:protocolname="rest" port="8080" />
启动程序后,即可通过访问浏览器或执行curl命令获取调用结果。通过REST协议能够实现异构语言间的调用。
- 高性能序列化
序列化会对远程调用的响应速度、吞吐量、网络带宽消耗产生较大影响,是提升分布式系统性能最关键的因素之一。
在Dubbo通信协议中,常见的序列化方式主要有以下几种。
Dubbo序列化:阿里巴巴公司尚未开发成熟的高效Java序列化实现,不建议在生产环境中使用。
Hessian2序列化:一种跨语言的高效二进制序列化方式。使用Dubbo框架修改过的hessianlite是Dubbo通信协议默认启用的序列化方式。
JSON序列化:采用FastJson解析JSON,文本序列化性能不如上面两种二进制序列化性能。
Java原生序列化:采用JDK自带的Java序列化实现,性能不是很理想。
通常情况下,以上四种主要序列化方式的性能从上到下依次递减。对于Dubbo通信协议这种追求高性能的远程调用方式来说,只有前两种高效序列化方式与之比较“般配”,而Dubbo序列化方式还不成熟,因此实际只剩下Hessian2方式可用。Dubbo通信协议默认采用它作为序列化选型。
但Hessian2是一个比较老的跨语言序列化实现方式,并不单独针对Java进行优化。而Dubbo通信协议是一种Java同构语言之间的远程调用,没有必要采用跨语言的序列化方式。
前面介绍的高性能序列化框架,如Kryo 、Protobuf 等,Dubbo都没有采用。除了这些,还有专门针对Java语言的FST、跨语言的Thrift、Avro、MsgPack等,这些序列化方式的性能都显著优于Hessian2。
鉴于此,DubboX引入Kryo和FST这两种高效Java序列化方式来取代Hessian2,它们与Dubbo这样的高性能通信协议更加“般配”。
使用方法非常简单,仅需在Dubbo 通信协议的配置中声明序列化协议名称即可,核心代码如下。
<dubbo:protocolname="dubbo" serialization="kryo"/>
或者也可以采用如下方式。
<dubbo:protocolname="dubbo" serialization="fst"/>
DubboX是当当网基于Dubbo进行增量开发而实现的项目。出于对Dubbo的敬意,保留了代码中阿里巴巴的包名,因此无法将代码发布到阿里巴巴的Maven中央仓库中。使用者需要自行下载源码编译打包。
Dubbo凭借远程调用和服务治理功能成为分布式系统的关键组件,并且借助自身优异的性能、较高的质量以及便捷的使用方式在服务化领域占据了一席之地。但服务治理领域所涵盖的内容非常广泛,即使像Dubbo这样优秀的项目,也并未完全实现服务治理领域的全部功能。目前,Dubbo缺乏有效的熔断机制,在调用链路跟踪方面也还有提升的空间。
Dubbo近年来疏于维护,因此后来居上的Spring Cloud渐渐占据了更大的市场份额。不过Dubbo团队已经在2017年宣布重新开始维护Dubbo,希望能带来更好的服务化解决方案。
(编者注:阿里巴巴开源了Sentinel,Dubbo重启之后也取得了长足的发展,附录如下)
2014年,当当网 fork 了 Dubbo 版本,命名为dubbox-2.8.0,并支持 HTTP REST 协议;
2014年10月,发布2.3.11版本;
2017年9月,阿里巴巴重启维护,重点升级所依赖的 JDK 及组件版本,发布2.5.4/5版本;(直接基于spring boot 去做的 上层 rpc 框架)
2018年2月,阿里巴巴宣布将 Dubbo 捐献给 Apache,进入 Apache 孵化器;
2018年6月,Apache Dubbo 发布首个加入 Apache 孵化器的版本2.6.2,发展首位committer,来自有赞的@yiji同学;
2018年7月,Dubbo 官方域名更新到 dubbo.apache.org,页面焕然一新,并启用新 logo,品牌全面升级;
2018年11月,加入孵化器以来,发展来自有赞的 @yiji同学成为首位 PPMC member;
2018年12月,第八届云计算标准和应用大会 ,Dubbo 获得中国优秀开源项目一等奖,同时获得开源中国举办的2018中国优秀开源项目奖,位列排行榜第3;
2019年1月,发布了2.7.0,支持 Java 1.8,包名更改为org.apache,支持 Restful 服务;
2019年1月,Dubbo 社区正式发布 Dubbo Ecosystem, 升级为完成的微服务解决方案;
2019年5月21日,Dubbo 从 Apache 正式毕业。

