基础环境搭建
刚入门的同学搭建初级dubbo环境。代码没有截图,方便想要动手试试的同学复制一些基础代码,可以模仿用户服务写一些自己的服务。
架构说明
注:订单服务的命名是方便后期做负载均衡使用
工程代码
1.父工程pom文件的关键依赖
<properties>
<dubbo.version>2.7.8</dubbo.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.dubbo-entity实体类
2.1 pom文件
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
</dependencies>
2.2 User实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = -5667192931247425035L;
private Long id;
private String name;
private String password;
}
2.3 Order实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Order implements Serializable {
private static final long serialVersionUID = 101782438579766279L;
private Long id;
private String orderNo;
}
3.dubbo-interface服务接口
3.1 pom依赖
<dependencies>
<dependency>
<groupId>org.example</groupId>
<artifactId>dubbo-entity</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
3.2 订单接口IOrderService.class
public interface IOrderService {
// 获取订单列表
List<Order> getOrderList();
}
3.3 用户接口IUserService
public interface IUserService {
// 获取用户列表
List<User> getUseList();
}
4. dubbo-user-service用户服务
4.1 pom依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<dependency>
<groupId>org.example</groupId>
<artifactId>dubbo-interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.5</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>
</dependencies>
4.2 主启动类(扫描包根据个人实际情况配置)
@SpringBootApplication
@EnableDubbo(scanBasePackages = "com.itman.dubbo.user.service")
public class UserServiceMain {
public static void main(String[] args) {
SpringApplication.run(UserServiceMain.class, args);
}
}
4.3 服务实现类(原本的dubbo的@Service注解已经过时,由@DubboService替代)
@DubboService
public class IUserServiceImpl implements IUserService {
@Override
public List<User> getUseList() {
List<User> userList = new ArrayList<>();
userList.add(new User(1L, "德玛西亚之力", "123456"));
userList.add(new User(2L, "德玛西亚皇子", "123456"));
return userList;
}
}
4.4 application.yml配置文件(参数比较多,了解为主,主要是针对后期的一些优化,目前全部取默认值)
server:
port: 9001
dubbo:
application:
name: dubbo-user-service # 应用名称,必填
registry:
address: zookeeper://localhost:2181 # 注册中心服务器地址,集群以逗号分隔
protocol:
name: dubbo # 协议名称,必填
port: 20881 # 协议缺省端口,dubbo默认端口为20880,未配置则为默认端口
provider:
threadpool: fixed # 线程池类型,fixed/cache,默认fixed
threads: 200 # 服务线程池大小,默认200
payload: 8388608 # 请求或响应的数据包大小,单位字节,默认8M(8388608=8M)
filter: -exception # 服务提供方远程调用过程拦截器名称,多个名称用逗号分隔
accepts: 1000 # 服务提供者最大可接受连接数
delay: -1 # 延迟注册服务时间(毫秒)- ,设为-1时,表示延迟到Spring容器初始化完成时暴露服务
timeout: 1000 # 远程服务调用超时时间(毫秒),默认1000
retries: 0 # 远程服务调用重试次数,不包括第一次调用,不需要重试请设为0,默认为2
connections: 100 # 对每个提供者的最大连接数
loadbalance: random # 负载均衡策略,可选值:random,roundrobin,leastactive,分别表示:随机,轮询,最少活跃调用
weight: 10 # 服务权重
executes: 100 # 服务提供者每服务每方法最大可并行执行请求数
actives: 100 # 每服务消费者每服务每方法最大并发调用数
charset: UTF-8 # 序列化编码
buffer: 8192 # 网络读写缓冲区大小
5. dubbo-order-service8001订单服务
同用户服务。配置文件需要修改端口号,应用名称,协议缺省端口,其余参数可以不配,也可以直接复用。
6.dubbo-consumer消费者
6.1 pom文件依赖
同用户服务。
6.2 UserController.class
@RestController
@RequestMapping("/user")
public class UserController {
@Resource
private UserService userService;
@GetMapping("/list")
public List<User> getUserList(){
return userService.getUserList();
}
}
6.3 UserService.class(原本的dubbo的@Reference注解已经过时,由@DubboReference替代)
@Service
public class UserService {
@DubboReference
private IUserService userService;
public List<User> getUserList(){
return userService.getUseList();
}
}
项目启动
1 下载并启动zookeeper(windows方式)
下载地址: https://downloads.apache.org/zookeeper/
启动: 进入zookeeper的bin文件夹下,双击zkServer.cmd即可
2 启动项目
先启动用户和订单服务,再启动消费者。目前未关闭启动检查(后面有介绍),所以必选先启动服务,再启动消费者,否则启动消费者启动时找不到服务会报错.
搭建dubbo-admin
1 下载源码
下载地址: https://github.com/apache/dubbo-admin
2 生成dubbo-admin的jar包,以前前端环境部署
根据github的说明文档,编译打包dubbo-admin-server-0.2.0-SNAPSHOT.jar,并且启动dubbo-admin-ui。
3 下面最终结果(登录的账号密码默认是root,root,这个可以在dubbo-admin-develop\dubbo-admin-server\src\main\resources\application.properties进行修改)
4 dubbo-admin-ui可以使用npm run build进行编译,生成的包可以利用nginx代理进行部署
相关配置
这里只列举几个,详细的可以去官网查询
1 启动检查(消费者启动,检查服务是否存在)
dubbo.consumer.check = false, 启动时检查提供者是否存在,true报错,false忽略
dubbo.registry.check = true, 注册中心不存在时,是否报错,true报错
也可以在注解中配置是否检查@DubboReference(check = false)
2 超时时间配置
dubbo.provider.timeout = 1000,服务提供方,远程服务调用超时时间(毫秒),默认1000
dubbo.consumer.timeout = 1000,服务消费方,远程服务调用超时时间(毫秒),默认1000
也可以在注解中配置超时时间@DubboReference(timeout = 1000)
覆盖策略:
精确优先: 方法级优先,接口级次之,全局配置再次之
消费者优先: 消费方优先,提供方次之
建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置
3 重试次数
dubbo.provider.retries = 2,远程服务调用重试次数,不包括第一次调用,不需要重试请设为0,默认为2
dubbo.consumer.retries = 2,远程服务调用重试次数,不包括第一次调用,不需要重试请设为0,默认为2
消费方和提供方都可以配置。如果提供方有多个,会重试其他提供方
使用场景:
幂等操作: 设置重试次数(幂等是方法重复调用多次,结果都是一样的,例如查询,修改,删除)
非幂等操作: 不能设置重试次数(非幂等是方法重复调用多次,会产生新的数据,例如新增)
4 本地存根
远程服务后,客户端通常只剩下接口,而实现全在服务器端,但提供方有些时候需要在客户端也执行部分逻辑,为服务端减少一些不必要的请求。比如:提前验证参数,调用失败后伪造容错数据等等,此时就需要在 API 中带上 Stub,客户端生成 Proxy 实例,会把 Proxy 通过构造函数传给 Stub [1],然后把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。
消费方添加的本地存根,Stub 必须有可传入 Proxy 的构造函数。
public class OrderServiceStub implements IOrderService {
private final IOrderService orderService;
/**
* 传入的是IOrderService的远程代理对象
* @param orderService
*/
public OrderServiceStub(IOrderService orderService) {
this.orderService = orderService;
}
@Override
public List<Order> getOrderList() {
return orderService.getOrderList();
}
@Override
public List<Order> getOrderByUserId(Long userId) {
System.out.println("OrderServiceStub getOrderByUserId------a");
if (!ObjectUtils.isEmpty(userId)){
System.out.println("OrderServiceStub getOrderByUserId------b");
return orderService.getOrderByUserId(userId);
}
System.out.println("OrderServiceStub getOrderByUserId------c");
return null;
}
}
高可用
1 zookeeper宕机与dubbo直连
1.1 zookeeper宕机
问题:zookeeper注册中心宕机,还可以消费dubbo暴露的服务
原因:
① 监控中心宕掉不影响使用,只会丢失采样数据
② 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新的服务
③ 注册中心对等集群,任意一台宕机后,将自动切换到另一台
④ 注册中心全部宕机后,服务提供者和服务消费者仍能通过本地缓存通讯
⑤ 服务提供者任意一台宕机,不影响使用
⑥ 服务提供者全部宕机,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
高可用:通过设计,减少系统不能提供服务的时间
1.2 dubbo直连
通过@DubboReference(url = "")可以直接连接服务提供者,不需要注册中心也可以调用
2 负载均衡
这边主要是将负载均衡配置在消费方
全局配置:dubb.consumer.loadbalance=random,可选值:random,roundrobin,leastactive,分别表示:随机,轮询,最少活跃调用,默认random
对单个服务进行负载均衡:@DubboReference(loadbalance = "random"),通过引用注解配置
3 服务降级
3.1 什么是服务降级(针对初学者)
当服务器压力增大的情况下,根据业务情况以及流量,对一些服务进行有策略的不处理或者换种简单的方式处理,从而释放服务器资源以保证核心交易的正常运作或高效运作。
3.2 通过dubbo-admin配置服务降级
新版目前还没有发布服务降级的版本,所以目前暂时先使用旧版的dubbo-admin进行使用,有两种方式,一种是不请求服务,就返回null;另一种就是请求服务失败后,返回null