Xml配置
服务提供者
导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.3</version>
</dependency>
配置文件
<!--1、指定当前服务/应用名字-->
<dubbo:application name="user-service-provider"></dubbo:application>
<!--2、指定注册中心位置-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<!--3、指定通信规则(协议,端口)-->
<dubbo:protocol name="dubbo" port="20880"></dubbo:protocol>
<!--4、暴露服务-->
<dubbo:service interface="com.zhijia.gmall.service.UserService" ref="userServiceImpl"
version="1.0.0"
></dubbo:service>
<!--dubbo包扫描,使用注解时可以使用-->
<!--dubbo:annotation packge= "com.zhijia.gmall.service.impl.UserServiceImpl"></dubbo:annotation-->
<!--服务实现-->
<bean id="userServiceImpl" class="com.zhijia.gmall.service.impl.UserServiceImpl"></bean>
服务消费者
xml配置文件
<dubbo:application name="order-service-consumer"></dubbo:application>
<dubbo:registry address="zookeeper://127.0.0.1:2181"></dubbo:registry>
<!--声明要调用的远程服务接口:生成远程服务代理-->
<dubbo:reference interface="com.zhijia.gmall.service.UserService" id="userService"
version="*" stub="com.zhijia.gmall.service.UserServiceStub">
</dubbo:reference>
注解配置
引入依赖
注:以下依赖均没有设置版本
<dependencies>
<!-- dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper</artifactId>
<type>pom</type>
</dependency>
<!-- dubbo starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- spring starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
配置application.yml
dubbo:
application:
name: dubbo-springboot-demo-provider #服务名称
protocol:
name: dubbo #通讯协议
port: -1 #端口
registry:
id: zk-registry #注册服务id
address: zookeeper://127.0.0.1:2181 #注册地址
config-center:
address: zookeeper://127.0.0.1:2181 #配置中心地址
metadata-report:
address: zookeeper://127.0.0.1:2181 #元数据中心
暴露服务
通过DubboService注解将 service 关联到上文定义的特定注册中心
@DubboService(registry="zk-registry")
//设置参数
@DubboService(version = "1.0.0", group = "dev", timeout = 5000)
public class DemoServiceImpl implements DemoService {}
通过 Java Config 配置进行关联也是同样道理
@Configuration
public class ProviderConfiguration {
@Bean
public ServiceConfig demoService() {
ServiceConfig service = new ServiceConfig();
service.setRegistry("zk-registry");
return service;
}
}
引入服务提供者
@Component
public class DemoClient {
@DubboReference
private DemoService demoService;
}
开启dubbo服务
@SpringBootApplication
@EnableDubbo
public class ProviderApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(ProviderApplication.class, args);
}
}
dubbo高级特性
配置原则
JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。
XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效。
Properties 最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,比如应用名。
重试次数
服务调用失败可以使用,不过考虑幂等性问题,一般不用于新增业务类接口
<dubbo:service retries="2" />
或
<dubbo:reference retries="2" />
或
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>
超时时间
由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。默认超时时间为1秒(1000)
<!--check:不检查服务 timoout:超时时间 retries:重试次数-->
<dubbo:consumer check="false" timeout="2000" retries="3"></dubbo:consumer>
Dubbo消费端
全局超时配置
<dubbo:consumer timeout="5000" />
指定接口以及特定方法超时配置
<dubbo:reference interface="com.foo.BarService" timeout="2000">
<dubbo:method name="sayHello" timeout="3000" />
</dubbo:reference>
Dubbo服务端
全局超时配置
<dubbo:provider timeout="5000" />
指定接口以及特定方法超时配置
<dubbo:provider interface="com.foo.BarService" timeout="2000">
<dubbo:method name="sayHello" timeout="3000" />
</dubbo:provider>
配置原则
- 方法级配置别优于接口级别,即小Scope优先
- Consumer端配置 优于 Provider配置 优于 全局配置,
多版本配置
<!--暴露服务-->
<dubbo:service interface="com.zhijia.gmall.service.UserService" ref="userServiceImpl"
version="1.0.0"
></dubbo:service>
<!--多版本-->
<dubbo:service interface="com.zhijia.gmall.service.UserService" ref="userServiceImpl2"
version="2.0.0"
></dubbo:service>
<bean id="userServiceImp2" class="com.zhijia.gmall.service.impl.UserServiceImpl2"></bean>
<!--服务实现-->
<bean id="userServiceImpl" class="com.zhijia.gmall.service.impl.UserServiceImpl"></bean>
随机调用版本
<!--声明要调用的远程服务接口:生成远程服务代理-->
<dubbo:reference interface="com.zhijia.gmall.service.UserService" id="userService"
version="*"></dubbo:reference>
负载均衡
在服务提供者上加上属性@Reference(loadbalance=”random”)
- Random:按权重随机,默认的机制,按权重值随机访问
- RoundRobin:按权重轮询
- LeastActive:最小活跃调用数,调用响应最快的,相同活跃数则随机访问
- ConsistonHash:一致性hash,相同参数的请求总是发送到同一提供者
集群容错模式
在服务提供者上加上属性@Reference(cluster =”failover”)
- Failover Cluster: 失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。
- Failfast Cluster: 快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
- Failsafe Cluster: 失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
- Failback Cluster: 失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
- Forking Cluster: 并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。
- Broadcast Cluster: 广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。
服务降级
特性说明
推荐使用相关限流降级组件(如 Sentinel)以达到最佳体验。参考示例实践:微服务治理/限流降级
服务降级是指服务在非正常情况下进行降级应急处理。
使用场景
某服务或接口负荷超出最大承载能力范围,需要进行降级应急处理,避免系统崩溃
调用的某非关键服务或接口暂时不可用时,返回模拟数据或空,业务还能继续可用
降级非核心业务的服务或接口,腾出系统资源,尽量保证核心业务的正常运行
某上游基础服务超时或不可用时,执行能快速响应的降级预案,避免服务整体雪崩
使用方案:
<dubbo:reference id="demoService" interface="com.xxx.service.DemoService" mock="return" />
<dubbo:reference id="demoService" interface="com.xxx.service.DemoService" mock="return null" />
<dubbo:reference id="demoService" interface="com.xxx.service.DemoService" mock="fail:return aaa" />
<dubbo:reference id="demoService" interface="com.xxx.service.DemoService" mock="force:return true" />
<dubbo:reference id="demoService" interface="com.xxx.service.DemoService" mock="fail:throw" />
<dubbo:reference id="demoService" interface="com.xxx.service.DemoService" mock="force:throw java.lang.NullPointException" />
dubbo高可用
现象:zookeeper注册中心宕机,还可以消费dubbo暴露的服务。
原因:
- 监控中心宕掉不影响使用,只是丢失部分采样数据
- 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
- 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
- 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
- 服务提供者无状态,任意一台宕掉后,不影响使用
- 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
RPC原理
一次完整的RPC调用流程(同步调用,异步另说)如下:
1)服务消费方(client)调用以本地调用方式调用服务;
2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
3)client stub找到服务地址,并将消息发送到服务端;
4)server stub收到消息后进行解码;
5)server stub根据解码结果调用本地的服务;
6)本地服务执行并将结果返回给server stub;
7)server stub将返回结果打包成消息并发送至消费方;
8)client stub接收到消息,并进行解码;
9)服务消费方得到最终结果。
RPC框架的目标就是要2~8这些步骤都封装起来,这些细节对用户来说是透明的,不可见的。
dubbo原理
dubbo原理 -框架设计
config 配置层:对外配置接口,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类
proxy 服务代理层:服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 以 ServiceProxy 为中心,扩展接口为 ProxyFactory
registry 注册中心层:封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactory, Registry, RegistryService
cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalance
monitor 监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory, Monitor, MonitorService
protocol 远程调用层:封装 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter
exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec
serialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool