初识Dubbo

什么是 Dubbo

Dubbo是阿里巴巴开源的基于Java的高性能RPC分布式服务框架,现已成为Apache基金会孵化项目。致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。

什么是 RPC?

在分布式计算,远程过程调用(英语:Remote Procedure Call,缩写为 RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开放网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额外地为这个交互作用编程(无需关注细节)。RPC是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受回应进行信息交互的系统。

如果涉及的软件采用面向对象编程,那么远程过程调用亦可称作远程调用或远程方法调用,例:Java RMI。

所以,对于Java程序员而言,RPC就是远程⽅法调⽤。远程方法调⽤和本地⽅法调用是相对的两个概念,本地⽅法调⽤指的是进程内部的⽅法调⽤,而远程⽅法 调用指的是两个进程内的方法相互调⽤。 如果实现远程⽅法调⽤,基本的就是通过网络,通过传输数据来进行调⽤。

所以就有了:

  1. RPC over Http:基于Http协议来传输数据
  2. PRC over Tcp:基于Tcp协议来传输数据

对于所传输的数据,可以交由RPC的双⽅来协商定义,但基本都会包括:

  1. 调⽤的是哪个类或接⼝
  2. 调⽤的是哪个⽅法,⽅法名和⽅法参数类型(考虑⽅法重载)
  3. 调⽤⽅法的⼊参

所以,我们其实可以看到RPC的⾃定义性是很⾼的,各个公司内部都可以实现⾃⼰的⼀套RPC框架,⽽ Dubbo就是阿⾥所开源出来的⼀套RPC框架。

其核心部分包含:

  1. 远程通讯:提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型,序列化,以及"请求-响应"模式的信息交换方式,透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何API侵入。
  2. 集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持,可在内网替代F5等硬件负载均衡器,降低成本,减少单点。
  3. 自动发现:基于注册中心目录服务,服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址,并且能够平滑添加或删除服务提供者。

摘自官网
摘自官网

Dubbo 总体架构

Dubbo架构
Dubbo架构

Dubbo 架构中的角色说明:

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

Dubbo 工作的基本流程:

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

Dubbo的六大特点:

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

Dubbo Quick Start

在 Spring Boot 中集成 Dubbo 快速上手 Dubbo。新建三个板块:provider(服务提供者)、consumer(服务消费者)、公共api模块。

编写父工程 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.fih.study</groupId>
    <artifactId>dubbo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>dubbo</name>
    <description>Demo project for Spring Boot</description>

    <modules>
        <module>dubbo-provider</module>
        <module>dubbo-consumer</module>
        <module>dubbo-demo-api</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <!--<spring-boot.version>2.1.13.RELEASE</spring-boot.version>-->
        <dubbo.version>2.7.8</dubbo.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-bom</artifactId>
            <version>${dubbo.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>${dubbo.version}</version>
        </dependency>

        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.5.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.2.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

        </plugins>
    </build>

</project>

编写 api 模块,添加消费者需要使用到的接口:

public interface HelloWorldApi {  
 String sayHello(String name);  
}

编写 provider 模块

1、指定 Dubbo 包扫描路径:

@SpringBootApplication  
@DubboComponentScan(basePackages = "com.fih.study.dubboprovider.provider")  
public class DubboProviderApplication {  
  
 public static void main(String\[\] args) {  
 SpringApplication.run(DubboProviderApplication.class, args);  
    }  
  
}

2、实现 api 接口,指定服务版本供消费者区分版本进行调用

@Slf4j  
@DubboService(version = "1.0.0")  
public class HelloWorldService implements HelloWorldApi {  
  
 private static final String OUT_FMT = "Hello %s";  
  
    @Override  
 public String sayHello(String name) {  
 log.info("sayHello name:{}", name);  
        return String.format(OUT_FMT, name);  
    }  
}

3、编写 provider 的配置文件|指定注册中心,dubbo协议

server.port=9001  
dubbo.application.id=dubo-study-provider  
dubbo.application.name=dubo-study-provider  
dubbo.registry.address=zookeeper://192.168.206.131:2181  
dubbo.registry.protocol=zookeeper  
dubbo.registry.timeout=100000  
  
dubbo.protocol.name=dubbo

编写 Consumer 模块

1、编写主类

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

2、编写 controller

@RestController  
public class HelloController {  
  
 @DubboReference(version = "1.0.0")  
 private HelloWorldApi helloWorldApi;  
  
    @GetMapping("/hello")  
 public String hello(String name) {  
  
 return helloWorldApi.sayHello(name);  
    }  
}

3、编写 consumer 配置文件:指定注册中心、通信协议

server.port=9002  
dubbo.application.id=dubbo-study-consumer  
dubbo.application.name=dubbo-study-consumer  
dubbo.registry.address=zookeeper://192.168.206.131:2181  
dubbo.registry.protocol=zookeeper  
dubbo.registry.timeout=100000  
  
dubbo.protocol.name=dubbo

启动测试:

  1. 请求接口
  2. 查看 Zookeeper:

Q&A

Dubbo 解决了什么问题

很多同学使用Dubbo有很长一段时间,如果被问起为什么要使用Dubbo,解决了什么问题?我们可能会随口而出:通过RPC调用实现应用间解耦,进而实现将复杂应用微服务化; 保证了系统功能的专一性,进而提高代码或者业务功能的复用性; 分布式的架构设计以及智能的负载均衡提升了我们系统的吞吐量,进而提高了性能……没错,是这样的。但是除了这些可能也回答不出来什么了。这里关于Dubbo解决了什么问题做一下整理,在被别人问道的时候心里也清楚,最关键的是为我们在后续的业务选型上可以做出正确的判断。

一开始就提到了单体应用到分布式的演变,那么随着业务的不断扩展,服务规模和架构的不断演进,在大规模服务化之前,应用可能只是通过Java 的 RMI协议 或Hession等工具实现简单地暴露和引用远程服务,通过配置URL地址进行调用,最后通过F5等硬件进行负载均衡。那既然可以实现简单的远程调用,为什么阿里还要投入这么大成本开发Dubbo呢,当然肯定有必要的一些考量,除了我刚刚提到的那点,Dubbo主要解决以下几个问题:

(1) 高性能、透明的RPC调用。
只要涉及服务之间的通信,RPC就必不可。Dubbo可以让我们像调用本地服务一样简单的去调用远程服务,而不需要再代码中显示的指定远程调用。整个过程对上层开发者透明,Dubbo会自动完成后续的所有操作,例如:负载均衡、路由、协议转换、序列化等。开发者只需要接收对应的调用结果。

(2)服务的自动注册与发现。
当服务越来越多时,服务URL配置管理变得非常困难,服务的注册与发现已经不可能由人工来管理。此时需要一个注册中心,动态的注册和发现服务,使服务的位置透明。Dubbo适配了多种注册中心。

(3)自动负载与容错。
当服务越来越多时,F5一年负载均衡器的单点压力也原来越大,Dubbo提供了完整的集群容错机制,可以实现软件层面的负载均衡,依次降低硬件的压力。Dubbo还提供了调用失败的各种容错机制,如Failover、Failfast、结果集合并等。

(4)动态的流量调度。
在应用运行时,某些服务节点可能因为硬件原因需要减少负载或者某些节点需要人工手动下线;又或者需要实现单元化的调用、灰度功能。通过Dubbo Admin管理控制台,用户可以在界面上动态地调整每个服务的权重、路由规则、禁用/启用,实现运行时的流量调度。

(5)依赖分析和调用统计
Dubbo可以介入第三方的APM做分布式链路追踪与性能分析,或者使用已有的独立监控中心的调用次数及耗时,我们可以通过这些数据反推系统容量,在合适的时候通过加机器进行扩容,并且可以预估需要添加多少台机器。

作者:程序员网址导航 链接:https://www.jianshu.com/p/88f622b6d807
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Dubbo 与 SpringCloud 的区别

定位区别

Dubbo 是 SOA(面向服务架构) 时代的产物,它的关注点主要在于服务的调用,流量分发、流量监控和熔断;而Spring Cloud 诞生于微服务架构时代,考虑的是微服务治理的方方面面,另外由于依托Spirng、Spirng Boot 的优势之上,两个框架在开始目标就不一致,Dubbo 定位服务治理、Spirng Cloud 是一个生态。因此可以大胆地判断,Dubbo 未来会在服务治理方面更为出色,而 SpringCloud 在微服务治理上面无人能敌。

技术栈区别

  • Dubbo底层是使用Netty这样的NIO框架,是基于TCP协议传输的,配合以Hession序列化完成RPC通信;
  • 而SpringCloud是基于Http协议+rest接口调用远程过程的通信,相对来说,Http请求会有更大的报文,占的带宽也会更多。但是REST相比RPC更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更为合适,至于注重通信速度还是方便灵活性,具体情况具体考虑。

模块区别

  1. Dubbo主要分为服务注册中心,服务提供者,服务消费者,还有管控中心;

  2. 相比起Dubbo简单的四个模块,SpringCloud则是一个完整的分布式一站式框架,他有着一样的服务注册中心,服务提供者,服务消费者,管控台,断路器,分布式配置服务,消息总线,以及服务追踪等;

整体比较

  1. Dubbo由于是二进制的传输,占用带宽会更少
  2. SpringCloud是Http协议传输,带宽会比较多,同时使用http协议一般会使用JSON报文,消耗会更大
  3. Dubbo的开发难度较大,原因是Dubbo的jar包依赖问题很多大型工程无法解决
  4. SpringCloud的接口协议约定比较自由且松散,需要有强有力的行政措施来限制接口无序升级

Dubbo与SpringCloud的区别 - SegmentFault 思否

Dubbo 和 Nacos 的联系

Apache Dubbo 提供了六大核心能力:面向接口代理的高性能RPC调用,智能容错和负载均衡,服务自动注册和发现,高度可扩展能力,运行期流量调度,可视化的服务治理与运维。

Nacos 致力于帮助您发现、配置和管理微服务,Nacos 支持几乎所有主流类型的“服务”的发现、配置和管理。

dubbo并不包含注册发现,当然可以通过配置到自身配置文件中的方式配置dubbo服务的消费者和提供者,但是这样其实就是写死了调用的地址和端口,导致扩容、缩容、调整部署的服务器等所有依赖的服务都需要调整配置重启。这样就需要一个中心化的服务来存储每个服务的名称和IP端口的对应关系。注册中心就是做这种事情的,Dubbo最早是用的Zookeeper,现在阿里自己写了一个Nacos,所以现在大力推广Nacos。

作者:张小夜 链接:https://www.zhihu.com/question/451932038/answer/1807376143
来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Feign 和 Dubbo 的异同

相同点

  1. Feign 和 Dubbo 都是 rpc 框架简单定义 rpc:可以像调本地接口一样调用远程接口的方式,就是RPC。
  2. Dubbo 与 Feign 都依赖注册中心、负载均衡。

不同点

1、协议

  • Dubbo:

    • 支持多传输协议(Dubbo、Rmi、http、redis等等),可以根据业务场景选择最佳的方式。非常灵活。
    • 默认的Dubbo协议:利用Netty,TCP传输,单一、异步、长连接,适合数据量小、高并发和服务提供者远远少于消费者的场景。
  • Feign:

    • 基于Http传输协议,短连接,不适合高并发的访问。

2、负载均衡

  • Dubbo:
    • 支持4种算法(随机、轮询、活跃度、Hash一致性),而且算法里面引入权重的概念。
    • 配置的形式不仅支持代码配置,还支持Dubbo控制台灵活动态配置。
    • 负载均衡的算法可以精准到某个服务接口的某个方法。
  • Feign:
    • 只支持N种策略:轮询、随机、ResponseTime加权。
    • 负载均衡算法是Client级别的。

3、容错策略

  • Dubbo:
    • 支持多种容错策略:failover、failfast、brodecast、forking等,也引入了retry次数、timeout等配置参数。
  • Feign:
    • 利用熔断机制来实现容错的,处理的方式不一样。

版权声明:本文为CSDN博主「老周聊架构」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/riemann_/article/details/108762693