简介
官网:Apache Dubbo
什么是 duboo
是一款高性能、轻量级的开源 Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
dubbo 是阿里开发的,2018年初阿里把 dubbo 开源给了 apache。
推荐的代码设计方式
把 interface service 放在一个公共的项目中,让别的具体的项目去实现。
然后如果有项目想要使用具体实现,都先去引入公共项目的依赖,然后 dubbbo 会完成远程调用。
dubbo的工作原理
原视频:27_尚硅谷_原理_服务暴露流程_哔哩哔哩_bilibili
duboo 并不是一个实体工具,它是一个规则规范,它实际去依赖的是注册中心,比如 zookeeper。zookeeper 需要实际启动,而 dubbo 只需要在项目中引入依赖,并按照规则去使用即可。
框架设计
-
config 配置层:对外配置接口,以 ServiceConfig, ReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类
-
proxy 服务代理层:服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 以 ServiceProxy 为中心,扩展接口为 ProxyFactory
-
registry 注册中心层:封装服务地址的注册与发现,以服务 UR为中心,扩展接口为 RegistryFactory, Registry, RegistryService
-
cluster 路由层:封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 Cluster, Directory, Router, LoadBalance
-
monitor 监控层:RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactory, Monitor, MonitorService
-
protoco远程调用层:封装 RPC 调用,以 Invocation, Result 为中心,扩展接口为 Protocol, Invoker, Exporter
-
exchange 信息交换层:封装请求响应模式,同步转异步,以 Request, Response 为中心,扩展接口为 Exchanger, ExchangeChannel, ExchangeClient, ExchangeServer
-
transport 网络传输层:抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 Channel, Transporter, Client, Server, Codec
-
serialize 数据序列化层:可复用的一些工具,扩展接口为 Serialization, ObjectInput, ObjectOutput, ThreadPool
解析加载
服务暴露
使用 dubbo 的优缺点
个人对 dubbo 的理解
dubbo 就相当于 feignClient,但是 feignClient 是代理 Controller API接口,即 feignClient 需要用一个额外的项目,显式地写在项目里面,然后提供者和消费者都启动着,消费者通过 feignClient 去调用提供者。那么就是说,提供者、消费者的接口方法定义和实现都是在自己的模块里面的,然后消费者引入 feignClient 这个模块。
而 dubbo 是代理 Service 层的接口方法,直接相当于 @Resource 一样引入一个 Service层的依赖,就可以直接用它的方法。就是说,dubbo 并不需要用一个额外的项目,显式地写在项目里面,而是由一个公共的服务组件,比如 framework 来把接口方法定义,然后提供者和消费者去引入这个组件即可,只是调用接口方法的时候使用 dubbo 的注解告诉 dubbo 一下。
dubbo 的健壮性
-
监控中心宕掉不影响使用,只是丢失部分采样数据
-
数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
-
注册中心对等集群,任意一台宕掉后,将自动切换到另一台
-
注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
-
服务提供者无状态,任意一台宕掉后,不影响使用
-
服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复
-
dubbo 提供了直连方式,即在注解上直接写死调用地址
dubbo快速开始
-
服务提供者(Provider):暴露服务的服务提供方,服务提供者在自己的容器启动时,向注册中心注册自己提供的服务。
-
服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
-
注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
-
监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
下载监控中心 Dubbo-OPS
下载完成后解压。然后如果 zookeeper 的地址不是本机,就去 resources 中的配置文件修改。
dubbo-admin - 管理控制台
想要 admin 的 jar包,只需要进 admin 目录下 cmd,mvn clean package,就可获得 jar。
然后就可以使用命令启动 admin,地址是 http:localhost:7001,root/root。
dubbo-moitor-simple - 监控中心
还是去目录下 cmd 运行 mvn clean package,就可获得 jar。
如果有 2.0.0 的话,去运行 bin/start.bat,启动监控服务。
监控中心的端口是 7070,然后访问地址是 localhost:8080
配置
https://dubbo.apache.org/zh-cn/overview/mannual/java-sdk/reference-manual/config/properties/
dubbo 有非常多的配置,注解中也有许多属性。
实例
实践1
代码地址:nwonknU/learning - Gitee.com
前置
引入依赖
<!-- 普通 Maven项目 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.6.2</version> </dependency> <!-- zookeeper 作为注册中心 --> <dependency> <groupId>org.apache.curator</groupId> <artifactId>curator-framework</artifactId> <version>2.12.0</version> </dependency> <!-- SpringBoot使用的依赖 --> <dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>0.2.0</version> </dependency>
让别的服务引入的公共组件
这个一般是叫 framework,统一让别的服务引入的组件模块,一般在里面写想让 dubbo 做 RPC 的接口方法,以及一些共用的工具类和统一返回类型等等。
public interface UserService { List<UserAddress> getUserAddressList(String userId); } public interface OrderService { List<UserAddress> initOrder(String userId); }
服务提供者
修改配置文件
server: port: 8081 dubbo: application: # 指定当前服务/应用的名字 name: user-service-provider # 注册中心 registry: # 使用的协议 protocol: zookeeper address: 127.0.0.1:2181 # 指定通信规则,协议、端口 protocol: name: dubbo port: 20880 # 要扫描的包路径,类上有 dubbo 的 @Service注解 # import com.alibaba.dubbo.config.annotation.Service; scan: base-packages: com.atguigu.gmall # 监控中心 monitor: protocol: registry
启动类
// 开启 dubbo 的功能 @EnableDubbo // 开启服务容错 //@EnableHystrix @SpringBootApplication public class UserServiceProviderApplication { public static void main(String[] args) { SpringApplication.run(UserServiceProviderApplication.class, args); } }
接口方法实现
import com.alibaba.dubbo.config.annotation.Service; import com.atguigu.gmall.pojo.UserAddress; import com.atguigu.gmall.service.UserService; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import java.util.Arrays; import java.util.List; import org.springframework.stereotype.Component; // 这是 dubbo 的注解,暴露服务,不是 Spring 的 // 现在好像改了,改成了 @DubboService,然后别人引入的时候是 @DubboReference @Service // 这才是 Spring 的,将类注册为 bean @Component public class UserServiceImpimplements UserService { // @HystrixCommand @Override public List<UserAddress> getUserAddressList(String userId) { System.out.println("UserServiceImpl..3....."); UserAddress address1 = new UserAddress(1, "北京市昌平区宏福科技园综合楼3层", "1", "李老师", "010-56253825", "Y"); UserAddress address2 = new UserAddress(2, "深圳市宝安区西部硅谷大厦B座3层(深圳分校)", "1", "王老师", "010-56253825", "N"); return Arrays.asList(address1, address2); } }
服务消费者
修改配置文件
server: port: 8082 dubbo: application: # 指定当前服务/应用的名字 name: order-service-consumer # 注册中心 registry: address: zookeeper://127.0.0.1:2181 # 指定通信规则,协议、端口 protocol: name: dubbo port: 20880 # 要扫描的包路径,类上有 dubbo 的 @Service注解 # import com.alibaba.dubbo.config.annotation.Service; scan: base-packages: com.atguigu.gmall # 监控中心 monitor: protocol: registry
启动类
@EnableDubbo //@EnableHystrix @SpringBootApplication public class OrderServiceConsumerApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceConsumerApplication.class, args); } }
接口方法实现
@Service public class OrderServiceImpimplements OrderService { // dubbo 来远程引用 @Reference(loadbalance = "random", timeout = 1000, check = false) UserService userService; // @HystrixCommand(fallbackMethod = "hello") @Override public List<UserAddress> initOrder(String userId) { System.out.println("用户id:" + userId); //1、查询用户的收货地址 List<UserAddress> addressList = userService.getUserAddressList(userId); return addressList; } public List<UserAddress> hello(String userId) { return Arrays.asList(new UserAddress(10, "测试地址", "1", "测试", "测试", "Y")); } }