背景

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

单一应用架构

当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。

垂直应用架构

当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。

分布式服务架构

当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
流动计算架构

当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。

架构


节点角色说明

Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心
Container 服务运行容器

调用关系说明

1.服务容器负责启动,加载,运行服务提供者。
2.服务提供者在启动时,向注册中心注册自己提供的服务。
3.服务消费者在启动时,向注册中心订阅自己所需的服务。
4.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
5.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
6.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性

连通性

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

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

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

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

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

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

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

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

健壮性

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

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

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

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

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

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

伸缩性

注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心

服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者

使用

XML配置

服务提供方

<!-- 应用名 -->
<dubbo:application name="dubboxdemo-service" />
<!-- 注册中心 -->
<dubbo:registry address="zookeeper://192.168.192.129:2181" />
<!-- 访问协议 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!-- 暴露服务 -->
<bean id="userService" class="cn.aiminjt.dubbodemo.service.UserServiceImpl"/>
<dubbo:service interface="cn.aiminjt.dubbodemo.service.UserService" ref="userService"></dubbo:service>

服务消费方

<!-- 应用名 -->
<dubbo:application name="dubboxdemo-web" />
<!-- 注册中心 -->
<dubbo:registry address="zookeeper://192.168.192.129:2181" />
<!—订阅服务 -->
<dubbo:reference interface="cn.aiminjt.dubbodemo.service.UserService" id="userService"></dubbo:reference>

注解

服务提供方

<!-- 应用名 -->
<dubbo:application name="dubboxdemo-service" />
<!-- 注册中心 -->
<dubbo:registry address="zookeeper://192.168.192.129:2181" />
<!-- 访问协议 -->
<dubbo:protocol name="dubbo" port="20880"/>
<!—注解扫描暴露服务 -->
<dubbo:annotation package="cn.aiminjt.dubboxdemo.controller" />

在需要暴露服务的类上使用注解

import com.alibaba.dubbo.config.annotation.Service;
@Service
public class UserServiceImpl implements UserService{@Overridepublic String getName() {return "aiminjt";}
}

服务消费方

<!-- 应用名 -->
<dubbo:application name="dubboxdemo-web" />
<!-- 注册中心 -->
<dubbo:registry address="zookeeper://192.168.192.129:2181" />
<!—注解扫描订阅服务 -->
<dubbo:annotation package="cn.aiminjt.dubboxdemo.controller" />

在需要暴露服务的类上使用注解

import com.alibaba.dubbo.config.annotation.Reference;
@Controller
@RequestMapping("/user")
public class UserController {@Referenceprivate UserService userService;...
}

协议

dubbo://

Dubbo 缺省协议采用单一长连接NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。
反之,Dubbo 缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。

特性

缺省协议,使用基于 mina 1.1.7 和 hessian 3.2.1 的 tbremoting 交互。
连接个数:单连接
连接方式:长连接
传输协议:TCP
传输方式:NIO 异步传输(NIO)
序列化:Hessian 二进制序列化
适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用 dubbo 协议传输大文件或超大字符串。
适用场景:常规远程服务方法调用

约束

参数及返回值需实现 Serializable 接口
参数及返回值不能自定义实现 List, Map, Number, Date, Calendar 等接口,只能用 JDK 自带的实现,因为 hessian 会做特殊处理,自定义实现类中的属性值都会丢失。

配置

配置协议:

<dubbo:protocol name="dubbo" port="20880" />

设置服务协议:

<dubbo:service protocol="dubbo" />

多端口:

<dubbo:protocol id="dubbo1" name="dubbo" port="20880" />
<dubbo:protocol id="dubbo2" name="dubbo" port="20881" />

rmi://

RMI 协议采用 JDK 标准的 java.rmi.* 实现,采用阻塞式短连接和 JDK 标准序列化方式。

特性

连接个数:多连接
连接方式:短连接
传输协议:TCP
传输方式:同步传输
序列化:Java 标准二进制序列化
适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
适用场景:常规远程服务方法调用,与原生RMI服务互操作

约束

参数及返回值需实现 Serializable 接口
dubbo 配置中的超时时间对 RMI 无效,需使用 java 启动参数设置:-Dsun.rmi.transport.tcp.responseTimeout=3000,参见下面的 RMI 配置

