Dubbo的基本应用

什么是Dubbo

Dubbo是阿里巴巴公司开源的一个高性能、轻量级的 Java RPC 框架

致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。

Dubbo的发展历史

2011/10/27: 阿里巴巴巴宣布 Dubbo 开源。

2012/10/23: 发布最后一个版本 2.5.3 并停止维护更新。

2017/07/31: 起死回生,官方宣布开启重新更新,并会得到重点维护.

2017/09/07: 发布起死回生的第一个版本:dubbo-2.5.4。

2018/01/08:

1、Dubbo 团队透露 Dubbo 3.0 宣布正式开工

2、发布了 dubbo-2.6.0 版本,主要合并了由当当网开源的 dubbox 项目分支。PS:dubbo停止维护期间,当当网基于 dubbo 开源了dubbox。

2018/01/22: Dubbo Spring Boot 版正式发布:dubbo-spring-boot-starter v1.0.0 公测版。

2018/02/09: Dubbo 通过投票正式进入 Apache 基金会孵化器,更新了 Apache 官方域名,也不再仅限于 Java 语言。

2019/05/20: Apache 软件基金会宣布 Dubbo 正式毕业,成为 Apache 的顶级项目。

2021/7月1日 : Dubbo 3.0版本正式发布

Dubbo主要特性

  • 面向接口代理的高性能RPC调用:提供高性能的基于代理的远程调用能力,服务以接口为粒度,屏蔽了远程调用底层细节。
  • 智能负载均衡:内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。(不太优秀,可以使用其他的组件)
  • 服务自动注册与发现:支持多种注册中心服务,服务实例上下线实时感知。(Dubbo+Zookeeper/nacos/eurake)
  • 高度可扩展能力:遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。
  • 运行期流量调度:内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。
  • 可视化的服务治理与运维:提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。

Dubbo的工作原理:

image-20230304002039464

注册中心是基于长链接推送到消费者,eurake是短连接TCP

  • 注册中心。协调 Consumer 与 Provider 之间的地址注册与发现
  • 配置中心。
    • 存储 Dubbo 启动阶段的全局配置,保证配置的跨环境共享与全局一致性
    • 负责服务治理规则(路由规则、动态配置等)的存储与推送。
  • 元数据中心。
    • 接收 Provider 上报的服务接口元数据,为 Admin 等控制台提供运维能力(如服务测试、接口文档等)
    • 作为服务发现机制的补充,提供额外的接口/方法级别配置信息的同步能力,相当于注册中心的额外扩展

保证三大中心高可用的部署架构

虽然三大中心已不再是Dubbo应用服务所必须的,但是在真实的生产环境中,一旦已经集成并且部署了该三大中心,三大中心还是会面临可用性问题,Dubbo需要支持三大中心的高可用方案。在Dubbo中就支持多注册中心、多元数据中心、多配置中心,来满足同城多活、两地三中心、异地多活等部署架构模式的需求。

  • 多注册中心:Dubbo 支持多注册中心,即一个接口或者一个应用可以被注册到多个注册中心中,比如可以注册到ZK集群和Nacos集群中,Consumer也能够从多个注册中心中进行订阅相关服务的地址信息,从而进行服务发现。通过支持多注册中心的方式来保证其中一个注册中心集群出现不可用时能够切换到另一个注册中心集群,保证能够正常提供服务以及发起服务调用。这也能够满足注册中心在部署上适应各类高可用的部署架构模式。
  • 多配置中心:Dubbo支持多配置中心,来保证其中一个配置中心集群出现不可用时能够切换到另一个配置中心集群,保证能够正常从配置中心获取全局的配置、路由规则等信息。这也能够满足配置中心在部署上适应各类高可用的部署架构模式。
  • 多元数据中心:Dubbo 支持多元数据中心:用于应对容灾等情况导致某个元数据中心集群不可用,此时可以切换到另一个元数据中心集群,保证元数据中心能够正常提供有关服务元数据的管理能力。

短连接每一次链接时都要创建一次连接,消耗性能。

image-20230303222330445

服务治理抽象控制面:是对Dubbo治理体系的抽象表达。控制面包含注册中心、流量监控策略、控制台,如果采用了 Service Mesh 架构则还包含 Istio 等服务网格控制面。

Dubbo数据面:数据面代表集群部署的所有 Dubbo 进程,进程之间通过 RPC 协议实现数据交换。

  • 服务消费者 (Dubbo Consumer),发起业务调用或 RPC 通信的 Dubbo 进程
  • 服务提供者 (Dubbo Provider),接收业务调用或 RPC 通信的 Dubbo 进程
  • 从数据面视角,Dubbo 帮助解决了微服务实践中的以下问题:
    • Dubbo 作为 服务开发框架 约束了微服务定义、开发与调用的规范,定义了服务治理流程及适配模式
    • Dubbo 作为 RPC 通信协议实现 解决服务间数据传输的编解码问题

Dubbo的基本使用

dubbo的配置文件为什么可以和spring的xml适配?

spring的2.5之后 ,Spring支持自定义Schema扩展XML配置

服务端

添加依赖

<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.8</version>
</dependency>

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<!--dubbo全局的服务名-->
<dubbo:application name="dubbo-server" />
<!--注册中心-->
<dubbo:registry address="N/A" timeout="10000" check="false"/>
<!--下面是nocas的注册中心,如果是zookeeper的,就换成zookeeper://....-->
<!--<dubbo:registry address="nacos://localhost:8848" timeout="10000"/>-->
<!-- 服务名称 及 端口号-->
<dubbo:protocol name="dubbo" port="20880" />
<!--需要发布的服务-->
<dubbo:service interface="com.example.dubbo.server.IloginService" ref="loginService" />
<!--dubbo的实现-->
<bean id="loginService" class="com.example.dubbo.server.IloginServiceImpl"/>


</beans>

响应

public class IloginServiceImpl implements IloginService{

@Override
public String login(String username, String password) {
//实现业务逻辑
if (username.equals("admin")&password.equals("admin")){
return "SUCCESS";
}
return "FAILED";
}
}

客户端

配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

<!--dubbo名称-->
<dubbo:application name="dubbo-client" />
<!--注册中心-->
<dubbo:registry address="nacos://localhost:8848" timeout="10000"/>
<!--服务地址-->
<dubbo:reference id="loginService" interface="com.example.dubbo.server.IloginService"
url="dubbo://192.168.31.170:20880/com.example.dubbo.server.IloginService" />

</beans>

请求

public class App 
{
public static void main( String[] args )
{
IloginService iloginService =null;
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:/META-INF/spring/application.xml");
iloginService = ac.getBean(IloginService.class);
System.out.println(iloginService.login("admin","admin"));
}
}

Dubbo支持的注册中心

consul、zk、Eureka、Redis、ectd、nacos、Dubbo、Spring Cloud

Dubbo vs Spring Cloud

Dubbo Spring Cloud
服务注册中心 Zookeeper Spring Cloud Netfix Eureka
服务调用方式 RPC REST API
服务监控 Dubbo-monitor Spring Boot Admin
熔断器 不完善 Spring Cloud Netflix Hystrix
服务网关 无 Spring Cloud Netflix Zuul
分布式配置 无 Spring Cloud Config
服务跟踪 无 Spring Cloud Sleuth
数据流 无 Spring Cloud Stream
批量任务 无 Spring Cloud Task
信息总线 无 Spring Cloud Bus

Dubbo主要做的是服务治理,可以通过整合其他组件来满足需求

并在之后和Spring Cloud整合为Dubbo Spring Cloud

功能组件 Spring Cloud Dubbo Spring Cloud
分布式配置(Distributed configuration) Git、Zookeeper、Consul、JDBC Spring Cloud 分布式配置 + Dubbo 配置中心
服务注册与发现(Service registration and discovery) Eureka、Zookeeper、Consul Spring Cloud 原生注册中心 + Dubbo 原生注册中心
负载均衡(Load balancing) Ribbon(随机、轮询等算法) Dubbo 内建实现(随机、轮询等算法 + 权重等特性)
服务熔断(Circuit Breakers) Spring Cloud Hystrix Spring Cloud Hystrix + Alibaba Sentinel 等
服务调用(Service-to-service calls) Open Feign、RestTemplate Spring Cloud 服务调用 + Dubbo @Reference
链路跟踪(Tracing) Spring Cloud Sleuth + Zipkin Zipkin、opentracing 等

以上对比表格摘自Dubbo Spring Cloud官方文档。本质上 都是为业务而生

Dubbo Spring Cloud的基本使用

nocas

  1. 进入依赖

    <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
    <version>2.2.7.RELEASE</version>
    </dependency>
    <dependency>
    <groupId>com.alibaba.cloud</ groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    <version>2.2.7.RELEASE</version>
    </dependency>
  2. 配置文件

    #dubbo服务描基础包路路径
    dubbo.scan.base-packages=com.example.springcloud.dubbo.provider

    #端口号 -1(20880开始自增)
    dubbo.protocol.name=dubbo
    dubbo.protocol.port=20880

    #注册中心地址
    spring.cloud.nacos.discovery.server-addr=localhost:8848
  3. 引入服务

    在需要引入的服务上加注解

    import org.apache.dubbo.config.annotation.Service;

    //@Service中可以配置dubbo相关的业务,用于暴露服务的注解
    @Service
    public class UserServiceImpl implements UserService {
    @Override
    public List<UserDTO> getUsers(InputParaDTO para) {
    System.out.println("====provider invoke====");
    }
    }
    @SpringBootApplication
    @EnableDiscoveryClient//客户端自动注册
    public class DubboProviderApplication {
    public static void main(String[] args) {
    SpringApplication.run(DubboProviderApplication.class,args);
    }
    }

zookeeper

  1. 进入依赖

    <dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>3.0.8</version>
    </dependency>
    <dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-x-discovery</artifactId>
    <version>5.2.1</version>
    </dependency>
  2. 配置文件

    dubbo:
    application:
    name: dubbo-provider
    registry:
    address: zookeeper://192.168.1.6:2181
    protocol:
    name: dubbo
    port: 20881

    server:
    port: 8090
    servlet:
    context-path: /dubbo-provider
  3. 引入服务

    在需要引入的服务上加注解

    import org.apache.dubbo.config.annotation.DubboService;

    @DubboService
    public class UserServiceImpl implements UserService {
    @Override
    public List<UserDTO> getUsers(InputParaDTO para) {
    System.out.println("====provider invoke====");
    }
    }
    @SpringBootApplication
    @EnableDubbo//客户端自动注册
    public class DubboProviderApplication {
    public static void main(String[] args) {
    SpringApplication.run(DubboProviderApplication.class,args);
    }
    }

以上两种都可以实现基本功能

Dobbo的使用

Dubbo多注册中心

Dubbo 支持同一服务向多注册中心同时注册,或者不同服务分别注册到不同的注册中心上去,甚至可以同时引用注册在不同注册中心上的同名服务。

provider

单服务多注册中心注册

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

<dubbo:application name="world" />
<!-- 多注册中心配置 -->
<dubbo:registry id="hangzhouRegistry" address="10.20.141.150:9090" /><!--杭州注册中心-->
<dubbo:registry id="wenzhouRegistry" address="10.20.141.151:9010" default="false" /><!--温州注册中心-->
<!-- 一个服务向多个注册中心注册 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="hangzhouRegistry,wenzhouRegistry" />
</beans>

不同服务使用不同注册中心

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

<dubbo:application name="world" />
<!-- 多注册中心配置 -->
<dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />
<dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" />
<!-- 向中文站注册中心注册 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" registry="chinaRegistry" />
<!-- 向国际站注册中心注册 -->
<dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" registry="intlRegistry" />
</beans>

consumer

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="world" />
<!-- 多注册中心配置 -->
<dubbo:registry id="chinaRegistry" address="10.20.141.150:9090" />
<dubbo:registry id="intlRegistry" address="10.20.154.177:9010" default="false" />
<!-- 引用中文站服务 -->
<dubbo:reference id="chinaHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="chinaRegistry" />
<!-- 引用国际站站服务 -->
<dubbo:reference id="intlHelloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" registry="intlRegistry" />
</beans>

多注册中心引用

如果只是测试环境临时需要连接两个不同注册中心,使用竖号分隔多个不同注册中心地址:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<dubbo:application name="world" />
<!-- 多注册中心配置,竖号分隔表示同时连接多个不同注册中心,同一注册中心的多个集群地址用逗号分隔 -->
<dubbo:registry address="10.20.141.150:9090|10.20.154.177:9010" />
<!-- 引用服务 -->
<dubbo:reference id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" />
</beans>

