dubbo
dubbo介绍
Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
中文官网: http://dubbo.apache.org/zh-cn/
dubbo工作原理
dubbo+zookeeper入门案例
首先确保zookeeper集群已经运行
1 创建父子项目
父项目: testdubbo
子项目: 测试方便, 均打jar包
- consumer 消费者 --> 添加springboot主启动类
- interface 接口-SOA思想 --> 不需要主启动类
- producer 生产者 --> 添加springboot主启动类
2. maven依赖
在父项目中导入dubbo的依赖
地址: https://mvnrepository.com/artifact/com.alibaba.boot/dubbo-spring-boot-starter
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
测试使用的依赖还有spring web
, thymeleaf
, lombok
3. interface子项目
此项目为SOA思想的接口中间项目
定义User实体类: 此实体类需要实现Serializable序列化接口, 因为底层要实现远程调用
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true) // 加不加无所谓, lombok中的注解, 用来连续赋值
public class User implements Serializable {
private static final long serialVersionUID = 1298816803633464735L;
private String username;
private String password;
private String phone;
private String email;
}
定义测试的service接口
public interface UserService {
User findUser(); // 查询用户 测试...
}
4. 生产者producer
pom依赖, 需要引入interface子项目
<dependencies>
<dependency>
<groupId>com.aarom</groupId>
<artifactId>interface</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
实现interface子项目中的UserService接口
注意@Service注解使用阿里巴巴包下的, 不要使用spring包的com.alibaba.dubbo.config.annotation.Service
// Service注解使用com.alibaba.dubbo.config.annotation.Service包下的
@Service(timeout = 3000) //3秒超时 使用dubbo的注解
public class UserServiceImpl implements UserService {
@Override
public User findUser() {
User user = new User();
user.setUsername("admin");
user.setPassword("123456");
user.setPhone("1231231231");
user.setEmail("231@qq.com");
return user;
}
}
application.yml配置文件配置如下:
server:
port: 8082
logging:
level:
com.aaron: debug
dubbo:
scan:
basePackages: com.aaron #指定dubbo的包路径 扫描dubbo的注解
application: #应用名称
name: provider-user #相同的接口 服务名称必定一致. 不同的接口服务名称一定不一致.
registry: #配置注册中心
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协议
name: dubbo #使用dubbo协议(tcp-ip) web-controller直接调用sso-Service
port: 20880 #每一个服务都有自己特定的端口 不能重复.
5. 消费者consumer
消费者负责调用interface子项目中的UserService接口, 此接口的实现有生产者producer完成
注意: 依赖注入使用阿里巴巴下的@Reference注解, 不要使用@Autowired com.alibaba.dubbo.config.annotation.Reference
@RestController
public class UserController {
// 此注解为阿里巴巴下的 com.alibaba.dubbo.config.annotation.Reference 包
@Reference //@Reference(check = false) 不检查生产者
private UserService userService;
@RequestMapping("/findUser")
public User findAll() {
return userService.findUser();
}
}
application.yml配置文件如下:
server:
port: 8081
logging:
level:
com.aaron: debug
dubbo:
scan:
basePackages: com.aaron
application:
name: consumer-user #定义消费者名称
registry: #注册中心地址
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
6. 进行测试
尽量先启动生产者producer, 再启动消费者consumer, 如果@Reference注解加上参数@Reference(check = false), 启动顺序无所谓
浏览器输入: http://localhost:8081/findUser
是否可以正常输出
如果输出了正常信息, 说明配置成功
关于InvocationTargetException异常
java.lang.reflect.InvocationTargetException: null
dubbo的异常信息
可能是因为配置文件中的dubbo.scan.basePackages
的值有问题, 请检查包是否正确
如果还不可以, 试着将属性basePackages
换成 base-packages
dubbo负载均衡
测试负载均衡
在上述的入门案例中, 我们可以再添加一个子项目producer2, 即生产者2, 内容与producer子项目类似, 但是配置文件需要做改动
dubbo:
scan:
basePackages: com.aaron #指定dubbo的包路径 扫描dubbo的注解
application: #应用名称
name: provider-user #相同的接口 服务名称必定一致. 不同的接口服务名称一定不一致.
registry: #配置注册中心
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: #指定协议
name: dubbo #使用dubbo协议(tcp-ip) web-controller直接调用sso-Service
port: 20882 #每一个服务都有自己特定的端口 不能重复.
注意的地方有两处:
- port 配置文件中dubbo的端口号必须和其他生产者不一样
- 如果是同一个模块, 要实现负载均衡, application下的 name属性要和其他生产者名字一致, 这里生产者1和生产者2的值都是
provider-user
为了方便区分负载均衡, 可以在UserServiceImpl中添加不同的输出内容, 用户测试区分
上述内容配置就绪以后, 浏览器再次输入: http://localhost:8081/findUser
多次刷新, 查看两个生产者的控制台输出即可
负载均衡策略
dubbo中提供了一个接口Loadbalance
此接口有4个实现类, 就是这4种负载均衡策略
4中策略: 默认为第三种, 随机策略 , 使用负载均衡时, 参数必须全小写!!!
-
consistenthash
hash一致性原则根据IP:port进行hash运算,之后绑定固定的提供者进行访问.
效果: 以后消费者与服务提供者进行了绑定.使用方法: 注解
@Reference(loadbalance = "consistenthash")
-
leastactive
挑选访问压力最小的挑选当前服务器压力较小的进行访问.
使用方法: 注解
@Reference(loadbalance = "leastactive")
-
random
随机访问随机访问策略
使用方法: 注解
@Reference(loadbalance = "random")
-
roundrobin
轮循策略轮流访问达到负载均衡
使用方法: 注解
@Reference(loadbalance = "roundrobin")
zookeeper中存储结构
在zookeeper安装目录下, 进入bin目录, 里面有个zkCli.sh
用户启动zookeeper客户端进行访问
进入zookeeper客户端: sh zkCli.sh
退出客户端: quit
在zookeeper客户端中, 我们输入ls
指令, 可以查看目录
例如: ls /
查看zookeeper的根路径
例如: ls /dubbo
查看根路径下的dubbo路径
zookeeper的数据存储结果如下:
dubbo的通讯原理
通讯协议: dubbo协议(tcp-ip)
说明: dubbo协议将TCP-IP协议进行封装.
Dubbo框架中使用dubbo协议建立了链接,之后通过IP:20880等端口 (yaml中配置的端口) 进行通讯,与LinuxIP地址无关.
客户端负载均衡/集中式负载均衡
集中式负载均衡
集中式负载均衡例如nginx
特点:
- 用户访问服务器时,自己不清楚访问的真实的服务器到底是谁,由nginx服务器动态的反向代理实现.
- 统一由负载均衡服务器进行负载. 问题 负载均衡服务器访问压力高.
客户端负载均衡
- 消费者在访问服务提供者时清楚的了解 到底应该访问哪台服务器.
- 由于每个客户端都进行负载均衡.相当于将压力均匀的分配给客户端.访问压力低.
核心:
- nginx一般只负责反向代理
- 在微服务框架中 几乎都是客户端负载均衡服务器.