SpringCloud Alibaba (四):Dubbo RPC框架

Dubbo简介

Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。致力于提高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。

节点 角色说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心
Container 服务运行容器

功能特点 :

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

    提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节。

  • 智能负载均衡

    内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。

  • 服务自动注册与发现

    支持多种注册中心服务,服务实例上下线实时感知。

  • 高度可扩展能力

    遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。

  • 运行期流量调度

    内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。

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

    提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。

Spring Cloud 为什么需要RPC

在Spring Cloud构建的微服务系统中,大多数的开发者使用都是官方提供的Feign组件来进行内部服务通信,这种声明式的HTTP客户端使用起来非常的简洁、方便、优雅,但是有一点,在使用Feign消费服务的时候,相比较Dubbo这种RPC框架而言,性能堪忧。

虽说在微服务架构中,会讲按照业务划分的微服务独立部署,并且运行在各自的进程中。微服务之间的通信更加倾向于使用HTTP这种简答的通信机制,大多数情况都会使用REST API。这种通信方式非常的简洁高效,并且和开发平台、语言无关,但是通常情况下,HTTP并不会开启KeepAlive功能,即当前连接为短连接,短连接的缺点是每次请求都需要建立TCP连接,这使得其效率变的相当低下。

对外部提供REST API服务是一件非常好的事情,但是如果内部调用也是使用HTTP调用方式,就会显得显得性能低下,Spring Cloud默认使用的Feign组件进行内部服务调用就是使用的HTTP协议进行调用,这时,我们如果内部服务使用RPC调用,对外使用REST API,将会是一个非常不错的选择,恰巧,Dubbo Spring Cloud给了我们这种选择的实现方式。

SpringCloud Alibaba 整合 Dubbo

创建ApacheDubbo总工程, 在pom.xml添加统一依赖



    4.0.0
​
    com.gofy
    ApacheDubbo
    1.0-SNAPSHOT
    pom
​
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.8.RELEASE
    
​
    
        dubbo-provider
        dubbo-consumer
    
​
    
        
        1.8
        UTF-8
        UTF-8
        Greenwich.SR3
        0.2.1.RELEASE
        2.7.6
        2.7.6
        2.7.6
        2.7.6
        2.7.6
        2.1.0.RELEASE
        1.0.6
    
​
    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                pom
                import
            
            
                org.springframework.cloud
                spring-cloud-alibaba-dependencies
                ${spring-cloud-alibaba.version}
                pom
                import
            
​
            
            
                org.apache.dubbo
                dubbo
                ${dubbo.version}
                
                    
                        org.springframework
                        spring
                    
                    
                        javax.servlet
                        servlet-api
                    
                    
                        log4j
                        log4j
                    
                
            
            
                org.apache.dubbo
                dubbo-spring-boot-actuator
                ${dubbo-actuator.version}
            
            
                org.apache.dubbo
                dubbo-spring-boot-starter
                ${dubbo-spring.version}
            
            
            
                org.apache.dubbo
                dubbo-serialization-kryo
                ${dubbo-kryo.version}
            
​
            
            
                com.alibaba
                dubbo-registry-nacos
                ${dubbo-nacos.version}
            
            
                com.alibaba.nacos
                nacos-client
                1.2.1
            
            
                com.alibaba.cloud
                spring-cloud-starter-alibaba-nacos-config
                ${dubbo-nacos-config.version}
            
            
                com.alibaba.spring
                spring-context-support
                ${spring-context-support.version}
            
        
    
​
    
        
            
            
                org.apache.maven.plugins
                maven-compiler-plugin
                
                    true
                
            
        
