RPC框架:dubbo的基本使用
常见的RPC协议:
- Dubbo协议
- Triple协议
- Rest协议
- gPRC协议
- HTTP协议
- Redis协议
- Hessian协议
- WebService协议
- Memcached协议
具体文档:https://dubbo.apache.org/zh/docs3-v2/java-sdk/reference-manual/protocol/
注意:
- TCP、UDP是传输层的协议,而HTTP和RPC是应用层协议。
- HTTP:超文本传输协议,RPC:远程过程调用。HTTP诞生于90年代,RPC诞生于80年代。那么为什么有了RPC还有HTTP呢?
- 电脑上的各种软件,如:xx管家,它们都是作为客户端(C)需要跟服务端(S)建立连接收发消息,此时可以使用自家的RPC协议,因为它们只用连接自己公司的服务器就可以了
- 浏览器不一样,B/S架构 ,需要连接不同家的服务器
问题:
- 为什么了有了RPC还要有HTTP?
RPC专门负责连接自家服务器(C/S架构)或者自己微服务组件的通信
- 为什么有了HTTP2.0还要使用RPC?
原理上说HTTP2.0效率比RPC更好,但是很多公司自己实现的RPC已经稳定了很多年了,也就没必要更换了
- 区别
- RPC要求服务提供方和服务调用方都需要使用相同的技术,要么都hessian,要么都dubbo
而http无需关注语言的实现,只需要遵循Rest规范- RPC主要关注自家服务器,HTTP需要关注各家
1 Dubbo概念
Dubbo是由阿里推出的用来进行RPC的框架,主要用于分布式上,其推荐的注册中心为zookeeper,它还有自己的监控中心,不过需要我们自己配置
官网https://dubbo.apache.org/zh/
2 SpringBoot整合Dubbo
主要有三种方式:
- 导入dubbo-starter,在application.properties中配置属性,@Service【dubbo的,暴露服务】,@Reference引用服务,@EnableDubbo(配置包扫描)
- 保留dubbo.xml文件:导入dubbo-starter,使用@ImportResouce导入dubbo的配置文件
- 使用注解API方式,将每一个组件手动创建到容器中,每一个配置标签都对应一个Config配置类(@Bean),最后放在一个总的下面
2.1 首先本地启动一个zookeeper
①首先到conf目录下,直接复制zoo_sample.cfg,然后将名称修改为zoo.cfg②在zk安装目录的bin目录下,直接执行zkServer.cmd
即可
2.2 创建API工程
创建一个maven工程,主要存储实体类和service接口
①实体类
需要实现序列化,因为dubbo在RPC过程中会将数据进行序列化与反序列化
public class UserAddress implements Serializable {
private Integer id;
private String userAddress;
private String userName;
public UserAddress() {
super();
}
public UserAddress(Integer id, String userAddress, String userName){
this.id = id;
this.userAddress = userAddress;
this.userName = userName;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
②接口
public interface UserService {
/**
* 根据id返回用户收获地址
* @return
*/
public List<UserAddress> getUserAddressList(String userId);
}
2.3 创建服务提供者provider
①导入依赖
<!--引入api依赖-->
<dependency>
<groupId>com.zi</groupId>
<artifactId>user-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--引入dubbo依赖-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
dubbo的0.2.0版本帮我们自动导入了zk及客户端
②配置文件
# 应用名称
dubbo.application.name=boot-user-service-provider
dubbo.registry.address=zookeeper://127.0.0.1:2181
server.port=8082
③服务具体实现【provider】
@Service//暴露服务【是dubbo的】
@Component
public class UserServiceImpl implements UserService {
@Override
public List<UserAddress> getUserAddressList(String userId) {
List<UserAddress> list = new ArrayList<>();
UserAddress address1 = new UserAddress(1, "阿根廷", "梅西");
UserAddress address2 = new UserAddress(2, "巴西", "内马尔");
list.add(address1);
list.add(address2);
return list;
}
}
④启动类
@SpringBootApplication
@EnableDubbo//开启基于注解的dubbo
public class BootUserServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(BootUserServiceProviderApplication.class, args);
}
}
2.4 创建服务消费者
①导入依赖
需要引入web模块,因为需要启动创建controller测试
<!--引入api依赖-->
<dependency>
<groupId>com.zi</groupId>
<artifactId>user-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--引入dubbo依赖-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
②配置文件
# 应用名称
dubbo.application.name=boot-order-service-consumer
dubbo.registry.address=zookeeper://127.0.0.1:2181
server.port=8081
③service
@Service
public class OrderService {
@Reference//导入dubbo的
private UserService userService;
public List<UserAddress> getUserAddressLis(String id){
List<UserAddress> addressList = userService.getUserAddressList(id);
return addressList;
}
}
④controller
@Controller
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/getOrderList")
@ResponseBody
public List<UserAddress> getUserOrderList(){
List<UserAddress> list = orderService.getUserAddressLis("1");
return list;
}
@ResponseBody
@GetMapping("/test")
public String test(){
return "success...";
}
}
⑤启动类
@SpringBootApplication
@EnableDubbo//开启基于注解的dubbo
public class BootOrderServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(BootOrderServiceConsumerApplication.class, args);
}
}
【常见问题】
①本地zookeeper是否启动,或者远程zookeeper地址是否正确
②zk是否导入、zk客户端是否导入
③实体类是否实现序列化、是否设置了get、set方法
④provider的@Service与consumer的@Reference是否导入的是dubbo的
⑤启动类上是否加上@EnableDubbo
【使用Dubbo的大体步骤】
- 创建api模块
- 创建provider,导入api模块依赖
- 创建consumer,导入api模块依赖
- zookeeper的地址
- dubbo的@Service、@Reference、@EnableDubbo【主要是包扫描】
3 其他概念
3.1 使用Spring整合dubbo
applicationContext.xml:
- application:指定应用名
- service:声明为Dubbo服务
- consumer:reference间共享的默认配置
- provider:service间共享的默认配置
- protocol:RPC协议及通信端口号,默认20880
- registry:注册中心类型、地址及相关配置
- monitor:监控类型及地址
service 与 reference 是 Dubbo 最基础的两个配置项,它们用来将某个指定的接口或实现类注册为 Dubbo 服务,并通过配置项控制服务的行为。
- service 用于服务提供者端,通过 service 配置的接口和实现类将被定义为标准的 Dubbo 服务,从而实现对外提供 RPC 请求服务。
- reference 用于服务消费者端,通过 reference 配置的接口将被定义为标准的 Dubbo 服务,生成的 proxy 可发起对远端的 RPC 请求。
- 一个应用中可以配置任意多个 service 与 reference
3.2 配置概念
①配置优先级
-D(命令行参数) > application.properties(applicationContext.xml) > dubbo.xml
②检查
可以设置check为false,就算没有一些服务或配置也不会报错
dubbo.consumer.check=false 所有的消费者都不检查
③超时
<dubbo:reference interface="com.zi.gmall.service.UserService"
id="userService" timeout="5000">
也可以在method上面配置
方法级优先 - 接口级 - 全局配置【级别一样则消费者优先】
<dubbo:consumer timeout="1000"></dubbo:consumer>
- 精确优先、消费者优先
3.3 重试次数、多版本
①retryies:重试次数
- 幂等(设置重试次数)【查询、删除、修改】
是否每次请求返回的值是一样的
- 非幂等(不能设置重试次数)【新增】
②version:设置版本,实现灰度发布
3.4 本地存根、dubbo直连
本地存根:stub,主要放在interface模块下
dubbo直连:直接在@Reference设置服务提供者地址,可以绕过注册中心
3.5 高可用:负载均衡
- 基于权重的随机
- 轮询
- 基于权重的轮询
- 最少活跃数【选择执行时间耗时最短的】
- 一致性hash
DUBBO默认使用的是随机的负载均衡机制,通过@Reference(loadbalance="roundrobin")
修改负载均衡策略。
可以通过@Service(weight=“”)修改权重,也可以到管理中心对权重进行倍增(权重*2)和半增(权重/2)
3.6 服务降级、容错
dubbo管理端地址:https://github.com/apache/incubator-dubbo-ops,下载项目之后,通过maven打包,然后java -jar + 打好的war直接运行
- 在dubbo的管理端页面进行屏蔽:直接不调用远程服务,直接返回为null
- 容错:在调用远程服务失败以后,才返回为null
通过hystrix进行容错:
①导入依赖
<!--引入hystrix依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
②在启动类上添加@EnableHystrix
//开启服务容错,服务提供者和消费者都需要添加
③添加@HystrixCommand
注解
@HystrixCommand(fallbackMethod = "hello")//服务调用失败之后,调用hello方法
4 RPC&Netty原理
dubbo原理:https://dubbo.apache.org/zh/docs3-v2/java-sdk/concepts-and-architecture/code-architecture/
4.1 Dubbo框架设计图