hessian://

Hessian协议用于集成 Hessian 的服务,Hessian 底层采用 Http 通讯,采用 Servlet 暴露服务,Dubbo 缺省内嵌 Jetty 作为服务器实现。
Dubbo 的 Hessian 协议可以和原生 Hessian 服务互操作,即:
提供者用 Dubbo 的 Hessian 协议暴露服务,消费者直接用标准 Hessian 接口调用
或者提供方用标准 Hessian 暴露服务,消费方用 Dubbo 的 Hessian 协议调用。
特性
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:Hessian二进制序列化
适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。
适用场景:页面传输,文件传输,或与原生hessian服务互操作

依赖

<dependency><groupId>com.caucho</groupId><artifactId>hessian</artifactId><version>4.0.7</version>
</dependency>

约束

参数及返回值需实现 Serializable 接口
参数及返回值不能自定义实现 List, Map, Number, Date, Calendar 等接口,只能用 JDK 自带的实现,因为 hessian 会做特殊处理,自定义实现类中的属性值都会丢失。

配置

定义 hessian 协议:

<dubbo:protocol name="hessian" port="8080" server="jetty" />

设置默认协议:

<dubbo:provider protocol="hessian" />

设置 service 协议:

<dubbo:service protocol="hessian" />

多端口:

<dubbo:protocol id="hessian1" name="hessian" port="8080" />
<dubbo:protocol id="hessian2" name="hessian" port="8081" />

http://

基于 HTTP 表单的远程调用协议,采用 Spring 的 HttpInvoker 实现
特性
连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:表单序列化
适用范围:传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件。
适用场景:需同时给应用程序和浏览器 JS 使用的服务。

约束

参数及返回值需符合Bean 规范

webservice://

基于 WebService 的远程调用协议,基于 Apache CXF 的 frontend-simple 和 transports-http 实现 。
可以和原生 WebService 服务互操作,即:
提供者用 Dubbo 的 WebService 协议暴露服务,消费者直接用标准 WebService 接口调用,
或者提供方用标准 WebService 暴露服务,消费方用 Dubbo 的 WebService 协议调用。

依赖

<dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-frontend-simple</artifactId><version>2.6.1</version>
</dependency>
<dependency><groupId>org.apache.cxf</groupId><artifactId>cxf-rt-transports-http</artifactId><version>2.6.1</version>
</dependency>

特性

连接个数:多连接
连接方式:短连接
传输协议:HTTP
传输方式:同步传输
序列化:SOAP 文本序列化
适用场景:系统集成,跨语言调用

约束

参数及返回值需实现 Serializable 接口
参数尽量使用基本类型和 POJO

注册中心

zookeeper 注册中心

Zookeeper 是 Apacahe Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用
支持以下功能:
当提供者出现断电等异常停机时,注册中心能自动删除提供者信息
当注册中心重启时,能自动恢复注册数据,以及订阅请求
当会话过期时,能自动恢复注册数据,以及订阅请求
当设置 <dubbo:registry check=“false” /> 时,记录失败注册和订阅请求,后台定时重试
可通过 <dubbo:registry username=“admin” password=“1234” /> 设置 zookeeper 登录信息
可通过 <dubbo:registry group=“dubbo” /> 设置 zookeeper 的根节点,不设置将使用无根树
支持 * 号通配符 <dubbo:reference group="" version="" />,可订阅服务的所有分组和所有版本的提供者

配置

Zookeeper 单机配置:

<dubbo:registry address="zookeeper://10.20.153.10:2181" />

或:

<dubbo:registry protocol="zookeeper" address="10.20.153.10:2181" />

Zookeeper 集群配置:

<dubbo:registry address="zookeeper://10.20.153.10:2181?backup=10.20.153.11:2181,10.20.153.12:2181" />

或:

<dubbo:registry protocol="zookeeper" address="10.20.153.10:2181,10.20.153.11:2181,10.20.153.12:2181" /

Multicast 注册中心

Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现。

1.提供方启动时广播自己的地址
2.消费方启动时广播订阅请求
3.提供方收到订阅请求时,单播自己的地址给订阅者,如果设置了 unicast=false,则广播给订阅者
4.消费方收到提供方地址时,连接该地址进行 RPC 调用。
组播受网络结构限制,只适合小规模应用或开发阶段使用。组播地址段: 224.0.0.0 - 239.255.255.255

