目录
架构
zookeeper的简单介绍
简单案例
Dubbo-admin的简单使用
Dubbo高级特性
序列化
地址缓存
超时与重试
多版本
负载均衡
集群容错
服务降级
Dubbo是阿里巴巴开源的一个高性能、轻量级RPC框架
架构
- provider:暴露服务的服务提供方
- container:服务运行容器
- consumer:调用远程服务的服务消费方
- registry:服务注册与发现的注册中心
- monitor:统计服务的调用次数和调用时间的监控中心
zookeeper的简单介绍
Dubbo建议使用Zookeeper作为服务注册中心
Zookeeper安装有两个需要注意的地方,首先是需要修改conf目录下的zoo_sample.cfg文件名,因为Zookeeper的生效配置文件名叫zoo.cfg,其次,需要修改该文件中的数据存放路径,最好和zookeeper安装目录同一路径
zookeeper的启动,去bin目录下执行如下命令
zkServer.sh start
查看zookeeper的状态
./zkServer.sh status
创建一个简单MVC项目后续我们在该项目上添加Dubbo
简单案例
一个Service模块一个Web模块,结构如下
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
}
@Service
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "hello dubbo";
}
}
启动服务查看运行情况
接下来我们在此基础上加入Dubbo的使用
修改Service中的Service注解为dubbo中的注解,原先的Service注解是将UserService注册到Spring中的IOC容器当中,现在我们不需要由Spring管理,而是通过dubbo来远程调用,因此修改此处的Serivce注解
修改application.xml配置文件,添加dubbo的配置
<!--dubbo的项目名称,需要唯一-->
<dubbo:application name="dubbo-service"/>
<!--配置注册中心-->
<dubbo:registry address="zookeeper://192.168.116.128:2181"/>
<!--配置需要扫描@Service注解的包路径-->
<dubbo:annotation package="com.zmt"/>
补全Service的目录结构就可以启动dubbo-service模块了
此时修改dubbo-web模块,首先去掉pom文件中的dubbo-service模块的引用,这时Controller中就会报错,为了避免报错,我们需要在本地创建一个对应的UserSerivce接口来进行注入,但由于不是Spring注入了,我们还需要修改注入注解为Dubbo的远程注入注解
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 1.从注册中心获取userService的访问url
* 2.进行远程调用RPC
* 3.将结果封装为一个代理对象,给变量赋值
* */
@Reference
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
}
这是我们需要在web模块同样添加一份dubbo的配置信息
<!--dubbo的项目名称,需要唯一-->
<dubbo:application name="dubbo-web"/>
<!--配置注册中心-->
<dubbo:registry address="zookeeper://192.168.116.128:2181"/>
<!--配置需要扫描@Service注解的包路径-->
<dubbo:annotation package="com.zmt"/>
修改完毕后,就可以启动web模块了。在启动过程中会报一个错误
这个错误指的是端口占用,这是因为我们是一台机器运行了两个dubbo服务,在生产环境中不会出现这个错误,但是这个错误不会影响程序运行。如果不希望出现该错误信息,我们可以修改dubbo的配置文件,添加一个修改端口的参数即可
<!--dubbo的项目名称,需要唯一-->
<dubbo:application name="dubbo-web">
<dubbo:parameter key="qos.port" value="33333"/>
</dubbo:application>
<!--配置注册中心-->
<dubbo:registry address="zookeeper://192.168.116.128:2181"/>
<!--配置需要扫描@Service注解的包路径-->
<dubbo:annotation package="com.zmt"/>
此时我们的项目结构大致如下
我们实现两个模块调用时,在web层创建了service层的接口,但是在开发时接口可能存在很多,方法也有很多,我们不一定保证在开发时保证不出错,因此,我们存在一个更好的解决方案,那就是再创建一个公共模块,web与service共同依赖该模块,那么结构就变成下面这张图了
新创建一个接口模块
我们将service与web模块中的接口删除,然后在pom文件中引入接口模块,导入接口模块中的接口即可。
Dubbo-admin的简单使用
dubbo-admin管理平台,是图形化的服务管理页面
从注册中心中获取到所有的提供者/消费者进行配置管理
路由规则、动态配置、服务降级、访问控制、权重调整、负载均衡等管理功能
下载完并解压后根据下面步骤进行即可
1、在dubbo-admin-server里面中找到application.properties修改zookeeper的地址
如果修改了需要在dubbo-admin-server目录执行mvn clean install -Dmaven.test.skip=true
2、在dubbo-admin-distribution中找到tager目录下的jar包运行完成后
3、在dubbo-admin-ui中执行npm run dev
Dubbo高级特性
序列化
在开发时,pojo模块里面的实体类都要实现Serializable接口,目的是序列化,传输数据
地址缓存
注册中心挂了的话,服务还是可以进行正常访问的。
原因:dubbo服务消费者在第一次调用时,会将服务提供方地址缓存到本地,以后再调用则不会访问注册中心。当服务提供地址发生改变时,注册中心会通知服务消费者。
超时与重试
服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一直等待下去。在某个峰值时刻,大量请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩,Dubbo利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务访问则自动断开连接。
设置连接超时timeout(默认为1000ms)可以在服务生产方与服务消费方两个地方设置,两个地方都设置timeout的话,服务消费者处的设置优先生效(但不推荐),一般只在服务生产者者里设置超时时间,因为只有服务生产者处知道自己的服务压力是否过大。
连接超时的话,会进行重试操作retries,默认是重试两次,一共发起三次请求
多版本
当我们需要让服务消费者从版本2处获取服务时,dubbo会让一部分用户先使用新功能,用户反馈没问题之后再将所有的用户迁移到新的服务提供方,这称之为灰度发布。dubbo中使用version属性来设置和调用同一个接口的不同版本。
@Service(version = "1.0") //将这个类提供的方法对外发布,将访问的地址ip,端口,路径注册到注册中心
public class UserServiceImpl implements UserService {
@Override
public String sayHello() {
return "hello dubbo";
}
@Override
public User findUserById(int id) {
User user = new User(1, "zhangsan");
return user;
}
}
@RestController
@RequestMapping("/user")
public class UserController {
/**
* 1.从注册中心获取userService的访问url
* 2.进行远程调用RPC
* 3.将结果封装为一个代理对象,给变量赋值
* */
@Reference(version = "1.0")
private UserService userService;
@RequestMapping("/sayHello")
public String sayHello(){
return userService.sayHello();
}
@RequestMapping("/findById")
public User findByUser(int id){
return userService.findUserById(id);
}
}
负载均衡
负载均衡的四种策略:
- Random:根据权重比例随机分配(这个是默认)
- RoundRobin:按权重轮询(1、2、3按着顺序来)
- LeastActive:最少活跃调用数,相同时随机
- ConsistentHash:一致性Hash,相同参数的请求总是发到统一提供者。
集群容错
集群容错模式:
- Failover Cluster:即上面的超时重试。失败重试一般用于读操作,写操作可能会出现多次写入重复
- Failfast Cluster:快速失败,只发起一次调用,通常用于写的操作
- Failsafe Cluster:失败安全,出现异常时,直接忽略,返回一个空结果
- Failback Cluster:失败自动恢复,后台记录失败请求,定时重发
- Forking Cluster:并行调用多个服务器,只要一个成功即返回。
- Broadcast Cluster:广播调用所有的提供者,逐个调用,任意一台报错则报错
服务降级
服务降级:(服务器在挂掉的边缘时,释放一些不重要的服务来维持核心服务的使用)
- mock=force:return null :表示消费方对该服务的方法调用都直接返回null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响
- mock=fail:return null :表示消费方对服务的方法调用在失败后,在返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响