2.5、代码优化
将接口抽取为独立模块,并且把接口有关的domain都放到这个模块中
(1)创建user-api模块引入依赖
(2)将UserService接口和User对象导入user-api模块下
(3)User对象实现序列化接口
1. package cn.itcast.user.domain; 2. 3. import lombok.Data; 4. 5. import java.io.Serializable; 6. 7. @Data 8. public class User implements Serializable { 9. private Long id; 10. private String username; 11. private String address; 12. }
3、Dubbo高级特性
3.2、超时与重试
服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一直等待下去。
在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩。
- dubbo 利用超时机制来解决这个问题(使用timeout属性配置超时时间,默认值1000,单位毫秒)
- 若超时时间较短,当网络波动时请求就会失败,Dubbo通过重试机制避免此类问题的发生
user-consumer模块中添加配置信息
1. dubbo: 2. registry: 3. address: nacos://127.0.0.1:8848 4. consumer: 5. timeout: 3000 6. retries: 0
3.3、启动检查
为了保障服务的正常可用,Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常
在正式环境这是很有必要的一项配置,可以保证整个调用链路的平稳运行
在开发时,往往会存在没有提供者的情况。由于启动检查的原因,可能导致开发测试出现问题
可以通过check=false关闭
user-consumer模块中添加配置信息
1. dubbo: 2. registry: 3. address: nacos://127.0.0.1:8848 4. consumer: 5. check: false
3.4、多版本
灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。
Dubbo提供了提供者多版本的支持,平滑处理项目功能升级部署
(1)user-provider定义新的服务实现类UserServiceImpl2,指定版本
1. @DubboService(version = “2.0.0”) 2. public class UserServiceImpl2 implements UserService { 3. ………… 4. }
(2)user-consumer消费者调用时,指定版本调用
1. @RestController 2. @RequestMapping("/user") 3. public class UserController { 4. //引用远程服务 5. @DubboReference(version = "2.0.0") 6. private UserService userService; 7. ……… 8. }
3.5、负载均衡
在集群部署时,Dubbo提供了4种负载均衡策略,帮助消费者找到最优提供者并调用
- Random :按权重随机,默认值。按权重设置随机概率。
- RoundRobin :按权重轮询
- LeastActive:最少活跃调用数,相同活跃数的随机。
- ConsistentHash:一致性 Hash,相同参数的请求总是发到同一提供者。
1. @RestController 2. @RequestMapping("/user") 3. public class UserController { 4. //引用远程服务 5. @DubboReference(loadbalance = "roundrobin") 6. private UserService userService; 7. }
4、SpringCloud整合Dubbo
通常来说,RPC协议比REST具有更好的性能。很多开发人员希望享受Spring Cloud的生态,同时有兼顾PRC的效率的效率。SpringCloud Alibaba很好的解决了这个问题。
4.1、功能概述
将Dubbo集成至SpringCloud主要是替换Ribbo或者Feign实现远程调用。加入Dubbo后,整体的架构如下:
4.2、入门案例
4.2.1、抽取接口
定义接口模块dubbo-api,并将UserService接口抽取到此模块下
1. package cn.itcast.dubbo.api; 2. 3. 4. import cn.itcast.dubbo.domain.User; 5. 6. public interface UserService { 7. 8. User queryById(Long id); 9. }
4.2.2、项目依赖
父工程加入SpringCloud Alibaba依赖
1. <dependency> 2. <groupId>com.alibaba.cloud</groupId> 3. <artifactId>spring-cloud-alibaba-dependencies</artifactId> 4. <version>2.2.5.RELEASE</version> 5. <type>pom</type> 6. <scope>import</scope> 7. </dependency>
消费者和提供者引入nacos注册中心和Dubbo依赖
1. <!--nacos注册中心的依赖--> 2. <dependency> 3. <groupId>com.alibaba.cloud</groupId> 4. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> 5. </dependency> 6. 7. <!--springcloud alibaba dubbo依赖 --> 8. <dependency> 9. <groupId>com.alibaba.cloud</groupId> 10. <artifactId>spring-cloud-starter-dubbo</artifactId> 11. </dependency> 12. 13. <dependency> 14. <groupId>cn.itcast</groupId> 15. <artifactId>dubbo-api</artifactId> 16. <version>1.0-SNAPSHOT</version> 17. </dependency>
4.2.3、服务提供者
修改UserService实现UserApi接口。并使用@DubboService注解替换@Service对外暴露dubbo服务
1. package cn.itcast.user.service; 2. 3. import cn.itcast.dubbo.api.UserService; 4. import cn.itcast.dubbo.domain.User; 5. import cn.itcast.user.mapper.UserMapper; 6. import org.apache.dubbo.config.annotation.DubboService; 7. import org.springframework.beans.factory.annotation.Autowired; 8. 9. @DubboService 10. public class UserServiceImpl implements UserService { 11. 12. @Autowired 13. private UserMapper userMapper; 14. 15. public User queryById(Long id) { 16. return userMapper.findById(id); 17. } 18. }
在application.yml中添加配置
1. spring: 2. datasource: 3. url: jdbc:mysql://localhost:3306/dubbo-demo?useSSL=false 4. username: root 5. password: root 6. driver-class-name: com.mysql.jdbc.Driver 7. application: 8. name: user-service 9. cloud: 10. nacos: 11. discovery: 12. server-addr: localhost:8848 13. #配置dubbo,注册中心,暴露的端口和协议,dubbo注解的包扫描 14. dubbo: 15. protocol: 16. name: dubbo 17. port: 20881 18. registry: 19. address: spring-cloud://localhost #使用SpringCloud中的注册中心 20. scan: 21. base-packages: cn.itcast.user.service #dubbo中包扫描
4.2.4、服务消费者
在OrderController中引入dubbo服务。调用UserService查询用户
1. package cn.itcast.order.controller; 2. 3. import cn.itcast.dubbo.api.UserService; 4. import cn.itcast.dubbo.domain.Order; 5. import cn.itcast.dubbo.domain.User; 6. import cn.itcast.order.service.OrderService; 7. import org.apache.dubbo.config.annotation.DubboReference; 8. import org.springframework.beans.factory.annotation.Autowired; 9. import org.springframework.web.bind.annotation.GetMapping; 10. import org.springframework.web.bind.annotation.PathVariable; 11. import org.springframework.web.bind.annotation.RequestMapping; 12. import org.springframework.web.bind.annotation.RestController; 13. 14. @RestController 15. @RequestMapping("order") 16. public class OrderController { 17. 18. @Autowired 19. private OrderService orderService; 20. 21. @DubboReference 22. private UserService userService; 23. 24. @GetMapping("{orderId}") 25. public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) { 26. //根据id查询订单 27. Order order = orderService.queryOrderById(orderId); 28. //获取用户id 29. Long userId = order.getUserId(); 30. //查询用户 31. User user = userService.queryById(userId); 32. //设置用户对象 33. order.setUser(user); 34. // 根据id查询订单并返回 35. return order; 36. } 37. }
在Order-service的模块中添加dubbo配置
1. spring: 2. application: 3. name: order-service 4. cloud: 5. nacos: 6. discovery: 7. server-addr: localhost:8848 8. #dubbo配置 9. dubbo: 10. registry: 11. address: spring-cloud://localhost #使用cloud的注册中心 12. consumer: 13. check: false #dubbo默认有启动检查 14. retries: 0 #dubbo内置的重试机制