Dubbo


架构演变

基础知识

性能指标

  • 响应时间:指执行一个请求从开始到最后收到响应数据所花费的总体时间。

  • 并发数:指系统同时能处理的请求数量。

    • 并发连接数:指的是客户端向服务器发起请求,并建立了TCP连接。每秒钟服务器连接的总TCP数量

    • 请求数:也称为QPS(Query Per Second) 指每秒多少请求.

    • 并发用户数:单位时间内有多少用户

  • 吞吐量:指单位时间内系统能处理的请求数量。

    • QPS:Query Per Second 每秒查询数。

    • TPS:Transactions Per Second 每秒事务数。

    • 一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。

架构目标

  • 高性能:提供快速的访问体验。

  • 高可用:网站服务一直可以正常访问。

  • 可伸缩:通过硬件增加/减少,提高/降低处理能力。

  • 高可扩展:系统间耦合低,方便通过新增/移除方式,增加/减少新的功能/模块。

  • 安全性:提供网站安全访问和数据加密,安全存储等策略。

  • 敏捷性:随需应变,快速响应。

相关概念

  • 集群:很多“人”一起 ,干一样的事。

    • 一个业务模块,部署在多台服务器上。
  • 分布式:很多“人”一起,干不一样的事。这些不一样的事,合起来是一件大事。

    • 一个大的业务系统,拆分为小的业务模块,分别部署在不同的机器上。

单体架构

优点:

  • 简单:开发部署都很方便,小型项目首选

缺点:

  • 项目启动慢、可靠性差、可伸缩性差、扩展性和可维护性差、性能低

垂直架构

将单体架构中的多个模块拆分为多个独立的项目。形成多个独立的单体架构。

垂直架构存在的问题:重复功能太多(例如图中 E 功能)

分布式架构

在垂直架构的基础上,将公共业务模块抽取出来,作为独立的服务,供其他调用者消费,以实现服务的共享和重用。

分布式架构存在的问题:服务提供方地址一旦产生变更,所有消费方都需要变更。

SOA架构

SOA:(Service-Oriented Architecture,面向服务的架构)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和契约联系起来。

ESB:(Enterparise Servce Bus) 企业服务总线,服务中介。主要是提供了一个服务于服务之间的交互。ESB 包含的功能如:负载均衡,流量控制,加密处理,服务的监控,异常处理,监控告急等等

微服务架构

微服务架构是在 SOA 上做的升华,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。

微服务架构 = 80%的SOA服务架构思想 + 100%的组件化架构思想 + 80%的领域建模思想

特点:

  • 服务实现组件化:开发者可以自由选择开发技术。也不需要协调其他团队

  • 服务之间交互一般使用REST API

  • 去中心化:每个微服务有自己私有的数据库持久化业务数据

  • 自动化部署:把应用拆分成为一个一个独立的单个服务,方便自动化部署、测试、运维

Dubbo 简介

Apache Dubbo 是一款易用、高性能的 WEB 和 RPC 框架,同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能力、工具与最佳实践。

Dubbo 作为一款微服务框架,最重要的是向用户提供跨进程的 RPC 远程调用能力。如上图所示,Dubbo 的服务消费者(Consumer)通过一系列的工作将请求发送给服务提供者(Provider)。

为了实现这样一个目标,Dubbo 引入了注册中心(Registry)组件,通过注册中心,服务消费者可以感知到服务提供者的连接方式,从而将请求发送给正确的服务提供者。

Dubbo 相关注解注解配置项参考手册

Dubbo 快速入门

参考:3 - Dubbo Spring Boot Starter 开发微服务应用 | Apache Dubbo

1.启动注册中心 ZooKeeper

要启动 ZooKeeper,您需要一个配置文件。这是一个示例,在 conf/zoo 中创建它.cfg:

tickTime=2000
dataDir=/Users/jianjian/JavaSoft/apache-zookeeper-3.8.1-bin/data/
clientPort=2181

启动ZooKeeper:

bin/zkServer.sh start

2.初始化项目

请参考:Dubbo Spring Boot Starter 开发微服务应用-初始化项目

3.添加 Maven 依赖

在初始化完项目以后,我们需要先添加 Dubbo 相关的 maven 依赖。