Dubbo多协议支持

Dubbo 从设计上不绑定任何一款特定通信协议,HTTP/2、REST、gRPC、JsonRPC、Thrift、Hessian2 等几乎所有主流的通信协议,Dubbo 框架都可以提供支持。 但是Dubbo官网是推荐我们使用Dubbo协议。Dubbo可以发布单个协议,也可以针对同一服务发布多个协议,多个服务发布多种协议等操作

Dubbo 对通信协议的支持具有以下特点:

  • 不绑定通信协议
  • 提供高性能通信协议实现
  • 支持流式通信模型
  • 不绑定序列化协议
  • 支持单个服务的多协议暴露
  • 支持单端口多协议发布
  • 支持一个应用内多个服务使用不同通信协议

Dubbo 容许配置多协议,在不一样服务上支持不一样协议或者同一服务上同时支持多种协议。

不一样服务使用不一样协议

不一样服务在性能上适用不一样协议进行传输,好比大数据用短链接协议,小数据大并发用长链接协议

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">


<dubbo:application name="world" />
<dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" />

<!-- 多协议配置 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="rmi" port="1099" />

<!-- 指定使用 dubbo协议 -->
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService" protocol="dubbo" />

<!-- 指定使用 rmi协议 -->
<dubbo:service interface="com.alibaba.hello.api.DemoService" version="1.0.0" ref="demoService" protocol="rmi" />

</beans>

同时使用多种协议

须要与 http 客户端互操做

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">


<dubbo:application name="world" />
<dubbo:registry id="registry" address="10.20.141.150:9090" username="admin" password="hello1234" />

<!-- 多协议配置 -->
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:protocol name="hessian" port="8080" />

<!-- 使用多个协议暴露服务 -->
<dubbo:service id="helloService" interface="com.alibaba.hello.api.HelloService" version="1.0.0" protocol="dubbo,hessian" />

</beans>

dubbo 支持的9种协议

Dubbo架构设计

image-20230303234456857

  • Service:接口层,为了让生产者更好的发布服务,让消费者更好的消费服务

  • Config:对外配置接口。生产者实现interface接口,并使用ServiceConfig来进行发布服务;消费者通过ReferenceConfig(即reference标签)引用服务,并进行代理

  • Proxy:服务代理层。消费者通过动态代理为接口创建代理类。ProxyFactory中默认提供了很多的扩展点(可扩展性的体现);生产者通过getInvoker方法获取到代理对象接口的真实实现(会存储真实的接口、配置、元数据信息);消费者通过getProxy方法获取到远程invoker接口的代理对象

  • Registy:注册中心层服务的发现和注册。RegistryFactory接口有很多的方法,且都有@Adaptive({“protocol”})注解,RegistryProrocol可以通过配置的protocol参数,进行不同的实现,并且将对应的信息保存到RegistryDirectory中。RegistryFactory默认兼容zookeeper、redis、nocas…并且都有对应的实现类

image-20230303232204235

  • Cluster:路由层提供调用场景的抽象(集群容错的抽象层),扩展点。

    • 容错:失败重试、快速失败、失败不作处理

    • 路由:条件路由、文件路由、脚本路由

    • 负载均衡:随机、轮询、一次性hash…

  • Monitor:监控层。监控RPC的调用次数,调用耗时…都会进行统计

  • Prorocol:远程调用层(最核心)。进行服务的暴露和引用

    • 多协议的实现
  • exchange:信息交换层。进行信息交换,封装请求响应模式;同步转异步

  • Transpot:网络传输层,抽象mina和netty为统一接口

  • Serialize:数据序列化层,提供一些可复用的工具

每一层的代码都很灵活,可以自由的对其中的代码进行替换,且不影响逻辑

在Dubbo的核心领域模型中:

  • Protocol是服务域,它是Invoker暴露和引用的主功能入口,它负责Invoker的生命周期管理。
  • Invoker是实体域,它是Dubbo的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起invoke调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。
  • Invocation是会话域,它持有调用过程中的变量,比如方法名,参数等。