Back
Featured image of post Dubbo+Nacos实现RPC

Dubbo+Nacos实现RPC

RESTful 与 RPC 的区别

在微服务定义中提道,每个小服务运行在自己的进程中,并以轻量级的机制进行通信。这里并没有明确给出具体的通信方式,只是要求以轻量级的机制进行通信,虽然作者推荐使用 RESTful 作为首选方案,但微服务间通信本身还有另一个轻量级的选择:以 Dubbo 为代表的 RPC通信方式。

RPC 是远程过程调用(Remote Procedure Call)的缩写形式,RPC 与 RESTful 最大的不同是,RPC 采用客户端(Client) - 服务端(Server) 的架构方式实现跨进程通信,实现的通信协议也没有统一的标准,具体实现依托于研发厂商的设计。

目前开源市场上 RPC 框架有很多,例如 GoogleRPC、Alibaba Dubbo、Facebook Thrift,每一种产品都有自己的设计与实现方案。

那 RESTful 与 RPC 有什么区别呢?通过一个表格进行说明:

Apache Dubbo

Dubbo 是阿里巴巴开源的高性能、轻量级的开源 Java 框架,目前被 Apache收录,官网是: http://dubbo.apache.org/

Dubbo 是典型的 RPC 框架的代表,通过客户端/服务端结构实现跨进程应用的高效二进制通信。

Apache Dubbo 提供了六大核心能力:

面向接口代理的高性能 RPC 调用;

智能容错和负载均衡;

服务自动注册和发现;

高度可扩展能力;

运行期流量调度;

可视化的服务治理与运维。

下图引用 Dubbo 的官方架构图,讲解 ApacheDubbo 的组成。

Dubbo 架构中,包含 5 种角色。

  • Provider:RPC服务提供者,Provider 是消息的最终处理者。
  • Container:容器,用于启动、停止 Provider 服务。这里的容器并非 Tomcat、Jetty 等 Web 容器,Dubbo 也并不强制要求 Provider 必须具备 Web 能力。Dubbo 的容器是指对象容器,例如 Dubbo 内置的 SpringContainer 容器就提供了利用 Spring IOC 容器管理 Provider 对象的职能。
  • Consumer:消费者,调用的发起者。Consumer 需要在客户端持有 Provider 的通信接口才能完成通信过程。
  • Registry:注册中心,Dubbo 架构中注册中心与微服务架构中的注册中心职责类似,提供了 Dubbo Provider 的注册与发现职能,Consumer通过 Registry 可以获取Provider 可用的节点实例的 IP、端口等,并产生直接通信。需要注意的是,前面我们讲解的 Alibaba Nacos 除了可以作为微服务架构中的注册中心外,同样对自家的 Dubbo 提供了 RPC 调用注册发现的职责,这是其他 Spring Cloud 注册中心所不具备的功能。
  • Monitor:监控器,监控器提供了Dubbo的监控职责。在 Dubbo 产生通信时,Monitor 进行收集、统计,并通过可视化 UI 界面帮助运维人员了解系统进程间的通信状况。Dubbo Monitor 主流产品有 Dubbo Admin、Dubbo Ops 等。

项目整合

服务提供者Provider

  • 引入依赖
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>2.7.8</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

相比标准微服务,需要额外依赖 dubbo-spring-boot-starterspring-boot-starter-actuator。其中 dubbo-spring-boot-starter 是 Dubbo 与 Spring Boot 整合最关键的组件,为 Spring Boot 提供了 Dubbo 的默认支持。而 spring-boot-starter-actuator则为微服务提供了监控指标接口,便于监控系统从应用收集各项运行指标。

  • 配置文件
server:
  port: 8000 #服务端口
spring:
  application:
    name: warehouse-service #微服务id
  cloud:
    nacos: #nacos注册地址
      discovery:
        server-addr: 192.168.31.101:8848
        username: nacos
        password: nacos
dubbo: #dubbo与nacos的通信配置
  application:
    name: warehouse-dubbo #provider在Nacos中的应用id
  registry: #Provider与Nacos通信地址,与spring.cloud.nacos地址一致
    address: nacos://192.168.31.101:8848
  protocol: 
    name: dubbo #通信协议名
    port: 20880 #配置通信端口,默认为20880
  scan: 
    base-packages: com.lagou.warehouseservice.dubbo

Dubbo 需要依托 Container(容器)对外暴露服务,而这个容器配置与微服务配置是分开的,需要额外占用一个网络端口20880提供服务。

dubbo.scan.base-packages 代表在 Dubbo 容器启动时自动扫描 com.lagou.warehouseservice.dubbo 包下的接口与实现类,并将这些接口信息在Nacos 进行登记,因此 Dubbo 对外暴露的接口必须放在该包下。

  • 开发服务

实体类dto这里不做示例了

下面是com.lagou.warehouseservice.dubbo包下创建的服务接口,包名要与 dubbo.scan.base-packages 保持一致

//Provider接口
public interface WarehouseService {
    //查询库存
    public Stock getStock(Long skuId);
}

com.lagou.warehouseservice.dubbo.impl包下创建实现类

@DubboService
public class WarehouseServiceImpl implements WarehouseService {
    public Stock getStock(Long skuId){
        /*
				 code
				*/
        return stock;
    }
}

需要额外增加 @DubboService注解。@DubboService 是 Provider 注解,说明该类所有方法都是服务提供者,加入该注解会自动将类与方法的信息在 Nacos中注册为 Provider。

服务消费者Consumer

  • 引入依赖和服务提供者一样
  • 配置文件
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.31.101:8848
        username: nacos
        password: nacos
server:
  port: 9000
dubbo:
  application:
    name: order-service-dubbo
  registry:
    address: nacos://192.168.31.101:8848
  • 将处于服务提供方的服务接口和相关实体类复制到调用方

接口就行,接口的实现类不用。相当于声明了通信接口,注意要求包名、类名及代码保持完全一致。上面是在与原项目同级目录新建了一个和服务提供方一样的包路径。

  • 消费者调用服务
@RestController
public class OrderController {
    
		@DubboReference
    private WarehouseService warehouseService;
    
    @GetMapping("/create_order")
    public Map createOrder(Long skuId , Long salesQuantity){
        
				// 查询商品库存,像调用本地方法一样完成业务逻辑。
        Stock stock = warehouseService.getStock(skuId);

				// code				

        return result;
    }
}

关键点是 @DubboReference 注解。该注解用在 Consumer 端,Spring 会自动生成远程服务的接口的代理实现类,并隐藏远程通信细节。

微服务启动后,在nacos的服务列表界面可以看到微服务和Dubbo的服务,表示注册成功了。

小坑

引入了spring-boot-starter-actuator 会与ShardingSphere检查数据库连接时产生冲突,抛出错误

org.springframework.dao.InvalidDataAccessApiUsageException: ConnectionCallback; isValid; 
nested exception is java.sql.SQLFeatureNotSupportedException: isValid

解决办法:

配置文件加上

management:
  health:
    db:
      enabled: false
comments powered by Disqus
一辈子热爱技术
Built with Hugo
Theme Stack designed by Jimmy
gopher