Dubbo之高级特性
Dubbo
- 注意
当启动服务时,该服务会占用本机一个端口号,故在一台电脑启动多个服务时需要在配置文件中更占用本机的端口号
<!--服务占用本机的端口-当本机启动多个服务时须保持不同-->
<dubbo:protocol port=""/>
<!--dubbo的配置-->
<!--1.配置项目的名称,唯一-->
<dubbo:application name="dubbo-service"/>
<!--2.配置注册中心的地址-->
<dubbo:registry address="zookeeper://192.168.23.129:2181" timeout="250000"/>
<!--3.配置dubbo包扫描,注解注册服务-->
<!-- <dubbo:annotation package="com.yh1.impl" />-->
<!--3.2xml配置方式注册服务,类上不需要注解-->
<dubbo:service interface="com.yh.ours.UserService" ref="demoService"/>
<bean id="demoService" class="com.yh1.impl.UserServiceImpl"/>
序列化
查询出数据后返回给消费者时所执行的便是序列化
- 作用:用于不同机器间传输对象的转换,将对象序列化为 流数据进行传输
- 被序列化的对象类必须实现序列化接口Serializable
- 接受到流数据后,反序列化为java对象
- 序列化和反序列化两者皆需要用到对象类,故定义在一个独立模块中,让两者依赖它—>类似于公共接口模块
- 即domain/pojo实体类皆需要实现接口Serializable且放在独立模块来作为资源被依赖
<groupId>org.yh</groupId>
<artifactId>debbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<!--被依赖资源-->
<dependency>
<groupId>org.yh</groupId>
<artifactId>dubbo-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
序列化和反序列化操作dubbo已经封装好,只需让pojo类实现接口即可
eg:
//必须实现Serializable
//一个实体类用于 模仿序列化和反序列化操作
public class User implements Serializable {
int id;
String name;
public User() {
}
public User(int id, String name) {
this.id = id;
this.name = name;
}
//省略get和set方法
Cotroller代码
@RequestMapping("/find.do")
public User find(int id){
return userService.findById(id);
}
地址缓存
问:注册中心挂了,服务是否可以正常访问?
答:可以,当第一次访问后,会将服务地址缓存至本地
但是当服务的地址变了以后就不行了,需要重新访问注册中心获取
超时和重试
超时
问:消费者创建线程调用提供者服务,如果调用失败或者提供者查询时间过长或挂了,则消费者将一直等待
- 可以在服务者方法中使用线程沉睡来模拟上述情况
@Service
public class UserServiceImpl implements UserService {
@Override
public User findById(int id) {
//此处让服务睡5秒,用来演示超时操作
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
User user=new User(1,"jack");
return user;
}
}
解决:设置timeout属性值来控制超时时间
- 在消费方@reference注解中设置
- 在提供者@service注解中设置
- 在配置文件中配置
<!--2.配置注册中心的地址-->
<dubbo:registry address="zookeeper://192.168.23.129:2181" timeout="250000"/>
- 建议配置在服务提供方@Service上
- 超时时消费者报错如下
重试
问题:出现了网络抖动网突然断了一下,断了3s超时时间设置是1s,则这一次请求就会失败,则会重新发送请求,一共发送3次
解决1:通过retries属性类设置重试次数。默认为2
多版本
灰度发布:新功能时,让一部分用户使用新版本,稳定后让全部用户使用新的版本。
使用:使用version属性来设置和调用同一个接口的不同版本
eg:公共接口模块中的UserService接口在服务提供者中有俩实现类UserServiceImpl1和UserServiceImpl2
在服务提供者的UserServiceImpl1@Service(version=“v1.0”)中设置version和UserServiceImpl2@Service(version=“v2.0”)
在消费者的@Reference(version=“v1.0 or v2.0”)中设置version来选择使用哪个版本
注:此处检验失败,原因未知
负载均衡
适用于集群环境,相同的服务部署在多台机器上
模拟步骤:
1.在服务提供者的@Service注解中添加weight属性,配置权重(可在服务内打印一句话来区别不同的服务)
2.启动该服务tomcat7:run
3.更改三个端口号后继续1,2,3步骤,直至启动三个服务器为止,保持权重不同
4.在消费者的@reference注解中配置loadbalance属性(共有四个值下面有)
5.启动服务,开始模拟
- 负载均衡策略(4种):来解决访问哪个机器
可以更改同一个服务的tomcat,dubbo的qos,本机三个的端口来模拟同一服务部署在多台机器
1.
<!--tomcat插件-->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>8000</port>
<path>/</path>
</configuration>
</plugin>
2.
<dubbo:protocol port="20881"/>
3.
<!--dubbo的配置-->
<!--1.配置项目的名称,唯一-->
<dubbo:application name="dubbo-service">
<!--dubbo的pos服务一个服务会启动一次,故一台机器时不同服务需要更改-->
<dubbo:parameter key="qos.port" value="33331"/>
</dubbo:application>
- 权重weight是服务提供者@Service注解的配置属性
- Random按权重weight属性随机。按权重设置随机概率
- RoundRobin按权重轮询
- LeastActice最少活跃调用数,相同则随机–>使用机器中处理请求最快的的机器
- ConsisitentHash:一致性Hash,相同参数的请求总是发到同一提供者
- 在消费者的@Reference注解中使用loadbalance属性(该属性值为loadbalance抽象类的四种实现类属性即上的小写)来设置采用上述哪种负载均衡策略
集群容错
问题: 消费者调用集群中某一机器出错了,该如何处理?
- 集群容错模式:
- **Failover Cluster:**失败重试。默认值。当出现失败,重试其它服务器,默认重试2次,使用retries配置。–一般用于读操作
- **Failfast Cluster 😗*快速失败,发起-次调用,失败立即报错。–通常用于写操作。
- **Failsafe Cluster:**失败安全,出现异常时,直接忽略。返回一个空结果。–用于写一些不重要的日志结果
- **Failback Cluster:**失败自动恢复,后台记录失败请求,定时重发。
- **Forking Cluster 😗*并行调用多个服务器,只要一个成功即返回。–耗性能
- Broadcast Cluster: 广播调用所有提供者,逐个调用,任意一台报错则报错。–同步要求较高时使用,如同时更新三个机器上的数据
- 在消费者的@Reference注解中使用cluster属性(该属性值为cluster抽象类的四种实现类属性即上的小写)来设置采用上述哪种集群容错策略
服务降级
场景描述:
- 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作
- 服务降级方式:
-
mock= force:return null:表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
-
mock=fail:return null:表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响
- 只需在消费方配置
@Reference(mock =“ force :return null")
private UserService userService;