Dubbo简单入门到实战

88 阅读6分钟

互联网的发展过程中,在以前只需要一个服务器,程序的前后端一起打包就可以了,但是随着流量的增加,常规的垂直应用架构也无法应对了,分布式服务架构势在必行,需要一个治理系统架构的方案。

随着服务化的进一步发展,服务越来越多,服务之间的调用和依赖关系也越来越复杂,诞生了面向服务的架构体系(SOA),也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架。就这样为分布式系统的服务治理框架就出现了,Dubbo 也就这样产生了。

什么是Dubbo

Dubbo官网:dubbo.incubator.apache.org/zh/

Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了 Java、Golang 等多语言 SDK 实现。使用 Dubbo 开发的微服务原生具备相互之间的远程地址发现与通信能力, 利用 Dubbo 提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。Dubbo 被设计为高度可扩展,用户可以方便的实现流量拦截、选址的各种定制逻辑。

Dubbo架构

主要组件

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

调用流程

  1. 服务容器负责启动,加载,运行服务提供者。

  2. 服务提供者在启动时,向注册中心注册自己提供的服务。

  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。

  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用。

  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

注册中心

注册中心是Dubbo核心组件之一。 Dubbo通过注册中心实现了分布式环境中各服务之间的注册与发现, 是各个分布式节点之间的纽带。

Dubbo可以使用多种注册中心,比如redis、zookeeper、eureka、nacos等,但注册中心又该如何选择呢?

官方推荐使用zookeeper注册中心。 个人意见,zookeeper在大数据计算时做注册中心是一个好的选择,但是在服务调用时,也许数据不需要超强的一致性。nacos是目前来说很友好的一个注册中心,他提供了CP+AP。还有可视化界面,还有配置中心等功能,功能相当完善。


到此,一些同学心里也可能和一样,心里还存在一些问题?

Spring Cloud 和 Dubbo 是什么关系,又有什么区别呢?

初始定位不同:SpringCloud定位为微服务架构下的一站式解决方案;Dubbo 是 SOA 时代的产物,它的关注点主要在于服务的调用和治理。

生态环境不同:SpringCloud依托于Spring平台,具备更加完善的生态体系;而Dubbo一开始只是做RPC远程调用,生态相对匮乏,现在逐渐丰富起来。

调用方式:SpringCloud是采用Http协议做远程调用,接口一般是Rest风格,比较灵活;Dubbo是采用Dubbo协议,接口一般是Java的Service接口,格式固定。但调用时采用Netty的NIO方式,性能较好。

组件差异:例如SpringCloud注册中心一般用Eureka,而Dubbo用的是Zookeeper。

作为远程调用,Dubbo 和 Feign 有什么差异呢?

Feign是SpringCloud中的远程调用方式,基于成熟Http协议,所有接口都采用Rest风格。因此接口规范更统一,而且只要符合规范,实现接口的微服务可以采用任意语言或技术开发。但受限于http协议本身的特点,请求和响应格式臃肿,其通信效率相对会差一些。

Dubbo框架默认采用Dubbo自定义通信协议,与Http协议一样底层都是TCP通信。但是Dubbo协议自定义了Java数据序列化和反序列化方式、数据传输格式,因此Dubbo在数据传输性能上会比Http协议要好一些。

Dubbo实战

下面基于Naocs注册中心集成Dubbo实现RPC调用。

环境

  • spring-boot:2.3.7.RELEASE
  • spring-cloud:Hoxton.SR10
  • spring-cloud-alibaba:2.2.5.RELEASE
  • dubbo:2.7.8

工程搭建

  • 公共接口工程 nacos-dubbo-api
  • 服务发布工程 nacos-dubbo-provider
  • 服务消费工程 nacos-dubbo-provider

父级工程搭建

pom引入spring-cloud、spring-cloud-alibaba。

   <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.5.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--  此依赖是为了解决java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils 错误-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
    </dependencies>

公共接口工程

创建接口

public interface ApiService {
    String test();
}

服务发布工程

pom引入nacos、dubbo

        <dependency>
            <groupId>com.syun</groupId>
            <artifactId>nacos-dubbo-api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>

nacos配置文件bootstrap.yml

spring:
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: 7e98b650-0c03-4663-b747-b3d4848630aa
        group: DEFAULT_GROUP

application.yml配置文件

server:
  port: 9001
  servlet:
    context-path: /provider
spring:
  application:
    name: nacos-dubbo-provider

#dubbo配置
dubbo:
  application:
    id: nacos-dubbo-provider
    name: nacos-dubbo-provider
  protocol:
    port: -1
    name: dubbo # 协议
  registry:
    address: nacos://localhost:8848
      # 配置namespace
    parameters[namespace]: 7e98b650-0c03-4663-b747-b3d4848630aa
  scan:
    base-packages: com.syun.nacos.dubbo
  • dubbo.scan.base-packages: 指定,提供服务的接口的包
  • dubbo.protocol.name: Dubbo 为协议名称
  • dubbo.protocol.port: -1 表示自增端口,从 20880 开始
  • dubbo.registry.address: 注册中心地址

服务实现类

import org.apache.dubbo.config.annotation.DubboService;
import syun.nacos.dubbo.service.ApiService;

@DubboService(version = "1.0.0",group = "test1")
public class ApiServiceImpl implements ApiService {
    @Override
    public String test() {
        return "hello";
    }
}

启动类

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

服务消费工程

pom.xml 与 bootstrap.yml 同服务生产工程

application.yml配置文件,和服务生产工程有一个地方不同,去掉dubbo.scan.base-packages。增加dubbo.cloud.subscribed-services(注册到nacos的服务名称)。

server:
  port: 9002
  servlet:
    context-path: /consumer
spring:
  application:
    name: nacos-dubbo-consumer

#dubbo配置
dubbo:
  application:
    id: nacos-dubbo-consumer
    name: nacos-dubbo-consumer
  protocol:
    port: -1
    name: dubbo
  registry:
    address: nacos://localhost:8848
    #设置订阅的服务
  cloud:
    subscribed-services: nacos-dubbo-provider

消费者实现类

import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import syun.nacos.dubbo.service.ApiService;

@RestController
public class TestController {

    @DubboReference(version = "1.0.0",group = "test1")
    ApiService apiService;

    @GetMapping("/test")
    public String hello() {
        return apiService.test();
    }
}

先后启动服务生产工程、服务消费工程,最后应在nacos-server看到provider和consumer的名称。

测试接口:http://localhost:9002/consumer/test

工程Gitee地址:gitee.com/renxiaoshi/…