认识Dubbo
Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。Dubbo 被设计为高度可扩展,用户可以方便的实现流量拦截、选址的各种定制逻辑。
Dubbo3 定义为面向云原生的下一代 RPC 服务框架。3.0 基于 Dubbo 2.x 演进而来,在保持原有核心功能特性的同时, Dubbo3 在易用性、超大规模微服务实践、云原生基础设施适配、安全性等几大方向上进行了全面升级。
Apache Dubbo 总体架构能很好的满足企业的大规模微服务实践,因为它从设计之初就是为了解决超大规模微服务集群实践问题,不论是阿里巴巴还是工商银行、中国平安、携程等社区用户,它们都通过多年的大规模生产环境流量对 Dubbo 的稳定性与性能进行了充分验证,因此,Dubbo 在解决业务落地与规模化实践方面有着无可比拟的优势:
- 开箱即用
易用性高,如 Java 版本的面向接口代理特性能实现本地透明调用
功能丰富,基于原生库或轻量扩展即可实现绝大多数的微服务治理能力 - 面向超大规模微服务集群设计
极致性能,高性能的 RPC 通信协议设计与实现
横向可扩展,轻松支持百万规模集群实例的地址发现与流量治理 - 高度可扩展
调用过程中对流量及协议的拦截扩展,如 Filter、Router、LB 等
微服务治理组件扩展,如 Registry、Config Center、Metadata Center 等 - 企业级微服务治理能力
国内公有云厂商支持的事实标准服务框架
多年企业实践经验考验,参考用户实践案例
Dubbo 基本工作流程
分布式系统
分布式系统是若干独立计算机的集合,是建立在网络之上的软件系统,在一个分布式系统中,一组独立的计算机展现给用户的是一个统一的整体,因此,我们可以将应用拆分几个核心的业务,通过分布式部署,集群构成一个分布式系统,对于用户来说,用户是感觉不到系统的分布性。
分布式系统特征
- (1)分布性。分布式系统由多台计算机组成,它们在地域上是分散的,可以散布在一个单位、一个城市、一个国家,甚至全球范围内。整个系统的功能是分散在各个节点上实现的,因而分布式系统具有数据处理的分布性。
- (2)自治性。分布式系统中的各个节点都包含自己的处理机和内存,各自具有独立的处理数据的功能。通常,彼此在地位上是平等的,无主次之分,既能自治地进行工作,又能利用共享的通信线路来传送信息,协调任务处理。
- (3)并行性。一个大的任务可以划分为若干个子任务,分别在不同的主机上执行。
- (4)全局性。分布式系统中必须存在一个单一的、全局的进程通信机制,使得任何一个进程都能与其他进程通信,并且不区分本地通信与远程通信。同时,还应当有全局的保护机制。系统中所有机器上有统一的系统调用集合,它们必须适应分布式的环境。在所有CPU上运行同样的内核,使协调工作更加容易。
RPC 框架
RPC【Remote Procedure Call】是指远程过程调用,是一种进程间通信方式,他是一种技术的思想,而不是规范。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,编写的调用代码基本相同。
Dubbo工作流程
Dubbo 首先是一款 RPC 框架,它定义了自己的 RPC 通信协议与编程方式。如上图所示,用户在使用 Dubbo 时首先需要定义好 Dubbo 服务;其次,是在将 Dubbo 服务部署上线之后,依赖 Dubbo 的应用层通信协议实现数据交换,Dubbo 所传输的数据都要经过序列化。
流程说明
Dubbo 的第一步就是定义 Dubbo 服务,服务在 Dubbo 中的定义就是完成业务功能的一组方法的集合,可以选择使用与某种语言绑定的方式定义,如在 Java 中 Dubbo 服务就是有一组方法的 Interface 接口,定义好服务之后,服务端(Provider)需要提供服务的具体实现,并将其声明为 Dubbo 服务,而站在服务消费方(Consumer)的视角,通过调用 Dubbo 框架提供的 API 可以获得一个服务代理(stub)对象,然后就可以像使用本地服务一样对服务方法发起调用了。 在消费端对服务方法发起调用后,Dubbo 框架负责将请求发送到部署在远端机器上的服务提供方,提供方收到请求后会调用服务的实现类,之后将处理结果返回给消费端,这样就完成了一次完整的服务调用。如图中的 Request、Response 数据流程所示。
随着微服务架构的发展,应用的部署、发布、扩缩容变得极为频繁,Dubbo通过引入注册中心来协调提供方与消费方的地址,提供者启动之后向注册中心注册自身地址,消费方通过拉取或订阅注册中心特定节点,动态的感知提供方地址列表的变化。
服务提供者(Provider):暴露服务的服务提供方,服务提供者在启动时,向注册中心注册自己提供的服务。
服务消费者(Consumer): 调用远程服务的服务消费方,服务消费者在启动时,向注册中心订阅自己所需的服务,服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
注册中心(Registry):注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者
监控中心(Monitor):服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
调用关系说明
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
Dubbo 核心特性
- 高性能 RPC 通信协议
Dubbo3 还提供更丰富的通信模型选择:
消费端异步请求(Client Side Asynchronous Request-Response)
提供端异步执行(Server Side Asynchronous Request-Response)
消费端请求流(Request Streaming)
提供端响应流(Response Streaming)
双向流式通信(Bidirectional Streaming) - 自动服务(地址)发现机制
Dubbo 提供的是 Client-Based 的服务发现机制,使用者可以有多种方式启用服务发现:
使用独立的注册中心组件,如 Nacos、Zookeeper、Consul、Etcd 等。
将服务的组织与注册交给底层容器平台,如 Kubernetes,这被理解是一种更云原生的使用方式 - 运行态流量管控
透明地址发现让 Dubbo 请求可以被发送到任意 IP 实例上,这个过程中流量被随机分配。当需要对流量进行更丰富、更细粒度的管控时,就可以用到 Dubbo 的流量管控策略,Dubbo 提供了包括负载均衡、流量路由、请求超时、流量降级、重试等策略,基于这些基础能力可以轻松的实现更多场景化的路由方案,包括金丝雀发布、A/B测试、权重路由、同区域优先等,更酷的是,Dubbo 支持流控策略在运行态动态生效,无需重新部署。 - 丰富的扩展组件及生态
支持的组件与部署架构 :注册中心(Zookeeper,Nacos,Kubernetes),元数据中心(Zookeeper,Nacos,Redis),配置中心(Zookeeper,Nacos,Redis,Apollo,Mesh),数据面 Envoy,控制面 Istio,SPI 集成:这里有众多的 Dubbo 扩展实现,包括协议、序列化、注册中心等,网关组件,链路追踪 ,等等
使用Dubbo
1. 安装dubbo-admin管理控制台
1.1下载dubbo管理端:dubbo-admin https://github.com/apache/dubbo-admin
1.2配置信息
下载代码: git clone https://github.com/apache/dubbo-admin.git
在 dubbo-admin-server/src/main/resources/application.properties
中指定注册中心地址
本次使用到的注册、配置中心使用的是nacos,nacos使用教程参考Nacos注册中心,配置中心的使用教程
构建
mvn clean package -Dmaven.test.skip=true
启动
进入dubbo-admin-develop\dubbo-admin-server\target目录,运行
java -jar dubbo-admin-server-0.5.0.jar
访问 http://localhost:8080
启动管理端成功
建立服务提供者
1pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba</artifactId>
<groupId>com.awei</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-gmall-user</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.awei</groupId>
<artifactId>dubbo-reference</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.0.9</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
</dependencies>
</project>
2.配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder/>
<bean id="userServiceImpl" class="com.awei.service.impl.UserServiceImpl"/>
<!--当前应用的名字 -->
<dubbo:application name="user-provider"></dubbo:application>
<!--指定注册中心的地址 -->
<dubbo:registry address="nacos://localhost:8848" />
<!--使用dubbo协议,将服务暴露在20880端口 -->
<dubbo:protocol name="dubbo" port="8888" />
<!-- 指定需要暴露的服务 -->
<dubbo:service interface="com.awei.services.UserService" ref="userServiceImpl" />
</beans>
3.业务类
package com.awei.service.impl;
import com.awei.entitis.UserAddress;
import com.awei.services.UserService;
import java.util.ArrayList;
import java.util.List;
/**
* @author Awei
* @date 2022/10/22 16:28
*/
public class UserServiceImpl implements UserService {
@Override
public List<UserAddress> getUserAddressList(String userId) {
ArrayList<UserAddress> array = new ArrayList<UserAddress>();
array.add(new UserAddress(1,"贵州省云岩区汇金路88号", "000",
"陈林睿","13598452584","1"));
array.add(new UserAddress(2,"贵州省云岩区汇金路99号", "000",
"陈林睿1","13598452584","0"));
return array;
}
}
4.启动程序
package com.awei.service.impl.com.awei.main;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
/**
* @author Awei
* @date 2022/10/22 17:46
*/
public class UserMain {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("provider.xml");
//启动
ioc.start();
System.in.read();
}
}
5.查看dubbo管理端,服务注册成功
## 建立服务消费者
1.pom文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-alibaba</artifactId>
<groupId>com.awei</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-gamll-order</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.awei</groupId>
<artifactId>dubbo-reference</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 引入dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.0.9</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
</project>
2.配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder/>
<context:component-scan base-package="com.awei.service"></context:component-scan>
<dubbo:application name="order-consumer"></dubbo:application>
<dubbo:registry address="nacos://localhost:8848" />
<!--声明要调用的远程服务接口:生成远程服务代理-->
<dubbo:reference interface="com.awei.services.UserService" id="userService"></dubbo:reference>
</beans>
3.启动服务,调用服务提供者接口
package com.awei.service.impl;
import com.awei.entitis.UserAddress;
import com.awei.services.OrderService;
import com.awei.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author Awei
* @date 2022/10/22 17:25
*/
@Component
public class OrderServiceImpl implements OrderService {
UserService userService;
@Override
public List<UserAddress> CreatOrder(String id) {
List<UserAddress> userAddresses = userService.getUserAddressList(id);
return userAddresses;
}
}
4.调用结果
更多使用说明可参考dubbo官网文档dubbo xml配置