SpringBoot 越来越热门以至于达到烂大街可见的程度, 而 Dubbo 这个基于二进制的微服务框架又捐献给 Apache 孵化, 如果不会如何使用那么是不是很不好意思呢?
这次从公司的项目中抽一个小列子来熟悉下如果从零构建, 至于深入了解 -> 传送门: Dubbo 官方中文手册
版本:
- Springboot2.x
- Double2.6
- Zk3.4.14
- JDK8
这里就不介绍 Dubbo 了, 传送去看看以前的: 互联网级微服务架构神器 Duubo
zookeepr 安装
下载去官网查找稳定的版本进行使用: http://www.apache.org/dyn/closer.cgi/zookeeper/
先在服务器上安装 zookeeper.
- cd /usr/local/src/
- # 下载
- sudo wget http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.14/zookeeper-3.4.14.tar.gz
- # 解压
- tar -zxvf zookeeper-3.4.14.tar.gz
- # 修改配置文件名称
- mv conf/zoo_sample.cfg zoo.cfg
- # 启动 zk
- ./bin/zkServer.sh start
- # 出现以下字样代表启动成功, 默认端口 2181
- Starting zookeeper ... STARTED
SpringBoot2.x 整合 Dubbo
父工程搭建 (pom 工程)
- <groupId>com.simple.springboot</groupId>
- <artifactId>yun-double</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>pom</packaging>
- <name>yun-double</name>
- <description>double</description>
- <!-- 统一管理依赖版本 -->
- <properties>
- <java.version>1.8</java.version>
- <double.version>2.0.0</double.version>
- <zkclient.version>0.10</zkclient.version>
- </properties>
- <!-- 依赖于 SpringBoot -->
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.1.4.RELEASE</version>
- <relativePath/>
- </parent>
- <!-- 依赖定义 -->
- <dependencyManagement>
- <dependencies>
- <dependency>
- <groupId>com.alibaba.spring.boot</groupId>
- <artifactId>dubbo-spring-boot-starter</artifactId>
- <version>${double.version}</version>
- </dependency>
- <dependency>
- <groupId>com.101tec</groupId>
- <artifactId>zkclient</artifactId>
- <version>${zkclient.version}</version>
- </dependency>
- </dependencies>
- </dependencyManagement>
创建公共接口工程 common
该工程用于存储服务层接口, 以减少代码的冗余.
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>com.simple.springboot</groupId>
- <artifactId>yun-double</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </parent>
- <groupId>com.simple.springboot</groupId>
- <artifactId>common</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>common</name>
- <description > 公共接口 </description>
创建公共接口
- public interface UserService {
- String getUserById(int id);
- }
创建服务提供者 (provider)
Pom 文件
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.simple.springboot</groupId>
- <artifactId>provider</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <packaging>jar</packaging>
- <name>provider</name>
- <description > 生产者 </description>
- <parent>
- <groupId>com.simple.springboot</groupId>
- <artifactId>yun-double</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </parent>
- <dependencies>
- <!-- SpringBoot 快速启动 Duubbo -->
- <dependency>
- <groupId>com.alibaba.spring.boot</groupId>
- <artifactId>dubbo-spring-boot-starter</artifactId>
- </dependency>
- <!-- Zk 客户端依赖 -->
- <dependency>
- <groupId>com.101tec</groupId>
- <artifactId>zkclient</artifactId>
- <!-- 排除依赖里的日志 -->
- <exclusions>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-API</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <!-- 导入公共接口依赖 -->
- <dependency>
- <groupId>com.simple.springboot</groupId>
- <artifactId>common</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
在 pom 文件中我们需要引入 Dubbo,Zk 客户端并且引入公共接口工程
application.properties 配置文件
- #dubbo.application.name 应用名称
- #dubbo.registry.address 注册中心地址
- #dubbo.protocol.name 协议名称
- #dubbo.protocol.port 协议端口
- #dubbo.scan dubbo 服务类包目录
- #server.port=8080
- spring.application.name=user-pro
- dubbo.application.name=user-provider1
- dubbo.registry.address=zookeeper://192.168.197.133:2181
- dubbo.protocol.name=dubbo
- dubbo.protocol.port=20880
在这里 dubbo.application.name 应用名称一定不能重复
实现 UserService
- @Component
- @Service(timeout = 10000,interfaceClass = UserService.class)
- public class UserServiceImpl implements UserService {
- @Override
- public String getUserById(int id) {
- if(id == 1) {
- return "SimpleWu";
- }else {
- return "Apache Dubbo";
- }
- }
- }
@Service 这个注解使用的不是 Spring 里面的而是 com.alibaba.dubbo.config.annotation.Service
timeout 配置超时时间
interfaceClass 接口类
version 服务版本, 如果配置了服务版本在消费端引用也必须一样, 具体等会说
创建启动类
在该工程中我们不需要引入 web 模块浪费端口号, 只需要这样写启动类
- @EnableDubbo
- @EnableDubboConfiguration
- @DubboComponentScan("com.simple.springboot.provider.common.impl")
- public class ProviderApplication {
- public static void main(String[] args) {
- SpringApplication App = new SpringApplication(ProviderApplication.class);
- App.run(args);
- //dubbo Main 独立运行, 脱离 Web 容器
- Main.main(args);
- }
- }
@EnableDubbo 启动 Dubbo 功能
@EnableDubboConfiguration 启动 Duubbo 配置
@DubboComponentScan 扫描提供者实现类
创建服务消费者 (consumer)
POM 文件
- <modelVersion>4.0.0</modelVersion>
- <groupId>com.simple.springboot</groupId>
- <artifactId>consumer</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>consumer</name>
- <description > 消费者 </description>
- <parent>
- <groupId>com.simple.springboot</groupId>
- <artifactId>yun-double</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </parent>
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-Web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- </dependency>
- <!-- SpringBoot 快速启动 Duubbo -->
- <dependency>
- <groupId>com.alibaba.spring.boot</groupId>
- <artifactId>dubbo-spring-boot-starter</artifactId>
- </dependency>
- <!-- Zk 客户端依赖 -->
- <dependency>
- <groupId>com.101tec</groupId>
- <artifactId>zkclient</artifactId>
- <!-- 排除依赖里的日志 -->
- <exclusions>
- <exclusion>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-API</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-log4j12</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <!-- 导入公共接口依赖 -->
- <dependency>
- <groupId>com.simple.springboot</groupId>
- <artifactId>common</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </dependency>
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
在这个工程中我们是需要依赖 Web 的, 不然咋访问呢
编写 Application.properties 配置文件
- spring.application.name=user-con
- server.port=8080
- dubbo.application.name=user-consumer
- dubbo.registry.address=zookeeper://192.168.197.133:2181
- dubbo.protocol.name=dubbo
- dubbo.protocol.port=20880
- #dubbo.scan=com.simple.springboot.provider.common.impl
在这里 dubbo.application.name 应用名称一定不能重复
dubbo.scan 该配置指向应该是要和服务提供方一致
编写 Controller
- @RestController
- public class UserController {
- //timeout 可以不指定, 如果提供则有填写但是 version 一定要指定 不然会找不到服务 直连需要加 url="dubbo://localhost:20880"
- @Reference
- private UserService userService;
- @GetMapping("/dubbo/user/{id}")
- public String getUserById(@PathVariable int id){
- return userService.getUserById(id);
- }
- }
在这里是使用 @Reference 去发现服务而不是 @Autowired 去注入 Bean
@Reference 里面可以配置 version,timeout 超时时间
如果需要 Dubbo 直连 url="dubbo://localhost:20880"
dubbo 提供了四种负载均衡策略, 分别是:
1,Random LoadBalance 按权重的随机负载均衡, 也是 dubbo 默认的负载均衡策略
2,RoundRobin LoadBalance 按权重的轮询负载均衡, 即在轮询的基础上添加了权重的策略
3,LeastActive LoadBalance 最少活跃调用数, 相同活跃数的随机访问, 活跃数指调用前后的计数差即响应时间的长短; 这种策略可以使响应慢的提供者收到的请求较少, 大大提供系统性能
4,ConsistentHash LoadBalance 一致性哈希; 相同参数的请求总是发到同一提供者
负载均衡的配置:@Reference(loadbalance = "roundrobin"),loadbalance 的值即为四种负载均衡的名称, 全部小写
在集群调用失败时, Dubbo 提供了多种容错方案, 缺省为 failover 重试. 下面列举 dubbo 支持的容错策略:
1,Failover Cluster: 失败自动切换, 当出现失败, 重试其它服务器. 通常用于读操作, 但重试会带来更长延迟. 可通过 retries="XXX" 来设置重试次数 (不含第一次).
2,Failfast Cluster: 快速失败, 只发起一次调用, 失败立即报错. 通常用于非幂等性的写操作, 比如新增记录.
3,Failsafe Cluster: 失败安全, 出现异常时, 直接忽略. 通常用于写入审计日志等操作.
4,Failback Cluster: 失败自动恢复, 后台记录失败请求, 定时重发. 通常用于消息通知操作.
5,Forking Cluster: 并行调用多个服务器, 只要一个成功即返回. 通常用于实时性要求较高的读操作, 但需要浪费更多服务资源. 可通过 forks="2" 来设置最大并行数.
6,Broadcast Cluster: 广播调用所有提供者, 逐个调用, 任意一台报错则报错 [2]. 通常用于通知所有提供者更新缓存或日志等本地资源信息.
配置如下:@Reference(cluster = "failsafe") 这里表示使用失败安全的容错策略
编写启动类
- /**
- * @author:SimpleWu
- * @date: 2019-05-08
- */
- @EnableDubbo
- @SpringBootApplication
- @EnableDubboConfiguration
- @DubboComponentScan("com.simple.springboot.provider.common.impl")
- public class ConsumerApplication {
- public static void main(String[] args) {
- SpringApplication.run(ConsumerApplication.class,args);
- }
- }
然后直接就可以访问成功了.
如果不想使用注解扫描可以使用 properties 进行配置
#dubbo.scan=com.simple.springboot.provider.common.impl
参考代码: 传送门
注意事项:
Dubbo 是一个二进制的 Rpc 框架在传输数据过程中, 实体类必须经过序列化.
在使用 poi 导出功能时一定不能把 response 传到 Service 层, 否则传输到 Service 是导出不了文件而报错, 至于文件下载也一样但是相信一般都会有单独的文件服务器.
来源: https://www.cnblogs.com/SimpleWu/p/10833555.html