配置

<dubbo:registry address="multicast://224.5.6.7:1234" />

<dubbo:registry protocol="multicast" address="224.5.6.7:1234" />

Redis 注册中心

基于 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 下获取消费者地址列表

配置

<dubbo:registry address="redis://10.20.153.10:6379" />

<dubbo:registry address="redis://10.20.153.10:6379?backup=10.20.153.11:6379,10.20.153.12:6379" />

<dubbo:registry protocol="redis" address="10.20.153.10:6379" />

<dubbo:registry protocol="redis" address="10.20.153.10:6379,10.20.153.11:6379,10.20.153.12:6379" />

选项
可通过 <dubbo:registry group=“dubbo” /> 设置 redis 中 key 的前缀,缺省为 dubbo。
可通过 <dubbo:registry cluster=“replicate” /> 设置 redis 集群策略,缺省为 failover:
failover: 只写入和读取任意一台,失败时重试另一台,需要服务器端自行配置数据同步
replicate: 在客户端同时写入所有服务器,只读取单台,服务器端不需要同步,注册中心集群增大,性能压力也会更大

Simple 注册中心

Simple 注册中心本身就是一个普通的 Dubbo 服务,可以减少第三方依赖,使整体通讯方式一致。

配置

将 Simple 注册中心暴露成 Dubbo 服务:

<?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://dubbo.apache.org/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"><!-- 当前应用信息配置 --><dubbo:application name="simple-registry" /><!-- 暴露服务协议配置 --><dubbo:protocol port="9090" /><!-- 暴露服务配置 --><dubbo:service interface="com.alibaba.dubbo.registry.RegistryService" ref="registryService" registry="N/A" ondisconnect="disconnect" callbacks="1000"><dubbo:method name="subscribe"><dubbo:argument index="1" callback="true" /></dubbo:method><dubbo:method name="unsubscribe"><dubbo:argument index="1" callback="false" /></dubbo:method></dubbo:service><!-- 简单注册中心实现,可自行扩展实现集群和状态同步 --><bean id="registryService" class="com.alibaba.dubbo.registry.simple.SimpleRegistryService" />
</beans>

引用 Simple Registry 服务:

<dubbo:registry address="127.0.0.1:9090" />

或者:

<dubbo:service interface="com.alibaba.dubbo.registry.RegistryService" group="simple" version="1.0.0" ... >

或者:

<dubbo:registry address="127.0.0.1:9090" group="simple" version="1.0.0" />

服务监控

部署服务管理中心

其实管理中心就是一个web应用,部署到tomcat即可。

在服务提供方通过telnet命令监控服务

使用

telnet localhost 20880

命令
ls
ls: 显示服务列表
ls -l: 显示服务详细信息列表
ls XxxService: 显示服务的方法列表
ls -l XxxService: 显示服务的方法详细信息列表
ps
ps: 显示服务端口列表
ps -l: 显示服务地址列表
ps 20880: 显示端口上的连接信息
ps -l 20880: 显示端口上的连接详细信息
cd
cd XxxService: 改变缺省服务,当设置了缺省服务,凡是需要输入服务名作为参数的命令,都可以省略服务参数
cd /: 取消缺省服务
pwd
pwd: 显示当前缺省服务
trace
trace XxxService: 跟踪 1 次服务任意方法的调用情况
trace XxxService 10: 跟踪 10 次服务任意方法的调用情况
trace XxxService xxxMethod: 跟踪 1 次服务方法的调用情况
trace XxxService xxxMethod 10: 跟踪 10 次服务方法的调用情况
count
count XxxService: 统计 1 次服务任意方法的调用情况
count XxxService 10: 统计 10 次服务任意方法的调用情况
count XxxService xxxMethod: 统计 1 次服务方法的调用情况
count XxxService xxxMethod 10: 统计 10 次服务方法的调用情况
invoke
invoke XxxService.xxxMethod({“prop”: “value”}): 调用服务的方法
invoke xxxMethod({“prop”: “value”}): 调用服务的方法(自动查找包含此方法的服务)
status
status: 显示汇总状态,该状态将汇总所有资源的状态,当全部 OK 时则显示 OK,只要有一个 ERROR 则显示 ERROR,只要有一个 WARN 则显示 WARN
status -l: 显示状态列表
log
log debug: 修改 dubbo logger 的日志级别
log 100: 查看 file logger 的最后 100 字符的日志
help
help: 显示 telnet 命帮助信息
help xxx: 显示xxx命令的详细帮助信息
clear
clear: 清除屏幕上的内容
clear 100: 清除屏幕上的指定行数的内容
exit
exit: 退出当前 telnet 命令行