​
        
        
            
                src/main/java
                
                    **/*.java
                
            
            
                src/main/resources
            
        
    

服务提供者

在Dubbo RPC框架中, 服务提供者的接口类和实现类应该分开为俩个模块, 所以我们应该在服务提供者下创建两个子模块, 分别为 接口模块dubbo-provider-api 实现模块dubbo-provider-service

在总工程 ApacheDubbo 下创建 dubbo-provider 模块, 添加服务提供者的统一依赖



    4.0.0

    
        ApacheDubbo
        com.gofy
        1.0-SNAPSHOT
    

    com.gofy
    dubbo-provider
    1.0-SNAPSHOT
    pom

    
        dubbo-provider-api
        dubbo-provider-service
    

  • dubbo-provider 下创建 dubbo-provider-api 子模块, 并添加依赖



    4.0.0
    
        dubbo-provider
        com.gofy
        1.0-SNAPSHOT
    
​
    com.gofy
    dubbo-provider-api
    1.0-SNAPSHOT
    jar
​

创建接口类 EchoService

package com.gofy.dubbo.api;
​
public interface EchoService {
    String echo(String s);
}
  • dubbo-provider 下创建 dubbo-provider-service 子模块, 并添加依赖

导入接口模块失败原因: 一般是总工程的统一依赖出了问题, 可以查看本地maven仓库的中总工程导入的依赖的包有没有缺失文件. 我之前失败原因就是 spring-cloud-dependencies 包出了问题, Greenwich.SR5版本下载一直缺失文件, 改为Greenwich.SR3就好了.



    4.0.0
    
        dubbo-provider
        com.gofy
        1.0-SNAPSHOT
    

    com.gofy
    dubbo-provider-service
    jar

    
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        

        
            org.apache.dubbo
            dubbo
        
        
            org.apache.dubbo
            dubbo-spring-boot-starter
        
        
            org.apache.dubbo
            dubbo-serialization-kryo
        
        
            com.alibaba
            dubbo-registry-nacos
        
        
            com.alibaba.nacos
            nacos-client
        

        
            com.alibaba.spring
            spring-context-support
        

        
        
            com.gofy
            dubbo-provider-api
            1.0-SNAPSHOT
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    com.gofy.dubbo.ProviderApplication
                
            
        
    


dubbo-provider-service 的application.yml里添加配置

注:如果要在 SpringClou Alibaba+Dubbo 中使用nacos动态配置,操作与之前naocs动态配置的操作一样

spring:
  application:
    name: dubbo-provider
  main:
    allow-bean-definition-overriding: true # 解决bean重复定义,设置为true时,后定义的bean会覆盖之前定义的相同名称的bean

dubbo:
  scan:
    base-packages: com.gofy.dubbo.service # 实现类所在的包
  protocol:
    name: dubbo
    port: -1 # 端口为-1时,即是让dubbo自动分配端口
    serialization: kryo # 使用kryo序列化/反序列化工具
  registry:
    address: nacos://192.168.11.132:8848 #注册中心地址,格式为 注册中心组件名://注册中心访问地址

创建实现类 EchoServiceImpl

package com.gofy.dubbo.service;
​
import com.gofy.dubbo.api.EchoService;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Value;
​
@Service(version = "1.0.0") //服务版本号
public class EchoServiceImpl implements EchoService {
​
    @Override
    public String echo(String s) {
        return "Hello Dubbo "+s;
    }
}

创建启动类 ProviderApplication

@SpringBootApplication
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}

服务消费者

在总工程 ApacheDubbo 下创建服务消费者 dubbo-consumer , 并添加依赖



    4.0.0
    
        ApacheDubbo
        com.gofy
        1.0-SNAPSHOT
    

    com.gofy
    dubbo-consumer
    jar

    
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        

        
        
            org.apache.dubbo
            dubbo
        
        
            org.apache.dubbo
            dubbo-spring-boot-starter
        
        
            org.apache.dubbo
            dubbo-spring-boot-actuator
        
        
            org.apache.dubbo
            dubbo-serialization-kryo
        
        
        
        
            com.alibaba
            dubbo-registry-nacos
        
        
            com.alibaba.nacos
            nacos-client
        
        
            com.alibaba.spring
            spring-context-support
        

        
        
            com.gofy
            dubbo-provider-api
            1.0-SNAPSHOT
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                
                    com.gofy.dubbo.ConsumerApplication
                
            
        
    

dubbo-consumer 的application.yml里添加配置

server:
  port: 8080
​
spring:
  application:
    name: dubbo-consumer
  main:
    allow-bean-definition-overriding: true
​
dubbo:
  scan:
    base-packages: com.gofy.dubbo.controller #controller类所在包
  protocol:
    name: dubbo
    port: -1
    serialization: kryo
  registry:
    address: nacos://192.168.11.132:8848
​
endpoints:
  dubbo:
    enabled: true #允许暴露dubbo分配的端点
​
management:
  health: #健康检查
    dubbo:
      status:
        defaults: memory
        extras: threadpool
  endpoints: #暴露所有web端点
    web:
      exposure:
        include: "*"

创建controller类 EchoController

package com.gofy.dubbo.controller;
​
import com.gofy.dubbo.api.EchoService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
​
@RestController
public class EchoController {
​
    @Reference(version = "1.0.0") //通过服务的版本号注入
    EchoService echoService;
    
    @GetMapping("/echo/{s}")
    public String echo(@PathVariable("s")String s){
        return echoService.echo(s);
    }
}

创建启动类 ConsumerApplication

@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
}

访问测试

访问nacos注册中心,查看已注册服务

访问 localhost:8080/echo/hi , 成功获取到服务提供者返回的信息

Dubbo负载均衡

当我们对内使用Dubbo的RPC通信,不再使用RestTemplate或feign的 HTTP通信时,我们要怎么使用负载均衡呢?

在 Dubbo 中,也有负载均衡的概念和相应的实现。Dubbo 需要对服务消费者的调用请求进行分配,避免少数服务提供者负载过大。服务提供者负载过大,会导致部分请求超时。因此将负载均衡到每个服务提供者上,是非常必要的。Dubbo 提供了4种负载均衡实现,分别是基于权重随机算法的 RandomLoadBalance、基于最少活跃调用数算法的 LeastActiveLoadBalance、基于 hash 一致性的 ConsistentHashLoadBalance,以及基于加权轮询算法的 RoundRobinLoadBalance。

源码分析

Dubbo负载均衡的源码在 org.apache.dubbo:dubbo下的org.apache.dubbo.rpc.cluster.loadbalance

通过源码可以发现4个负载均衡策略的实现类都继承了AbstractLoadBalance抽象类,而AbstractLoadBalance实现了LoadBalance接口。

再来看看LoadBalance接口,可以知道duboo是通过 loadbalance属性来适配负载均衡接口的实现类,且默认值为 random 权重随机。

@SPI("random")
public interface LoadBalance {
    @Adaptive({"loadbalance"})
     Invoker select(List<Invoker> invokers, URL url, Invocation invocation) throws RpcException;
}

所以,我们只要在 @Reference注解里添加 loadbalance属性 ,就可以选择dubbo的负载均衡策略了

loadbalance属性值为负载均衡实现类的 NAME 属性,分别是:

random 、roundrobin 、leastactive 、consistenthash

@Reference(version = "1.0.0", loadbalance = "roundrobin")
EchoService echoService;

负载均衡策略实现类的详细源码分析, dubbo官方文档 里讲解得非常好,就不多转述了

我的个人博客站


翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via
谷歌翻译(国内)

翻译 朗读 复制 正在查询,请稍候…… 重试 朗读 复制 复制 朗读 复制 via 谷歌翻译(国内)