对于多模块项目,首先需要在父项目的 pom.xml 里面配置依赖信息。

<properties>
        <dubbo.version>3.2.0</dubbo.version>
        <spring-boot.version>2.7.8</spring-boot.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                  <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <!-- Dubbo -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-bom</artifactId>
                <version>${dubbo.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
                <version>${dubbo.version}</version>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

然后在 dubbo-spring-boot-consumerdubbo-spring-boot-provider 两个模块 pom.xml 中进行具体依赖的配置。

编辑 ./dubbo-spring-boot-consumer/pom.xml./dubbo-spring-boot-provider/pom.xml 这两文件,都添加下列配置。

    <dependencies>
        <!-- interface -->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>dubbo-spring-boot-demo-interface</artifactId>
            <version>${project.parent.version}</version>
        </dependency>

        <!-- dubbo -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <artifactId>slf4j-reload4j</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>

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

    </dependencies>

在这份配置中,定义了 dubbo 和 zookeeper(以及对应的连接器 curator)的依赖。

添加了上述的配置以后,可以通过 IDEA 刷新依赖

4.定义服务接口

服务接口沟通消费端和服务端的桥梁。

dubbo-spring-boot-demo-interface 模块的 org.apache.dubbo.springboot.demo 下建立 DemoService 接口,定义如下:

package org.apache.dubbo.springboot.demo;

public interface DemoService {

    String sayHello(String name);
}

DemoService 中,定义了 sayHello 这个方法。后续服务端发布的服务,消费端订阅的服务都是围绕着 DemoService 接口展开的。

5. 定义服务端的实现

定义了服务接口之后,可以在服务端这一侧定义对应的实现,这部分的实现相对于消费端来说是远端的实现,本地没有相关的信息。

dubbo-spring-boot-demo-provider 模块的 org.apache.dubbo.springboot.demo.provider 下建立 DemoServiceImpl 类,定义如下:

package org.apache.dubbo.springboot.demo.provider;

import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.springboot.demo.DemoService;

@DubboService
public class DemoServiceImpl implements DemoService {

    @Override
    public String sayHello(String name) {
        return "Hello " + name;
    }
}

DemoServiceImpl 中,实现了 DemoService 接口,对于 sayHello 方法返回 Hello name

注:在DemoServiceImpl 类中添加了 @DubboService 注解,通过这个配置可以基于 Spring Boot 去发布 Dubbo 服务。

6.配置服务端 YAML 配置文件

从本步骤开始至第 7 步,将会通过 Spring Boot 的方式配置 Dubbo 的一些基础信息。

首先,我们先创建服务端的配置文件。

dubbo-spring-boot-demo-provider 模块的 resources 资源文件夹下建立 application.yml 文件,定义如下:

dubbo:
  application:
    name: dubbo-springboot-demo-provider
  protocol:
    name: dubbo
    port: -1
  registry:
    address: zookeeper://localhost:2181

在这个配置文件中,定义了 Dubbo 的应用名、Dubbo 协议信息、Dubbo 使用的注册中心地址。

7. 配置消费端 YAML 配置文件

同样的,我们需要创建消费端的配置文件。

dubbo-spring-boot-demo-consumer 模块的 resources 资源文件夹下建立 application.yml 文件,定义如下:

dubbo:
  application:
    name: dubbo-springboot-demo-consumer
  protocol:
    name: dubbo
    port: -1
  registry:
    address: zookeeper://localhost:2181 

在这个配置文件中,定义了 Dubbo 的应用名、Dubbo 协议信息、Dubbo 使用的注册中心地址。

8. 基于 Spring 配置服务端启动类

除了配置 Yaml 配置文件之外,我们还需要创建基于 Spring Boot 的启动类。

首先,我们先创建服务端的启动类。

dubbo-spring-boot-demo-provider 模块的 org.apache.dubbo.springboot.demo.provider 下建立 Application 类,定义如下:

package org.apache.dubbo.springboot.demo.provider;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

在这个启动类中,配置了一个 ProviderApplication 去读取我们前面第 6 步中定义的 application.yml 配置文件并启动应用。

9. 基于 Spring 配置消费端启动类

同样的,我们需要创建消费端的启动类。

dubbo-spring-boot-demo-consumer 模块的 org.apache.dubbo.springboot.demo.consumer 下建立 Application 类,定义如下:

package org.apache.dubbo.springboot.demo.consumer;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {

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

在这个启动类中,配置了一个 ConsumerApplication 去读取我们前面第 7 步中定义的 application.yml 配置文件并启动应用。

10. 配置消费端请求任务

除了配置消费端的启动类,我们在 Spring Boot 模式下还可以基于CommandLineRunner去创建

dubbo-spring-boot-demo-consumer 模块的 org.apache.dubbo.springboot.demo.consumer 下建立 Task 类,定义如下:

package org.apache.dubbo.springboot.demo.consumer;

import java.util.Date;

import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.springboot.demo.DemoService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class Task implements CommandLineRunner {
    @DubboReference
    private DemoService demoService;

    @Override
    public void run(String... args) throws Exception {
        String result = demoService.sayHello("world");
        System.out.println("Receive result ======> " + result);

        new Thread(()-> {
            while (true) {
                try {
                    Thread.sleep(1000);
                    System.out.println(new Date() + " Receive result ======> " + demoService.sayHello("world"));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }
}

Task 类中,通过@DubboReference 从 Dubbo 获取了一个 RPC 订阅,这个 demoService 可以像本地调用一样直接调用。在 run方法中创建了一个线程进行调用。

11. 启动应用

截止第 10 步,代码就已经开发完成了,本小节将启动整个项目并进行验证。

首先是启动 org.apache.dubbo.springboot.demo.provider.Application ,等待一会出现如下图所示的日志(Current Spring Boot Application is await)即代表服务提供者启动完毕,标志着该服务提供者可以对外提供服务了。

[Dubbo] Current Spring Boot Application is await...

然后是启动org.apache.dubbo.springboot.demo.consumer.Application ,等待一会出现如下图所示的日志(Hello world )即代表服务消费端启动完毕并调用到服务端成功获取结果。

Receive result ======> Hello world

Dubbo Admin

安装

参考:两种方式安装dubbo-admin、zookeeperM1 Mac下使用Docker安装zookeeper、dubbo-admin

准备工作

参考:docker安装zookeeperDocker安装Zookeeper教程(超详细)

  • 安装 zookeeper
 docker search zookeeper    
 docker pull zookeeper 
 docker images              # 查看下载的本地镜像
 docker inspect zookeeper   # 查看zookeeper详细信息
  • 创建ZooKeeper 挂载目录(数据挂载目录、配置挂载目录和日志挂载目录)
mkdir -p /mydata/zookeeper/data # 数据挂载目录
mkdir -p /mydata/zookeeper/conf # 配置挂载目录
mkdir -p /mydata/zookeeper/logs # 日志挂载目录
  • 启动ZooKeeper容器
docker run -d --name zookeeper --privileged=true -p 2181:2181  -v /mydata/zookeeper/data:/data -v /mydata/zookeeper/conf:/conf -v /mydata/zookeeper/logs:/datalog zookeeper

参数说明

-d  # 表示在一直在后台运行容器
--name # 设置创建的容器名称
-p 2181:2181 # 对端口进行映射,将本地2181端口映射到容器内部的2181端口
-v # 将本地目录(文件)挂载到容器指定目录;
--restart always #始终重新启动zookeeper,看需求设置不设置自启动
  • 查看容器
docker ps
  • 添加ZooKeeper配置文件,在挂载配置文件目录(/mydata/zookeeper/conf)下,新增zoo.cfg 配置文件,配置内容如下:
dataDir=/data   # 保存zookeeper中的数据
clientPort=2181 # 客户端连接端口,通常不做修改
dataLogDir=/datalog
tickTime=2000   # 通信心跳时间
initLimit=5     # LF(leader - follower)初始通信时限
syncLimit=2     # LF 同步通信时限
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
server.1=localhost:2888:3888;2181
  • 启动zk客户端
# 进入zookeeper 容器内部
docker exec -it zookeeper /bin/bash
# 检查容器状态
docker exec -it zookeeper /bin/bash ./bin/zkServer.sh status
# 进入控制台
docker exec -it zookeeper zkCli.sh

docker 安装

  • 拉取镜像
docker search dubbo-admin

docker pull apache/dubbo-admin
  • 创建容器
docker run -d --name dubbo-admin -p 8081:8080 -e admin.registry.address=zookeeper://ip地址:2181 -e admin.config-center=zookeeper://ip地址:2181 -e admin.metadata-report.address=zookeeper://ip地址:2181 --restart=always apache/dubbo-admin
  • 访问dubbo-admin

访问地址: http://ip地址:8081,用户名/密码:root/root

手动安装

两种方式安装dubbo-admin、zookeeper

Dubbo 高级特性

序列化

dubbo 内部已经将序列化和反序列化的过程内部封装了

我们只需要在定义pojo类时实现Serializable接口即可

一般会定义一个公共的pojo模块,让生产者和消费者都依赖该模块。

地址缓存

注册中心挂了,服务是否可以正常访问?

可以,因为dubbo服务消费者在第一次调用时,会将服务提供方地址缓存到消费者本地,以后再调用则不会访问注册中心。

当服务提供者地址发生变化时,注册中心会通知服务消费者。

超时与重试

服务消费者在调用服务提供者的时候发生了阻塞、等待的情形,这个时候,服务消费者会一直等待下去。在某个峰值时刻,大量的请求都在同时请求服务消费者,会造成线程的大量堆积,势必会造成雪崩。

  • dubbo 利用超时机制来解决这个问题,设置一个超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。

  • 使用timeout属性配置超时时间,默认值1000,单位毫秒。

设置了超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。如果出现网络抖动,则这一次请求就会失败。

  • Dubbo 提供重试机制来避免类似问题的发生。

  • 通过 retries 属性来设置重试次数。默认为 2 次。

@DubboService(timeout = 1000, retries = 2)

多版本

灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。

  • dubbo 中使用 version 属性来设置和调用同一个接口的不同版本
@DubboService(version = "v1.0")   // 提供方
@DubboReference(version = "v1.0") // 使用方

负载均衡

Dubbo 提供 4 种负载均衡策略:

  • Random :按权重随机,默认值。按权重设置随机概率。

  • RoundRobin :按权重轮询。

  • LeastActive:最少活跃调用数,相同活跃数的随机。

  • ConsistentHash:一致性 Hash,相同参数的请求总是发到同一提供者。

@DubboService(weight = 100)
@DubboService(weight = 200)
@DubboReference(loadbalance = "random")

集群容错

Dubbo 提供的集群容错模式:

  • Failover Cluster:失败重试。默认值。当出现失败,重试其它服务器 ,默认重试2次,使用 retries 配置。一般用于读操作

  • Failfast Cluster :快速失败,只发起一次调用,失败立即报错。通常用于写操作。

  • Failsafe Cluster :失败安全,出现异常时,直接忽略。返回一个空结果。

  • Failback Cluster :失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

  • Forking Cluster :并行调用多个服务器,只要一个成功即返回。

  • Broadcast Cluster :广播调用所有提供者,逐个调用,任意一台报错则报错。

@DubboReference(cluster = "failover")

服务降级

服务降级方式

  • mock=force:return null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
  • mock=fail:return null 表示消费方对该服务的方法调用在失败后,再返回null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
@DubboReference(mock = "force:return null")

📚参考资料

❤️Sponsor

您的支持是我不断前进的动力,如果您感觉本文对您有所帮助的话,可以考虑打赏一下本文,用以维持本博客的运营费用,拒绝白嫖,从你我做起!🥰🥰🥰

支付宝 微信

文章作者: 简简
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 简简 !
评论
填上邮箱会收到评论回复提醒哦!!!
 上一篇
ZooKeeper ZooKeeper
ZK简介Zookeeper 是 Apache Hadoop 项目下的一个子项目,是一个树形目录服务。Zookeeper 是一个分布式的、开源的分布式应用程序的协调服务。 Zookeeper 提供的主要功能包括:配置管理、分布式锁、集群管理
2023-03-07
下一篇 
可搜索加密:B-SSE方案 可搜索加密:B-SSE方案
论文名称:《Encrypted Keyword Search Mechanism Based on Bitmap Index for Personal Storage Services》 地址:https://ieeexplore.ie
2022-12-12
  目录