回声测试

回声测试用于检测服务是否可用,回声测试按照正常请求流程执行,能够测试整个调用是否通畅,可用于监控。
所有服务自动实现 EchoService 接口,只需将任意服务引用强制转型为 EchoService,即可使用。
Spring 配置:

<dubbo:reference id="memberService" interface="com.xxx.MemberService" />

代码:

// 远程服务引用
MemberService memberService = ctx.getBean("memberService");
EchoService echoService = (EchoService) memberService; // 强制转型为EchoService
// 回声测试可用性
String status = echoService.$echo("OK");
assert(status.equals("OK"));

DUBBO常用配置

直连提供者

在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获取列表。

通过 XML 配置

如果是线上需求需要点对点,可在 dubbo:reference 中配置 url 指向提供者,将绕过注册中心,多个地址用分号隔开,配置如下:

<dubbo:reference id="xxxService" interface="com.alibaba.xxx.XxxService" url="dubbo://localhost:20880" />

多协议

Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。
不同服务不同协议
不同服务在性能上适用不同协议进行传输,比如大数据用短连接协议,小数据大并发用长连接协议

<?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://dubbo.apache.org/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <dubbo:application name="world"  /><dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" /><!-- 多协议配置 --><dubbo:protocol name="dubbo" port="20880" /><dubbo:protocol name="rmi" port="1099" /><!-- 使用dubbo协议暴露服务 --><dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo" /><!-- 使用rmi协议暴露服务 --><dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" protocol="rmi" />
</beans>

多协议暴露服务

<?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://dubbo.apache.org/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <dubbo:application name="world"  /><dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" /><!-- 多协议配置 --><dubbo:protocol name="dubbo" port="20880" /><dubbo:protocol name="rmi" port="1099" /><!-- 使用dubbo,rmi协议暴露服务 --><dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo,rmi" />
</beans>

多注册中心

Dubbo 支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。另外,注册中心是支持自定义扩展的。
多注册中心注册服务
比如:中文站有些服务来不及在青岛部署,只在杭州部署,而青岛的其它应用需要引用此服务,就可以将服务同时注册到两个注册中心。

<?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://dubbo.apache.org/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"><dubbo:application name="world"  /><!-- 多注册中心配置 --><dubbo:registry id="hangzhouRegistry" address="10.20.141.150:9090" /><dubbo:registry id="qingdaoRegistry" address="10.20.141.151:9010" default="false" /><!-- 向多个注册中心注册 --><dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="hangzhouRegistry,qingdaoRegistry" />
</beans>

不同服务使用不同注册中心

比如:CRM 有些服务是专门为国际站设计的,有些服务是专门为中文站设计的。

<?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://dubbo.apache.org/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"><dubbo:application name="world"  /><!-- 多注册中心配置 --><dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" /><dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" /><!-- 向中文站注册中心注册 --><dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="chinaRegistry" /><!-- 向国际站注册中心注册 --><dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" registry="intlRegistry" />
</beans>

多注册中心引用

比如:CRM 需同时调用中文站和国际站的 PC2 服务,PC2 在中文站和国际站均有部署,接口及版本号都一样,但连的数据库不一样。

<?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://dubbo.apache.org/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"><dubbo:application name="world"  /><!-- 多注册中心配置 --><dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" /><dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" /><!-- 引用中文站服务 --><dubbo:reference id="chinaHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="chinaRegistry" /><!-- 引用国际站站服务 --><dubbo:reference id="intlHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="intlRegistry" />
</beans>

服务分组( 一个接口多实现 )

当一个接口有多种实现时,可以用 group区分。
服务提供

