Dubbo初探
dubbo配置
官方文档:
http://dubbo.io/User+Guide-zh.htm
依赖jar:
配置:
server:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd"
>
<bean id="testService" class="com.test.client.impl.TestServiceImpl" />
<dubbo:application name="test_server" />
<dubbo:registry address="N/A" />
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:service interface="com.test.client.TestService" ref="testService" />
</beans>
其中dubbo:application表示应用名称,不重复即可
dubbo:registry:注册中心地址
dubbo:protocol:采用的协议
dubbo:service:提供服务的接口
client:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
">
<dubbo:application name="hehe_consumer" />
<dubbo:consumer timeout="30000">
</dubbo:consumer>
<dubbo:reference id="testServer" interface="com.test.client.TestService"
url="dubbo://127.0.0.1:20880/com.test.client.TestService"/>
</beans>
其中dubbo:reference表示使用的服务,url表示直连。
注册中心架构
用zookeeper、redis等都可以做注册中心,一般用zookeeper,zookeeper是apache hadoop的子项目。
管理控制台
管理控制台的主要作用是服务治理,具体包括路由规则、动态配置、服务降级、访问控制、权重调整、负载均衡等。
管控台是否正常对dubbo服务没影响,不需要高可用,一般单节点部署。
安装:
将dubbo-admin-2.5.3.war放到tomcat即可,如解压到ROOT目录,将原war包移除,以免重启后修改被覆盖。
unzip dubbo-admin-2.5.3.war -d ROOT
修改配置:
/usr/local/apache-tomcat-6.0.45_dubbo_manager/webapps/ROOT/WEB-INF/dubbo.properties
需要配置管控台的登录账号与,zookeeper注册中心的地址,如:
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest
然后登录界面即可查看
此时输入服务名即可搜索,如:
配置部署了 Dubbo 管控台的 Tomcat 开机启动: 在虚拟主机中编辑/etc/rc.local 文件,加入: su - kkk -c '/home/wusc/dubbo-admin-tomcat/bin/startup.sh'
监控中心
监控中心统计各服务的调用次数、调用时间,先在内存汇总,然后每分钟发送一次到监控中心服务端,以报表展示。
监控中心可不安装,不影响dubbo正常使用。
监控中心本身也是一个dubbo服务
监控中心可通过扩展接口自定义开发:
com.alibaba.dubbo.monitor.MonitorFactory
com.alibaba.dubbo.monitor.Monitor
可参考在官方文档的"开发者指南"进行扩展,可满足个性需求,如:
服务健康状况、服务压力性能情况、报警通知等。
官方有自带的简易监控中心。
简易监控中心安装
监控中心自带了jetty服务器,不需要tomcat了,将dubbo-monitor-simple-2.5.3-assembly.tar.gz解压,如放到/usr/local,目录名为dubbo-monitor修改配置:
vim /usr/local/dubbo-monitor/conf/dubbo.properties
注释掉广播地址,打开zookeeper的注释即可
#dubbo.registry.address=multicast://224.5.6.7:1234
dubbo.registry.address=zookeeper://127.0.0.1:2181
其中dubbo.protocol.port=7070是监控中心作为dubbo服务的端口
dubbo.jetty.port是监控中心web的端口
这两个端口不要与其他端口有冲突。
然后启动其自带的jetty服务即可。
cd /usr/local/dubbo-monitor/bin/
./start.sh
浏览器访问:
dubbo-monitor/bin里面有启停jetty的各种命令
dubbo服务集群
概念
dubbo服务集群是指一个dubbo服务部署在多台机器上
1、当某个机器的服务挂掉,zookeeper注册中心会自动移除,将请求转到可用的机器上,实现高可用。
2、一般一台机器上只部署一份同一个服务。
3、服务挂掉要注意是tomcat进程结束,而不是被防火墙阻止访问,如果是被防火墙阻止的,会卡在那里很久。
集群容错模式
容错模式是指在调用一个dubbo服务超时(失败)时候的处理,通过Cluster属性设置,第1、2种最常用。
默认是cluster="failover" retries="2"
设置第1种的retries="0"则跟第2种几乎一样。所以一般默认就行了,对不支持幂等的接口设置retries="0"即可。
将读接口和写接口放到不同接口类中,可以方便统一配置。
1、Failover Cluster(默认)
失败自动切换,当出现失败,重试其它服务器。
通常用于读操作,但重试会带来更长延迟,不能用于不支持幂等的接口
可通过retries="2"来设置重试次数(不含第一次)。
配置:
提供者:
<dubbo:service retries="2" />
或:
消费者:
<dubbo:reference retries="2" />
或:
消费者的某个方法
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>
消费方配置优先于提供方配置
2、Failfast Cluster
快速失败,只发起一次调用,失败立即报错。
通常用于非幂等性的写操作,比如新增记录。
配置:
<dubbo:service cluster="failfast">
或
<dubbo:reference cluster="failfast">
3、Failsafe Cluster
失败安全,出现异常时,直接忽略。
通常用于写入审计日志等操作。
配置:
<dubbo:service cluster="failsafe">
或
<dubbo:reference cluster="failsafe">
4、Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。
通常用于消息通知操作。
配置:
<dubbo:service cluster="failback">
或
<dubbo:reference cluster=" failback ">
5、Forking Cluster
并行调用多个服务器,只要一个成功即返回。
通常用于实时性要求较高的读操作,但需要浪费更多服务资源。
可通过forks="2"来设置最大并行数。
配置:
<dubbo:service cluster="forking">
或
<dubbo:reference cluster=" forking">
6、Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错。(2.1.0开始支持)
通常用于通知所有提供者更新缓存或日志等本地资源信息。
配置:
<dubbo:service cluster="broadcast">
或
<dubbo:reference cluster=" broadcast ">
负载均衡策略
负载均衡是指请求分配到集群中哪台服务器的处理。默认为random,一般在管理控制台中设置,很少在配置文件中设置,一般用默认。
有以下4种:
Random LoadBalance
随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
可以在管理控制台设置权重。
实现源码在:com.alibaba.dubbo.rpc.cluster.loadbalance.RandomLoadBalance
存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
实现源码在com.alibaba.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
就是计算每次调用的耗时(计数差)平均值,耗时越大的提供者收到越少的请求
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
算法参见:http://en.wikipedia.org/wiki/Consistent_hashing。
缺省只对第一个参数Hash,如果要修改,请配置<dubbo:parameter key="hash.arguments" value="0,1" />
缺省用160份虚拟节点,如果要修改,请配置<dubbo:parameter key="hash.nodes" value="320" />
配置:
可以配置在provider或者consumer的接口或者接口的方法上:
配置如:
<dubbo:service interface="..." loadbalance="roundrobin" /> |
或:
<dubbo:reference interface="..." loadbalance="roundrobin" /> |
或:
<dubbo:service interface="..."> <dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:service> |
或:
<dubbo:reference interface="..."> <dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:reference> |
也可以在管理控制台配置每个接口或方法的负载均衡策略
dubbo线程模型
概念:
dubbo默认有线程池,所有请求都会派发到线程池,在provider标签或protocol标签可以配置,如:
<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />
这也是默认配置.
可选项:
Dispatcher
all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。
direct 所有消息都不派发到线程池,全部在IO线程上直接执行。
message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在IO线程上执行。
execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在IO线程上执行。
connection 在IO线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。
ThreadPool
fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)
cached 缓存线程池,空闲一分钟自动删除,需要时重建。
limited 可伸缩线程池,但池中的线程数只会增长不会收缩。(为避免收缩时突然来了大流量引起的性能问题)。
事件处理线程说明
- 如果事件处理的逻辑能迅速完成,并且不会发起新的IO请求,比如只是在内存中记个标识,则直接在IO线程上处理更快,因为减少了线程池调度。
- 但如果事件处理逻辑较慢,或者需要发起新的IO请求,比如需要查询数据库,则必须派发到线程池,否则IO线程阻塞,将导致不能接收其它请求。
- 如果用IO线程处理事件,又在事件处理过程中发起新的IO请求,比如在连接事件中发起登录请求,会报"可能引发死锁"异常,但不会真死锁。
源码在:com.alibaba.dubbo.common.threadpool
dubbo protocol的主要配置
linux用户线程数限制导致的OutOfMemoryError异常
linux对非root的普通用户创建线程数有限制,默认为1024个,如果java中超过,则会报java.lang.OutOfMemoryError: unable to create new native thread异常。
配置在:
/etc/security/limits.d/90-nproc.conf
其中*表示非root的其他用户。
配置后需reboot重启生效。
调整时注意:
1、不要用root来部署,因为线程数没有限制,资源耗光会导致终端都无法连接,只能硬重启。
2、linux可创建的最大线程数计算:用物理内存/128K,大约等于最大线程数。
如:
cat /proc/meminfo | grep MemTotal
echo "1012352/128"|bc
ulimit –u
ulimit –u是查看最大线程数。两个值很接近,上面计算是为了说明最大线程数跟物理内存相关。
模块划分
服务化概念:将系统垂直划分,抽取出基础服务层,为业务层服务。
划分过细:破坏子系统的独立性,占用进程数、内存过多。
划分过粗:不能很好解耦,升级维护影响大
注意事项:
1、不要有环状依赖调用
2、服务间依赖链不要过长(尽量3个以内,经常是划分过细导致)
3、避免分布式事务(尽量用MQ分布式消息来解决)
4、不要跨服务查询表(也就是表也需要垂直拆分,尽量一个服务一个库)
5、服务划分是个不断优化的过程
接口设计原则:
1、接口粒度尽可能大,一个接口完成一个功能,而不是一个功能的某个步骤。
2、接口以业务场景为划分,相同场景做抽象,以便减少接口数量。
3、同时避免过于抽象的通用接口,如Map query(Map) 就没有意义。
4、每个接口都应提供版本号,如version="1.0",为后续不兼容升级考虑
5、接口兼容性:接口新增方法、模型新增字段可以兼容。而删除方法、字段、修改等不兼容,需要变更接口版本号升级。
6、以抛异常的方式代替返回错误码方式
7、增加接口参数校验
8、在provider(提供者端)尽量多配置consumer(消费端)的属性,默认是先读取consumer端的配置,如果没有就用provider的配置,如果还没有,就取consumer端的全局默认配置。
因为provider更清楚自己服务的特性,需要做哪些配置,所以尽量配在provider端。尽量避免使用consumer端的全局默认配置,那样不可控。
dubbo服务启动检查:
A服务依赖B服务,则必须当B启动了,A才能正常启动,默认要检查(check="true"),配置check="false"可不检查。
关闭某个服务启动检查
<dubbo:reference check="false" interface="..."/>
关闭所有服务启动检查
<dubbo:consumer check="false"/>
关闭注册中心启动检查
<dubbo:registry check="false" />
其中reference优先级大于consumer的配置。
registry的check="false"是指注册中心连接失败了也不管,继续启动。
dubbo直连
直连可不通过注册中心,而直接使用url连接到服务提供者。配置:
消费端加url属性即可,如:
<dubbo:reference id="xxxService" interface="com.alibaba.xxx.XxxService" url="dubbo://localhost:20890" />
只订阅
开发的时候,本机只需要订阅注册中心的服务,而不能注册上去对外提供服务。配置:
<dubbo:registry address="10.20.153.10:9090" register="false" />
或
<dubbo:registry address="10.20.153.10:9090?register=false" />
只注册
如果有两个镜像环境,两个注册中心,有一个服务只在其中一个注册中心有部署,另一个注册中心还没来得及部署,而两个注册中心的其它应用都需要依赖此服务,所以需要将服务同时注册到两个注册中心,但却不能让此服务同时依赖两个注册中心的其它服务。如:
配置:
禁用订阅配置:
<dubbo:registry id="hzRegistry" address="10.20.153.10:9090" /> <dubbo:registry id="qdRegistry" address="10.20.141.150:9090" subscribe="false" /> |
或者:
<dubbo:registry id="hzRegistry" address="10.20.153.10:9090" /> <dubbo:registry id="qdRegistry" address="10.20.141.150:9090?subscribe=false" /> |
在qdRegistry这个注册中心配置了只注册。

浙公网安备 33010602011771号