Spring Boot中使用Dubbo

高并发下Redis会出现的问题:

  • 缓存穿透
  • 缓存雪崩
  • 热点缓存

一、定义commons工程11-dubboCommons

(1) 创建工程

创建Maven的Java工程,并命名为11-dubboCommons

(2) 定义pom文件

  1. <groupId>com.abc</groupId>
  2. <artifactId>11-dubboCommons</artifactId>
  3. <version>1.0-SNAPSHOT</version>
  4. <properties>
  5. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  6. <maven.compiler.source>1.8</maven.compiler.source>
  7. <maven.compiler.target>1.8</maven.compiler.target>
  8. </properties>
  9. <dependencies>
  10. <dependency>
  11. <groupId>org.projectlombok</groupId>
  12. <artifactId>lombok</artifactId>
  13. <version>1.18.4</version>
  14. <scope>provided</scope>
  15. </dependency>
  16. </dependencies>

(3) 定义实体类

(4) 定义业务接口

(5) 将工程安装到本地库

运行Maven的install命令,将工程安装到本地版本库,以备其它工程使用

二、定义提供者11-provider-springboot

(1) 创建工程

创建一个Spring Boot工程,并重命名为11-provider-springboot

(2) 定义pom文件

A、添加dubbo与spring boot整合依赖
B、添加zkClient依赖
C、其它依赖

  • dubboCommons依赖
  • spring boot与redis整合依赖
  • mybatis与spring boot整合依赖
  • 数据源Druid依赖
  • mysql驱动依赖
  • slf4j-log4j12依赖
  • spring-boot-starter-web依赖
  1. <groupId>com.abc</groupId>
  2. <artifactId>11-provider-springboot</artifactId>
  3. <version>0.0.1-SNAPSHOT</version>
  4. <parent>
  5. <groupId>org.springframework.boot</groupId>
  6. <artifactId>spring-boot-starter-parent</artifactId>
  7. <version>2.1.5.RELEASE</version>
  8. <relativePath/> <!-- lookup parent from repository -->
  9. </parent>
  10. <properties>
  11. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  12. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  13. <java.version>1.8</java.version>
  14. </properties>
  15. <dependencies>
  16. <!--dubbo与spring boot整合依赖-->
  17. <dependency>
  18. <groupId>com.alibaba.spring.boot</groupId>
  19. <artifactId>dubbo-spring-boot-starter</artifactId>
  20. <version>2.0.0</version>
  21. </dependency>
  22. <!-- zk客户端依赖:zkclient -->
  23. <dependency>
  24. <groupId>com.101tec</groupId>
  25. <artifactId>zkclient</artifactId>
  26. <version>0.10</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>com.abc</groupId>
  30. <artifactId>11-dubboCommons</artifactId>
  31. <version>1.0-SNAPSHOT</version>
  32. </dependency>
  33. <!--Spring Boot与Redis整合依赖-->
  34. <dependency>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-starter-data-redis</artifactId>
  37. </dependency>
  38. <!--mybatis与Spring Boot整合依赖-->
  39. <dependency>
  40. <groupId>org.mybatis.spring.boot</groupId>
  41. <artifactId>mybatis-spring-boot-starter</artifactId>
  42. <version>1.3.2</version>
  43. </dependency>
  44. <!--数据源Druid依赖-->
  45. <dependency>
  46. <groupId>com.alibaba</groupId>
  47. <artifactId>druid</artifactId>
  48. <version>1.1.10</version>
  49. </dependency>
  50. <!--MySQL驱动依赖-->
  51. <dependency>
  52. <groupId>mysql</groupId>
  53. <artifactId>mysql-connector-java</artifactId>
  54. <version>5.1.47</version>
  55. </dependency>
  56. <dependency>
  57. <groupId>org.slf4j</groupId>
  58. <artifactId>slf4j-log4j12</artifactId>
  59. <version>1.7.25</version>
  60. <scope>test</scope>
  61. </dependency>
  62. <dependency>
  63. <groupId>org.springframework.boot</groupId>
  64. <artifactId>spring-boot-starter-web</artifactId>
  65. </dependency>
  66. <dependency>
  67. <groupId>org.springframework.boot</groupId>
  68. <artifactId>spring-boot-starter-test</artifactId>
  69. <scope>test</scope>
  70. </dependency>
  71. </dependencies>
  72. <build>
  73. <plugins>
  74. <plugin>
  75. <groupId>org.springframework.boot</groupId>
  76. <artifactId>spring-boot-maven-plugin</artifactId>
  77. </plugin>
  78. </plugins>
  79. <resources>
  80. <!--注册dao包下mybatis映射文件为资源目录-->
  81. <resource>
  82. <directory>src/main/java</directory>
  83. <includes>
  84. <include>**/*.xml</include>
  85. </includes>
  86. </resource>
  87. </resources>
  88. </build>

(3) 定义Service实现类

  1. import com.abc.bean.Employee;
  2. import com.abc.dao.EmployeeDao;
  3. import com.alibaba.dubbo.config.annotation.Service;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.cache.annotation.CacheEvict;
  6. import org.springframework.cache.annotation.Cacheable;
  7. import org.springframework.data.redis.core.BoundValueOperations;
  8. import org.springframework.data.redis.core.RedisTemplate;
  9. import org.springframework.stereotype.Component;
  10. import org.springframework.transaction.annotation.Transactional;
  11. import java.util.concurrent.TimeUnit;
  12. @Service // Dubbo的注解 <dubbo:service/>
  13. @Component
  14. public class EmployeeServiceImpl implements EmployeeService {
  15. @Autowired
  16. private EmployeeDao dao;
  17. @Autowired
  18. private RedisTemplate<Object, Object> redisTemplate;
  19. // 当有对象插入时会清空realTimeCache缓存空间
  20. @CacheEvict(value="realTimeCache", allEntries = true)
  21. @Transactional(rollbackFor = Exception.class)
  22. @Override
  23. public void addEmployee(Employee employee) {
  24. dao.insertEmployee(employee);
  25. }
  26. // 一旦有了查询结果,则会将此结果写入到realTimeCache缓存
  27. // key是employee_加上方法参数
  28. @Cacheable(value = {"realTimeCache"}, key = "'employee_'+#id")
  29. @Override
  30. public Employee findEmployeeById(int id) {
  31. // 从DB查询
  32. System.out.println("从DB查询id = " + id);
  33. return dao.selectEmployeeById(id);
  34. }
  35. private volatile Object count;
  36. // 双重检测锁机制解决Reids的热点缓存问题
  37. @Override
  38. public Integer findEmployeeCount() {
  39. // 获取Redis操作对象
  40. BoundValueOperations<Object, Object> ops = redisTemplate.boundValueOps("count");
  41. // 从缓存获取数据
  42. count = ops.get();
  43. if(count == null) {
  44. synchronized (this) {
  45. count = ops.get();
  46. if(count == null) {
  47. System.out.println("从DB中查询");
  48. // 从DB中查询
  49. count = dao.selectEmployeeCount();
  50. // 将查询结果存放到Redis
  51. ops.set(count, 10, TimeUnit.SECONDS);
  52. }
  53. }
  54. }
  55. return (Integer) count;
  56. }
  57. }

(4) 定义Dao接口

(5) 定义映射文件

(6) 修改启动类

在启动类上必须要添加@EnableDubboConfiguration注解,开启Dubbo的自动配置功能

(7) 修改主配置文件

  1. server:
  2. port: 8888
  3. mybatis:
  4. # 注册mybatis中实体类的别名
  5. type-aliases-package: com.abc.bean
  6. # 注册映射文件
  7. mapper-locations: classpath:com/abc/dao/*.xml
  8. spring:
  9. # 注册数据源
  10. datasource:
  11. # 指定数据源类型为Druid
  12. type: com.alibaba.druid.pool.DruidDataSource
  13. driver-class-name: com.mysql.jdbc.Driver
  14. url: jdbc:mysql:///test?useUnicode=true&amp;characterEncoding=utf8
  15. username: root
  16. password: root
  17. # 连接Redis服务器
  18. redis:
  19. host: 39.97.176.160
  20. port: 6379
  21. # 连接Redis高可有集群
  22. # redis:
  23. # sentinel:
  24. # master: mymaster
  25. # nodes:
  26. # - sentinelOS1:26379
  27. # - sentinelOS2:26379
  28. # - sentinelOS3:26379
  29. # 配置缓存
  30. cache:
  31. type: redis # 指定缓存类型
  32. cache-names: realTimeCache # 指定缓存区域名称
  33. # 功能等价于spring-boot配置文件中的<dubbo:application/>
  34. application:
  35. name: 11-provider-springboot
  36. # 指定zk注册中心
  37. dubbo:
  38. registry: zookeeper://39.97.176.160:2181
  39. # zk集群作注册中心
  40. # registry: zookeeper://zkOS1:2181?backup=zkOS2:2181,zkOS3:2181

三、定义消费者11-consumer-springboot

(1) 创建工程

创建一个Spring Boot工程,并重命名为11-consumer-springboot

(2) 定义pom文件

  • dubbo与spring boot整合依赖
  • zkClient依赖
  • dubboCommons依赖
  • JSP引擎jasper依赖
  • slf4j-log4j12依赖
  • spring-boot-starter-web依赖

(3) 修改主配置文件

  1. spring:
  2. # 功能等价于spring-dubbo配置文件中的<dubbo:application/>
  3. application:
  4. name: 11-consumer-springboot
  5. # 指定zk注册中心
  6. dubbo:
  7. registry: zookeeper://39.97.176.160:2181
  8. # zk集群作注册中心
  9. # registry: zookeeper://zkOS1:2181?backup=zkOS2:2181,zkOS3:2181

(4) 创建index.jsp页面

在src/main/webapp目录下定义index.jsp文件

(5) 定义处理器

  1. package com.abc.controller;
  2. import com.abc.bean.Employee;
  3. import com.abc.service.EmployeeService;
  4. import com.alibaba.dubbo.config.annotation.Reference;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.ui.Model;
  7. import org.springframework.web.bind.annotation.PathVariable;
  8. import org.springframework.web.bind.annotation.PostMapping;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.ResponseBody;
  11. @Controller
  12. @RequestMapping("/consumer/employee")
  13. public class SomeController {
  14. // @Autowired
  15. @Reference // Dubbo的注解 <dubbo:reference />
  16. private EmployeeService employeeService;
  17. @PostMapping("/register")
  18. public String someHandle(Employee employee, Model model) {
  19. employeeService.addEmployee(employee);
  20. model.addAttribute("employee", employee);
  21. return "/welcome.jsp";
  22. }
  23. @RequestMapping("/find/{id}")
  24. @ResponseBody
  25. public Employee findHandle(@PathVariable("id") int id) {
  26. return employeeService.findEmployeeById(id);
  27. }
  28. @RequestMapping("/count")
  29. @ResponseBody
  30. public Integer countHandle() {
  31. return employeeService.findEmployeeCount();
  32. }
  33. }

(6) 定义welcome.jsp页面

(7) 修改入口类

四、测试

当有对象插入时会清空realTimeCache缓存空间
一旦有了查询结果,则会将此结果写入到realTimeCache缓存

http://localhost:8080/index.jsp  首页

http://localhost:8080//consumer/employee/find/2 根据Id查找

http://localhost:8080//consumer/employee/count 查找总数

原文地址:https://www.cnblogs.com/edda/p/13260451.html