<dubbo:service group="feedback" interface="com.xxx.IndexService" ref=”impl1”/>
<dubbo:service group="member" interface="com.xxx.IndexService" ref=”impl2”/>

服务引用

<dubbo:reference id="feedbackIndexService" group="feedback" interface="com.xxx.IndexService" />
<dubbo:reference id="memberIndexService" group="member" interface="com.xxx.IndexService" />

任意组引用

<dubbo:reference id="barService" interface="com.foo.BarService" group="*" />

多版本

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
可以按照以下的步骤进行版本迁移:
在低压力时间段,先升级一半提供者为新版本
再将所有消费者升级为新版本
然后将剩下的一半提供者升级为新版本
老版本服务提供者配置:

<dubbo:service interface="com.foo.BarService" version="1.0.0" />

新版本服务提供者配置:

<dubbo:service interface="com.foo.BarService" version="2.0.0" />

老版本服务消费者配置:

<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />

新版本服务消费者配置:

<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />

如果不需要区分版本,可以按照以下的方式配置 :

<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />

结果缓存

缓存的好处不用多说,在传统的业务开发中,引入缓存可以帮助减轻数据库的压力,在分布式的系统中,引入缓存有两种方式,第一种是在调用者,也就是消费者端引入缓存,如果能够命中缓存,则默认读取缓存中的内容,不需要再进行远程调用,这样就减少了一次IO 请求,也能减少服务提供者的压力;第二种就是在服务提供者提供缓存,同样的请求,把对请求的结果缓存在某个地方,比如Redis,或者java内存中,亦或者第三方的内存容器里,当数据库有更新的时候,同步更新内存,当新的请求在缓存中没有命中的时候,就会击穿缓存落到数据库实例上。
以上就是缓存设计的基本也是最简单的实现方式,不过如何提高缓存的命中率,有很多的算法,有Least Frequently Used(LFU),LeastRecently User(LRU),First in First out(FIFO)等等的算法。
Dubbo也支持缓,Dubbo 提供声明式缓存,并且是在服务消费者实现了缓存,因为Dubbo是一个纯粹的服务调用框架,所以它并没有实现高性能高命中的缓存策略,其实也没有办法实现,因为没有具体的业务场景,如何提高缓存命中率,跟业务是息息相关的,哪些是热点数据,在具体业务中才会知道,所以Dubbo只提供了三种缓存方案.
lru 基于最近最少使用原则删除多余缓存,保持最热的数据被缓存。
threadlocal 当前线程缓存,比如一个页面渲染,用到很多 portal,每个 portal 都要去查用户信息,通过线程缓存,可以减少这种多余访问。
jcache 与 JSR107 集成,可以桥接各种缓存实现

配置

<dubbo:reference interface="com.foo.BarService" cache="lru" />

服务上下文信息

RpcContext服务上下文记录的是当前服务调用过程中所需的环境信息
RpcContext是一个ThreadLocal的临时状态记录器,当接收到RPC请求时,RpcContext的状态都会变化。比如:A调用B,B调用C,则B机器上,在B调用C之前,RpcContext记录的是A调用B的信息,在B调用C之后,RpcContext记录的是B调用C的信息。

服务消费方

服务提供方


通过RpcContext可以进行隐式传参

异步调用

基于NIO的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对于多线程开销较小。


延迟暴露

如果你的服务需要预热时间,比如初始化缓存数据,等待相关资源就位等等,可以使用delay进行延迟暴露。

并发与连接控制(限流)

https://blog.csdn.net/tianyaleixiaowu/article/details/74942405
Dubbo可以对服务的连接和并发数量进行控制。如下:

<dubbo:protocol name="dubbo" port="20881" accepts="100"></dubbo:protocol>

服务降级

什么是服务降级?当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。
本地存根
https://www.cnblogs.com/hzhuxin/p/8250602.html
步骤一、编写服务接口类

public interface UserService {public String findName();public String getUser(String arg);
}

步骤二、编写服务提供者

@Service
public class UserServiceImpl implements UserService {public String findName() {String str = "tom";return str;}public String getUser(String arg){return arg+System.currentTimeMillis();}
}

步骤三、配置服务提供者

