一文上手Dubbo
一文上手Dubbo1 什么是分布式系统把一个系统按模块分拆成多个子系统,每个子系统部署到不同的服务器上,分布式系统就是这些子系统的集合,但对用户是透明的,用户使用时,感觉只是一个系统。2 Dubbo是什么一款高性能的、轻量级的、开源的java RPC框架。就是后台调用后台时用的。3 Dubbo官网http://dubbo.apache.org/zh-cn/4 Zookeeper的作...
一文上手Dubbo
1 什么是分布式系统
把一个系统按模块分拆成多个子系统,每个子系统部署到不同的服务器上,分布式系统就是这些子系统的集合,但对用户是透明的,用户使用时,感觉只是一个系统。
2 Dubbo是什么
一款高性能的、轻量级的、开源的java RPC框架。
就是后台调用后台时用的。
3 Dubbo官网
http://dubbo.apache.org/zh-cn/
4 Zookeeper的作用
注册中心
5 Zookeeper安装
1、 下载zookeeper-3.4.11.tar.gz
2、 解压
3、 配置文件:
1) 将conf文件夹下的zoo_sample.cfg改名为zoo.cfg
2) clientPort=2181(Zookeeper端口号)
3) dataDir=…/data(数据存储路径)
4、 启动Zookeeper,命令:zkServer.cmd(Windows)或 zkServer.sh(Linux)
6 安装Dubbo管理控制台
1、 下载 incubator-dubbo-ops-master.zip(在dubbo的GitHub上找)
2、 解压
3、 使用Maven打包 dubbo-admin工程,生成dubbo-admin-0.0.1-SNAPSHOT.jar
4、 运行:java –jar dubbo-admin-0.0.1-SNAPSHOT.jar
5、 登录:localhost:7001 默认用户名:root 密码:root
注意:管理控制台依赖Zookeeper服务,因此使用此管理控制台,必须开启Zookeeper服务。
7 Maven+Spring工程下使用Dubbo
7.1 总流程
1、将服务提供者注册到注册中心(暴露服务)
1)导入Dubbo依赖(2.6.2) 和 Zookeeper客户端
2)配置服务提供者
2、让服务消费者去注册中心订阅服务提供者
7.2 场景
创建3个工程,分别是 common-server、user-server、order-server
common-server 用于存放所有的 bean 和 service 接口
user-server 是服务提供者
order-server 是服务消费者
7.3 提供者端步骤
7.3.1 编写Service接口和实现类
com.hongyu.dubbo.service.UserService
com.hongyu.dubbo.service.impl.UserServiceImpl
7.3.2 引入Dubbo依赖和Zookeeper客户端依赖
<!-- 引入Dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- 引入操作Zookeeper的客户端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
7.3.3 Spring中配置Dubbo
<!-- 1、指定当前应用的名字 (同样的服务名字相同,不同的服务名字不同) -->
<dubbo:application name="user-service"/>
<!-- 2、指定注册中心的位置 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 或者这么写也行
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" />
-->
<!-- 3、指定通信规则 通信协议?通信端口 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 4、暴露服务 ref:指向服务的实现 -->
<dubbo:service interface="com.hongyu.dubbo.service.UserService"
ref="userServiceImpl" />
<!-- 服务的实现 -->
<bean id="userServiceImpl"
class="com.hongyu.dubbo.service.impl.UserServiceImpl" />
7.4 消费者端步骤
7.4.1 编写Service接口和实现类
com.hongyu.dubbo.service.OrderService
com.hongyu.dubbo.service.impl.OrderServiceImpl
7.4.2 将UserService接口拷贝到消费者工程
注意:接口所在的包不能变
也可以把接口和bean单独放在一个单独的工程中
7.4.3 在实现类中依赖注入UserService
@Autowired
private UserService userService;
7.4.4 引入Dubbo依赖和Zookeeper客户端依赖
<!-- 引入Dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<!-- 引入操作Zookeeper的客户端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
7.4.5 Spring中配置Dubbo
<context:component-scan base-package="com.hongyu.dubbo" />
<!-- 1、指定当前应用的名字 (同样的服务名字相同,不同的服务名字不同) -->
<dubbo:application name="order-service"/>
<!-- 2、指定注册中心的位置 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- 或者这么写也行
<dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" />
-->
<!-- 声明需要调用的远程服务的接口 生成远程服务代理 -->
<dubbo:reference id="userService"
interface="com.hongyu.dubbo.service.UserService" />
7.4.6 将OrderService也放入Spring容器
@ org.springframework.stereotype.Service
public class OrderServiceImpl implements OrderService {
@Autowired
private UserService userService;
7.4.7 验证
先启动user-server服务
再启动order-server服务
调用order-server的Service接口方法,order-server再远程RPC调用user-service的方法
如果能拿到结果,证明配置成功,否则配置失败
此时查看Dubbo控制台,可以看到有一个提供者和一个消费者
8 安装Dubbo监控中心
1、 下载 incubator-dubbo-ops-master.zip(在dubbo的GitHub上找)
2、 解压
3、 使用Maven打包 dubbo-monitor-simple工程,生成dubbo-monitor-simple-2.0.0.jar 和 dubbo-monitor-simple-2.0.0-assembly.tar.gz
4、 解压 dubbo-monitor-simple-2.0.0-assembly.tar.gz 文件
5、 修改 conf/ dubbo.properties
dubbo.registry.address=zookeeper://127.0.0.1:2181
6、 运行: assembly.bin/start.bat
7、 验证:http://localhost:8080/
8、 在提供者和消费者工程的Spring文件中配置监控中心
<!-- 发现监控中心 自动发现 -->
<dubbo:monitor protocol="registry" />
<!-- 或者这么写,指定监控中心的地址
<dubbo:monitor address="127.0.0.1:7070" />
-->
9 Dubbo与SpringBoot整合
9.1 创建提供者和消费者的Springboot工程
略
9.2 在提供者和消费者的pom.xml文件中引入Dubbo依赖
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
9.3 配置提供者的application.properties文件
dubbo.application.name=boot-user-service
dubbo.registry.protocol=zookeeper
dubbo.registry.address=127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.monitor.protocol=registry
9.4 提供者在需要暴露接口的Service实现类上,加入注解
@org.springframework.stereotype.Component
@com.alibaba.dubbo.config.annotation.Service
9.5 配置消费者的application.properties文件
dubbo.application.name=boot-order-service
dubbo.registry.protocol=zookeeper
dubbo.registry.address=127.0.0.1:2181
dubbo.monitor.protocol=registry
server.port=8081
9.6 在消费者的Service中引入提供者的Service接口
@com.alibaba.dubbo.config.annotation.Reference
private UserService userService;
9.7 在提供者和消费者的SpringBoot启动类中加入@EnableDubbo注解
@com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo
10 Dubbo配置提取优先级
1、 取Java虚拟机参数,例如:-Ddubbo.protocol.port=20883
2、 取spring配置文件
3、 取 dubbo.properties
11 配置消费者启动时不检查远程的Service引用
Spring配置文件中,引用的标签加入 check=”false”
<dubbo:reference id="userService"
interface="com.hongyu.dubbo.service.UserService" check="false" />
<!—统一配置消费者策略 -->
<dubbo:consumer check="false" />
<!— 注册中心是否存在,也可以启动时不检查 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" check=”false” />
12 Dubbo的超时设置
默认是1秒
<!-- 声明需要调用的远程服务的接口 生成远程服务代理 设置3秒超时 -->
<dubbo:reference id="userService"
interface="com.hongyu.dubbo.service.UserService" timeout="3000" />
<!-- 声明需要调用的远程服务的接口 生成远程服务代理 -->
<dubbo:reference id="userService"
interface="com.hongyu.dubbo.service.UserService" timeout="4000">
<!-- 超时也可以设置在方法上 -->
<dubbo:method name="getUserAddressList" timeout="3000" />
</dubbo:reference>
配置的优先级:
方法级优先,接口级次之,全局配置再次之。
级别一样,则消费方优先,提供方次之
13 Dubbo的重试次数设置
重试次数不包含第1次调用
<dubbo:reference id="userService"
interface="com.hongyu.dubbo.service.UserService" timeout="4000" retries="3">
优先级与超时相同
如果同一服务起了多个副本,则会重试不同的副本
通常幂等方法中会设置重试,非幂等方法通常不设置重试
14 Dubbo的多版本
14.1 作用
实现灰度发布,只升级部分机器,防止新版本的不稳定
14.2 配置步骤
14.2.1 提供者暴露多个版本的接口
在Spring配置文件中配置:
<!-- 4、暴露服务 ref:指向服务的实现 -->
<dubbo:service interface="com.hongyu.dubbo.service.UserService"
ref="userServiceImpl01" version="1.0.0" />
<!-- 服务的实现 -->
<bean id="userServiceImpl01"
class="com.hongyu.dubbo.service.impl.UserServiceImpl" />
<!-- 4、暴露服务 ref:指向服务的实现 -->
<dubbo:service interface="com.hongyu.dubbo.service.UserService"
ref="userServiceImpl02" version="2.0.0" />
<!-- 服务的实现 -->
<bean id="userServiceImpl02"
class="com.hongyu.dubbo.service.impl.UserServiceImpl2" />
14.2.2 消费者引用时指定版本号
在Spring配置文件中配置:
<dubbo:reference id="userService"
interface="com.hongyu.dubbo.service.UserService" timeout="4000" retries="3"
version="2.0.0" />
version 属性指定为 * ,则随机访问所有版本
15 Dubbo的本地存根
15.1 概述
消费者端对远程调用的接口进行二次封装,做一些校验等额外工作。
15.2 具体步骤
15.2.1 创建存根类
com.hongyu.dubbo.service.impl.UserServiceStub
15.2.2 实现提供者的UserService接口
public class UserServiceStub implements UserService {
15.2.3 将提供者的接口作为成员变量并在构造方法中注入
public class UserServiceStub implements UserService {
private UserService userService;
/**
* 传入的是UserService的远程代理对象
* @param userService
*/
public UserServiceStub(UserService userService) {
this.userService = userService;
}
15.2.4 实现对应的方法逻辑
@Override
public List<UserAddress> getUserAddressList(String userId) {
System.out.println("进入UserService存根");
if(StringUtils.isBlank(userId)) {
System.out.println("存根条件不符合");
return new ArrayList<>();
}
System.out.println("执行远程调用");
return userService.getUserAddressList(userId);
}
15.2.5 Spring中配置存根
<!-- 声明需要调用的远程服务的接口 生成远程服务代理 -->
<dubbo:reference id="userService"
interface="com.hongyu.dubbo.service.UserService"
timeout="4000" retries="3" version="*"
stub="com.hongyu.dubbo.service.impl.UserServiceStub">
<!-- 超时也可以设置在方法上 -->
<dubbo:method name="getUserAddressList" timeout="3000" />
</dubbo:reference>
16 Dubbo与SpringBoot整合的其他方式
16.1 三种方式
16.1.1 第一种:在Spring配置文件中配置Dubbo属性
导入 dubbo-starter,在application.properties配置属性,使用@Service暴露服务,使用@Reference引用服务,在SpringBoot启动类加上@EnableDubbo注解
16.1.2 第二种:在原生Dubbo配置文件中配置Dubbo属性
保留Dubbo配置文件,同样需要导入 dubbo-starter
将配置Dubbo属性的Spring文件拷贝到Springboot工程,然后在启动文件处引用。并且删除@EnableDubbo注解
@ImportResource(locations = "classpath:provider.xml")
//@EnableDubbo(scanBasePackages = {"com.hongyu.dubbo"})
@SpringBootApplication(scanBasePackages = {"com.hongyu.dubbo"})
public class BootUserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(BootUserServiceApplication.class, args);
}
}
注意:有一些配置只在Spring配置文件中才能配,注解实现不了,例如在暴露的方法的上配置属性
16.1.3 第三种 使用注解API的方式(写一个配置类)
同样需要导入 dubbo-starter
写一个Dubbo的配置类,例如com.hongyu.dubbo.config.MyDubboConfig
package com.hongyu.dubbo.config;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyDubboConfig {
/**
* <dubbo:application name="user-service"/>
* @return
*/
@Bean
public ApplicationConfig applicationConfig() {
ApplicationConfig config = new ApplicationConfig();
config.setName("boot-user-service");
return config;
}
/**
* <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
* @return
*/
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("zookeeper://127.0.0.1:2181");
return registryConfig;
}
/**
* <dubbo:protocol name="dubbo" port="20882" />
* @return
*/
@Bean
public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(20884);
return protocolConfig;
}
/**
* <dubbo:monitor protocol="registry" />
*/
@Bean
public MonitorConfig monitorConfig() {
MonitorConfig monitorConfig = new MonitorConfig();
monitorConfig.setProtocol("registry");
return monitorConfig;
}
}
暴露接口,还是使用 @com.alibaba.dubbo.config.annotation.Service 注解
需要在Springboot启动类配置包扫描
@EnableDubbo(scanBasePackages = {“com.hongyu.dubbo”})
17 Dubbo高可用
17.1 缓存机制
当注册中心,例如Zookeeper宕机后,如果消费者访问过一次提供者,则消费者会缓存提供者的地址,提供者地址不变的情况下,仍然可以访问。
17.2 可以直连
可以不通过Zookeeper,直连提供者
@Reference(url=”127.0.0.1:80885”)
private UserService userService;
(多版本的情况下,可能会失效,也不推荐用这种方式)
17.3 负载均衡机制
17.3.1 Random
随机策略,可配权重,权重越高被调用的几率越大
17.3.2 RoundRobin
轮询,可配权重,权重越高被轮询到的次数越多
例如:
3台机器,第一台权重是100,第二台是200,第三台是50
则第一台的访问几率是 100/(100+200+50) = 2/7
则第二台的访问几率是 200/(100+200+50) = 4/7
则第三台的访问几率是 50/(100+200+50) = 1/7
按轮询的机制,机器被访问的顺序是 1 2 3 1 2 2 2
因为是轮询,所以是按顺序访问,但有权重,当第6次访问时,发现3号机已没有几率,然后发现1号机也没有几率了,所以访问了2号机,以此类推
17.3.3 LeastActive
最少活跃调用数,在调用接口后,会记录响应时间,始终访问响应最快的机器
17.3.4 ConsistentHash
一致性Hash
将某一属性的值,进行Hash计算,Hash值相同,会始终访问同一台机器。
17.4 设置负载均衡策略
默认是随机策略
在提供者的暴露处或消费者的引用处制定负载均衡策略
loadbalance = RandomLoadBalance.NAME
loadbalance = RoundRobinLoadBalance.NAME
loadbalance = LeastActiveLoadBalance.NAME
17.5 设置权重
在暴露接口的Service注解中设置,@Service(version = "2.0.0", weight = 100)
或者使用管理控制台设置
17.6 服务降级
可以在控制台,把消费者端某个接口屏蔽,则直接返给客户端的是空页面
把消费者某个接口设置为容错,则在超时等访问失败时,返回为空
(多版本的情况下,会失效)
17.7 服务容错
17.7.1 配置重试
通过前面说的配置重试次数,可以切换到不同的服务器重试
17.7.2 集群容错模式
17.7.2.1 Failover Cluster
失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次)。
重试次数配置如下:
<dubbo:service retries="2" />
或
<dubbo:reference retries="2" />
或
<dubbo:reference>
<dubbo:method name="findFoo" retries="2" />
</dubbo:reference>
17.7.2.2 Failfast Cluster
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
17.7.2.3 Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
17.7.2.4 Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
17.7.2.5 Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=“2” 来设置最大并行数。
17.7.2.6 Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。
17.7.3 集群模式配置
按照以下示例在服务提供方和消费方配置集群模式
<dubbo:service cluster="failsafe" />
或
<dubbo:reference cluster="failsafe" />
默认是 Failover Cluster
17.8 整合Hystrix进行容错
17.8.1 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
17.8.2 启动类上加上@EnableHystrix
17.8.3 需要降级的方法上增加@HystrixCommand注解
@HystrixCommand(fallbackMethod = "hello")
public List<UserAddress> getUserAddressList(String userId)
// fallbackMethod是设置回调方法,该方法的参数和返回值都可以和降级的方法一样
17.8.4 编写hello方法
public List<UserAddress> hello(String userId) {
List<UserAddress> list = new ArrayList<>();
list.add(new UserAddress(1, "11","11" ,"11","11","Y"));
return list;
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)