Dubbo

目录

什么是Dubbo?

环境要求

Dubbo架构

基于注解的代码实现:

供应者配置

消费者配置

[Dubbo 高级特性](#Dubbo 高级特性)

序列化

地址缓存

超时与重试

多版本

负载均衡(必须有集群的环境)

集群容错

延伸阅读

[1. 消费端是怎么找到服务端的?](#1. 消费端是怎么找到服务端的?)

[2. 消费端是如何发起请求的?](#2. 消费端是如何发起请求的?)


什么是Dubbo?

Dubbo实现多种语言,为所有主流语言提供对等的微服务开发体验

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

在数据面,Dubbo作为一款微服务框架最重要的是向用户提供跨进程的 RPC 远程调用能力,在控制面,作为微服务的抽象控制面,Dubbo由一系列可选的微服务治理组件构成,负责Dubbo集群的服务发现,流量管控,可视化监测等

Dubbo官方推荐使用Zookeeper作为注册中心

环境要求

  • 系统:Windows、Linux、MacOS

  • JDK 8 及以上(推荐使用 JDK17)

  • Git

  • IntelliJ IDEA(可选)

  • Docker (可选)

Dubbo****架构

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

基于注解的代码实现:

首先,必须有一个提供程序的整体配置:

供应者配置

配置:

XML 复制代码
dubbo.application.name=samples-annotation-provider
dubbo.registry.address=zookeeper://121.37.118.193:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.provider.token=true

配置类

java 复制代码
@Configuration
@EnableDubbo(scanBasePackages = "org.apache.dubbo.samples.annotation.impl")
@PropertySource("classpath:/spring/dubbo-provider.properties")
static class ProviderConfiguration {
}

@EnableDubbo将使 Spring 包能够找到任何由 Dubbo 注释注释的内容。org.apache.dubbo.samples.annotation.impl

作为提供程序,接口实现类必须由以下项注释:@DubboService

java 复制代码
@DubboService
public class AnnotatedGreetingService implements GreetingService {

    public String sayHello(String name) {
        System.out.println("greeting service received: " + name);
        return "hello, " + name;
    }

}

消费者配置

消费者的整体配置对提供商来说非常温和:

配置:

dubbo.application.name=samples-annotation-consumer
dubbo.registry.address=zookeeper://121.37.118.193:2181

配置类 :

java 复制代码
@Configuration
@EnableDubbo(scanBasePackages = "org.apache.dubbo.samples.annotation.action")
@PropertySource("classpath:/spring/dubbo-consumer.properties")
@ComponentScan(value = {"org.apache.dubbo.samples.annotation.action"})
static class ConsumerConfiguration {

}

您可以使用注释将提供程序自动连接到使用者:@DubboReference

java 复制代码
@Component("annotatedConsumer")
public class GreetingServiceConsumer {

    @DubboReference
    private GreetingService greetingService;
    
    ...
}

依赖配置:

XML 复制代码
    <properties>
        <source.level>1.8</source.level>
        <target.level>1.8</target.level>
        <dubbo.version>3.2.0</dubbo.version>
        <spring.version>4.3.30.RELEASE</spring.version>
        <junit.version>4.13.1</junit.version>
        <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
        <zookeeper_version>3.8.0</zookeeper_version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-framework-bom</artifactId>
                <version>${spring.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <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>
            <dependency>
                <groupId>org.apache.zookeeper</groupId>
                <artifactId>parent</artifactId>
                <version>${zookeeper_version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
            <type>pom</type>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

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

        <dependency>
            <groupId>com.github.spotbugs</groupId>
            <artifactId>spotbugs-annotations</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>commons-cli</groupId>
            <artifactId>commons-cli</artifactId>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-client</artifactId>
        </dependency>
        <dependency>
            <groupId>jline</groupId>
            <artifactId>jline</artifactId>
        </dependency>
        <dependency>
            <groupId>io.dropwizard.metrics</groupId>
            <artifactId>metrics-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.xerial.snappy</groupId>
            <artifactId>snappy-java</artifactId>
        </dependency>
    </dependencies>

    <profiles>
        <!-- For jdk 11 above JavaEE annotation -->
        <profile>
            <id>javax.annotation</id>
            <activation>
                <jdk>[1.11,)</jdk>
            </activation>
            <dependencies>
                <dependency>
                    <groupId>javax.annotation</groupId>
                    <artifactId>javax.annotation-api</artifactId>
                    <version>1.3.2</version>
                </dependency>
            </dependencies>
        </profile>
    </profiles>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>${source.level}</source>
                    <target>${target.level}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

Dubbo高级特性

序列化

dubbo 内部已经将序列化和反序列化的过程内部封装了,我们只需要在定义pojo类时实现Serializable接口即可,一般会定义一个公共的pojo模块,让生产者和消费者都依赖该模块。

地址缓存

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

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

超时与重试

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

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

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

设置了超时时间,在这个时间段内,无法完成服务访问,则自动断开连接。

如果出现网络抖动,则这一次请求就会失败。

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

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

供应端代码:(建议配置在供应端)

java 复制代码
@Service(timeout = 3000,retries = 2)//当前服务3秒超时,重试2次,一共3次
public class UserServiceImpl implements UserService {

    int i = 1;
    public String sayHello() {
        return "hello dubbo hello!~";
    }


    public User findUserById(int id) {
        System.out.println("服务被调用了:"+i++);
        //查询User对象
        User user = new User(1,"zhangsan","123");
        //数据库查询很慢,查了5秒

        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return user;
    }
}

消费者代码

java 复制代码
@RestController
@RequestMapping("/user")
public class UserController {

    //注入Service
    //@Autowired//本地注入

    /*
        1. 从zookeeper注册中心获取userService的访问url
        2. 进行远程调用RPC
        3. 将结果封装为一个代理对象。给变量赋值

     */

    @Reference(timeout = 1000)//远程注入
    private UserService userService;


    @RequestMapping("/sayHello")
    public String sayHello(){
        return userService.sayHello();
    }

    /**
     * 根据id查询用户信息
     * @param id
     * @return
     */
    int i = 1;
    @RequestMapping("/find")
    public User find(int id){

        new Thread(new Runnable() {
            public void run() {
                while (true){
                    System.out.println(i++);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();


        return userService.findUserById(id);
    }

多版本

灰度发布:当出现新功能时,会让一部分用户先使用新功能,用户反馈没问题时,再将所有用户迁移到新功能。 dubbo 中使用version 属性来设置和调用同一个接口的不同版本

java 复制代码
@Service(version = "v2.0")
public class UserServiceImpl2 implements UserService {
    ...
}
java 复制代码
    @Reference(version = "v2.0")//远程注入
    private UserService userService;

负载均衡(必须有集群的环境)

负载均衡策略(4种) :
• Random :按权重随机,默认值。按 权重设置随机 概率。
2号机的权重概率:200/(100+200+100)

配置如下,分别对应上面三个提供者,100,200,100,启动三个服务

java 复制代码
@Service(weight = 100)
public class UserServiceImpl implements UserService {
    ...
}
java 复制代码
    @Reference(loadbalance = "random")//远程注入
    private UserService userService;

• RoundRobin :按权重轮询。(1,2,3然后发现2的权重最大随后访问2
• LeastActive :最少活跃调用 数, 相同活跃数的 随机。(
• ConsistentHash :一致性 Hash , 相同参数的请求总是发到同一提供者。

集群容错

java 复制代码
    @Reference(cluster = "failover")//远程注入
    private UserService userService;

集群容错模式:
Failover Cluster:失败重试。默认值。当出现失败,重试其它服务器 ,默认重试2次,使用 retries 配置。一般用于读操作
Failfast Cluster :快速失败,只发起一次调用,失败立即报错。通常用于写操作。
Failsafe Cluster :失败安全,出现异常时,直接忽略。返回一个空结果。
Failback Cluster :失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
Forking Cluster :并行调用多个服务器,只要一个成功即返回。
Broadcast Cluster :广播调用所有提供者,逐个调用,任意一台报错则报错

延伸阅读

1. 消费端是怎么找到服务端的?

服务提供者会向注册中心中写入自己的地址,供服务消费者获取。

2. 消费端是如何发起请求的?

在 Dubbo 的调用模型中,起到连接服务消费者和服务提供者的桥梁是接口。

服务提供者通过对指定接口进行实现,服务消费者通过 Dubbo 去订阅这个接口。服务消费者调用接口的过程中 Dubbo 会将请求封装成网络请求,然后发送到服务提供者进行实际的调用。

java 复制代码
// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java

package org.apache.dubbo.samples.api;

public interface GreetingsService {

    String sayHi(String name);

}

服务消费者通过 Dubbo 的 API 可以获取这个 GreetingsService 接口的代理,然后就可以按照普通的接口调用方式进行调用。得益于 Dubbo 的动态代理机制,这一切都像本地调用一样。

java 复制代码
// 1-basic/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java

// 获取订阅到的 Stub
GreetingsService service = reference.get();
// 像普通的 java 接口一样调用
String message = service.sayHi("dubbo");
相关推荐
pk_xz12345628 分钟前
Shell 脚本中变量和字符串的入门介绍
linux·运维·服务器
小珑也要变强31 分钟前
Linux之sed命令详解
linux·运维·服务器
海绵波波10737 分钟前
Webserver(4.3)TCP通信实现
服务器·网络·tcp/ip
九河云2 小时前
AWS账号注册费用详解:新用户是否需要付费?
服务器·云计算·aws
Lary_Rock3 小时前
RK3576 LINUX RKNN SDK 测试
linux·运维·服务器
幺零九零零3 小时前
【计算机网络】TCP协议面试常考(一)
服务器·tcp/ip·计算机网络
云飞云共享云桌面4 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
幺零九零零8 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
free9 小时前
netstat中sendq/recvq用于排查发送端发送数据的问题
服务器
力姆泰克9 小时前
看电动缸是如何提高农机的自动化水平
大数据·运维·服务器·数据库·人工智能·自动化·1024程序员节