<?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:p="http://www.springframework.org/schema/p"xmlns:context="http://www.springframework.org/schema/context"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:property-placeholder location="classpath:properties/*.properties"></context:property-placeholder><dubbo:protocol name="dubbo" port="${port}" accepts="100"></dubbo:protocol><dubbo:application name="dubbo-service"/><dubbo:registry address="zookeeper://192.168.25.128:2181"/><dubbo:annotation package="com.pinyougou.service.impl" />
</beans>

步骤四、编写服务消费者

@RestController
@RequestMapping("/consumer")
public class ConsumerController {@Reference(timeout = 100000,cache = "lru",stub = "")private UserService userService;@RequestMapping("/findName")public String findName(){RpcContext.getContext().setAttachment("username","xxcc");String temp = "";userService.findName();//发送请求,立即返回userService.getUser("rose");return temp;}
}

步骤五、编写本地存根类

public class UserServiceStub implements UserService {private UserService userService;   //远程dubbo的servicepublic UserServiceStub(UserService userService) {this.userService = userService;}public String findName() {try {return  userService.findName();//调用远程}catch (Exception e){//调用本地return "网络延迟,请稍后再试";}}public String getUser(String arg) {try {return userService.getUser(arg);//调用远程}catch (Exception e){//调用本地return "非法用户";}}
}

本地伪装
https://blog.csdn.net/xingfeichen/article/details/80584636
编写本地伪装类Mock,然后在@Reference(mock = “mock类的全路径”)!!

public class BarServiceMock implements UserService {public String findName() {return "network error!!";//友好信息。降级服务信息}public String getUser(String arg) {return "network busing!!";//友好信息。降级服务信息}
}

dubbo过滤器

public class MyFilter implements Filter {public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {System.out.println("请求前************************");Result invoke = invoker.invoke(invocation);//调用请求System.out.println("请求后&&&&&&&&&&&&&&&&&&&&&&&&&");return invoke;}
}

通过@Service(filter = “”)指定使用过滤器!!

集群容错

在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。

各节点关系:

这里的 Invoker 是 Provider 的一个可调用 Service 的抽象,Invoker 封装了 Provider 地址及 Service 接口信息
Directory 代表多个 Invoker,可以把它看成 List ,但与 List 不同的是,它的值可能是动态变化的,比如注册中心推送变更
Cluster 将 Directory 中的多个 Invoker 伪装成一个 Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个
Router 负责从多个 Invoker 中按路由规则选出子集,比如读写分离,应用隔离等
LoadBalance 负责从多个 Invoker 中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选

集群容错模式

可以自行扩展集群容错策略

Failover Cluster

失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。
重试次数配置如下:

<dubbo:service retries="2" />
或
<dubbo:reference retries="2" />
或
<dubbo:reference><dubbo:method name="findFoo" retries="2" />
</dubbo:reference>

Failfast Cluster

快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

Failsafe Cluster

失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

Failback Cluster

失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

Forking Cluster

并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。

Broadcast Cluster

广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。

集群模式配置

按照以下示例在服务提供方和消费方配置集群模式

<dubbo:service cluster="failsafe" />
或
<dubbo:reference cluster="failsafe" />

负载均衡

在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random 随机调用。
可以自行扩展负载均衡策略。
https://blog.csdn.net/lihao21/article/details/54695471

负载均衡策略

Random LoadBalance

随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

RoundRobin LoadBalance

轮循,按公约后的权重设置轮循比率。
存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

LeastActive LoadBalance

最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

ConsistentHash LoadBalance

一致性 Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
缺省只对第一个参数 Hash,如果要修改,请配置 <dubbo:parameter key=“hash.arguments” value=“0,1” />
缺省用 160 份虚拟节点,如果要修改,请配置 <dubbo:parameter key=“hash.nodes” value=“320” />

配置

服务端服务级别

<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作用?
提供RPC远程服务调用方案,实现不同系统之间的通信的,解决分布式部署,soa服务治理解决方案
说说dubbo的实现原理?
你们dubbo使用的是什么注册中心?除了这个还有哪些注册中心?
zookeeper
注册中心挂掉怎么办 ?
服务提供方与服务消费方的通信协议??
服务提供者挂掉怎么办??

关注公众号 程序员壹读 及时获取最新整理技术文档

dubbo简介与配置相关推荐

  1. Java Dubbo:(一)Dubbo 简介

    Dubbo 简介 1.Dubbo 是什么 2.发展历史 3.Dubbo 能做什么 4.Dubbo 产生的背景 1.Dubbo 是什么 Dubbo 官网地址 Dubbo 最早是 Alibaba 开源的分 ...

  2. Nginx 反向代理工作原理简介与配置详解

    Nginx 反向代理工作原理简介与配置详解 测试环境 CentOS 6.8-x86_64 nginx-1.10.0 下载地址:http://nginx.org/en/download.html 安装 ...

  3. MyBatis简介与配置MyBatis+Spring+MySql

    一.MyBatis简介与配置MyBatis+Spring+MySql 原文出自:http://limingnihao.iteye.com/blog/781671 MyBatis学习 之 一.MyBat ...

  4. Dubbo简介与基本概念

    场景 分布式系统的发展演变以及RPC简介: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103555049 Dubbo简介 Ap ...

  5. Flume NG 简介及配置实战

    2019独角兽企业重金招聘Python工程师标准>>> Flume NG 简介及配置实战 博客分类: 分布式计算 1.Flume 的一些核心概念: 1.1 数据流模型 1.2 高可靠 ...

  6. FTP服务的简介和配置详解

    FTP服务的简介和配置详解 注意:配置FTP服务时,最好关闭防火墙和selinux 1.FTP服务简介 FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为& ...

  7. Dubbo场景场景配置用法详解

    前言 对Dubbo常用的场景详解以及配置说明. dubbo配置来源有 JVM参数.外部配置.api配置(xml配置,注解配置).属性文件配置.优先级从高到低,这点是前提. 启动时检查 Dubbo会在启 ...

  8. 深入浅出Mybatis系列(六)---objectFactory、plugins、mappers简介与配置[转]

    上篇文章<深入浅出Mybatis系列(五)---TypeHandler简介及配置(mybatis源码篇)>简单看了一下TypeHandler, 本次将结束对于mybatis的配置文件的学习 ...

  9. 【ASM】udev简介及配置、多路径(multipath)等

    [ASM]udev简介及配置.多路径等 [ASM]Oracle ASM + 11gR2 + RHEL6.5 安装 请参考:http://blog.itpub.net/26736162/viewspac ...

最新文章

  1. 到今天了,今天又结束了
  2. 发现问题,是解决问题的第一步
  3. Question for recommendation system, which is a baseline
  4. python写前端代码_哪种ide能同时写java和前端代码?
  5. c语言编译成功,[C/CPP系列知识] 那些程序C语言可以编译通过但C++无法编译成功 Write a C program that won’t compile in C++...
  6. 面试最后HR都要问一句有没有什么问题要问我?
  7. 分布式认证方案-基于token的认证方式
  8. pytorch教程龙曲良01-05
  9. html提交form预处理,HTML5 之图片上传预处理
  10. ecshop 模板 php代码,ecshop无法在模板文件.dwt和.lbi中直接添加php代码的解决方法...
  11. Android成长日记-Android监听事件的方法
  12. php实现tcp连接的原理,PHP实现TCP实例
  13. python设计小游戏谁先走到17_蜗牛绕墙爬(python小游戏源码)
  14. 灵魂拷问!java数据结构面试题
  15. 初识NB-IoT的机卡绑定
  16. 解决SQL数据库无法附加
  17. GaMD-高斯加速分子动力学模拟中文教程
  18. 质谱的工作原理及发展史
  19. 声势浩大发展云服务的金蝶,如今“破茧”了吗
  20. svn取消文件夹图标_TortoiseSVN文件夹及文件图标不显示解决方案

热门文章

  1. 用计算机图形学画字母,计算机图形学模拟试卷一
  2. php安装时提示dir,php网站安装出现dir
  3. python hist的使用
  4. 抖音创作全攻略 附下载地址
  5. 深度相机---(5)深度相机应用
  6. jupyter notebook切换conda环境时相关报错
  7. 在image2lcd图片取模软件使用中遇到的小问题,和解决方法
  8. zjnu 1744 EKSPLOZIJA(模拟栈)
  9. HBase+Solr 的 二级索引 实时查询
  10. iOS开发笔记 - 语言篇之Swift