Dubbo快速上手

基本使用

添加依赖

    <artifactId>dubbo</artifactId>
    <packaging>pom</packaging>
    <modules>
        <module>provider</module>
        <module>consumer</module>
    </modules>
    
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <dubbo.version>3.0.6</dubbo.version>
    </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>

            <!-- Apache 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</artifactId>
                <version>${dubbo.version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>javax.servlet</groupId>
                        <artifactId>servlet-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
        </dependency>

        <!-- 此pom适用于以前的版本,现在已经包含在 dubbo-dependencies-zookeeper
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>5.2.1</version>
        </dependency>-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>${dubbo.version}</version>
            <type>pom</type>
            <exclusions>
                <!-- apache zookeeper 默认使用了 slf4j 门面的 log4j 实现。排除后就没有配置文件的警告⚠️-->
                <exclusion>
                    <artifactId>log4j</artifactId>
                    <groupId>log4j</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>slf4j-log4j12</artifactId>
                    <groupId>org.slf4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <!-- 要么使用zk,要么使用nacos,二选一
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
        </dependency>-->

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

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

添加配置

server:
  port: 8086 # 生产/消费端的port需不同
spring:
  application:
    name: consumer # 生产/消费端的name需不同
dubbo:
  application:
    name: ${spring.application.name}
  registry:
    protocol: zookeeper
    address: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
#    address: nacos://127.0.0.1:8848
#    注册中心是否检查
#    check: false
  scan:
    base-packages: com.howeres.service
  protocol: # 这里使用了dubbo协议
    name: dubbo
    port: 20882 # 生产/消费端的通讯port需不同
  consumer:
#    全局消费者默认是否检查
    check: false
    retries: 3

使用注解

  • 提供端
@DubboService(methods = {@Method(name = "getInfo", timeout = 3000)},version = "1.0.0")
public class MessageServiceImpl implements MessageService {
    @Override
    public String getInfo(String info) {
        try { TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) { e.printStackTrace();}
        return info + "已经抵达上车点";
    }
}
  • 消费端
@Service
public class DriverServiceImpl implements DriverService {

    /**
     * dubbo的注册中心宕机了依然能连,是因为本地还有缓存。
     *
     * <p>没有注册中心也能调用服务:dubbo直连,reference使用url参数 (ip+port);
     *
     * <p>检查单独检查是否连接:check,也可以设置参数{@code dubbo.consumer.check=false}
     *
     * <p>版本:version,灰度发布通配符:*;*不能与dubbo直连一起使用。因为dubbo直连绕过了注册中心,所以无法对版本进行负载均衡,也就无法使用通配符
     *
     * <p>本地存根:stub,全限定名+全参构造器
     *
     * <p>重试次数:retries,方法级、service级都行
     */
    @DubboReference(
            methods = @Method(name = "getInfo", timeout = 3000, retries = 3),
            // url = "127.0.0.1:20881", // dubbo 直连不能搭配版本通配符 *
            check = false,
            version = "*",
            stub = "com.howeres.service.impl.MessageServiceStub")
    MessageService messageService;

    public String pickUp(String info) {
        return messageService.getInfo(info);
    }
}
  • 消费端本地存根
public class MessageServiceStub implements MessageService {

    private final MessageService messageService;

    public MessageServiceStub(MessageService messageService) {
        this.messageService = messageService;
    }

    @Override
    public String getInfo(String info) {
        if (info == null) {
            return null;
        }
        return messageService.getInfo(info);
    }
}

基本配置

  • dubbo的注册中心宕机了依然能连,是因为本地还有缓存。
  • 没有注册中心也能调用服务:dubbo直连,reference使用url参数 (ip+port);
  • 检查单独检查是否连接:check,也可以设置参数dubbo.consumer.check=false
  • 版本:version,灰度发布通配符:*;*不能与dubbo直连一起使用。推测是因为直连是精确到某一个服务,而多版本适合多个微服务,所以必须指定版本
  • 本地存根:stub,全限定名+全参构造器
  • 超时时间:timeout,官方推荐放在提供端。因为多个消费端同时消费时,实际执行时间只有提供端知道。
  • 重试次数:retries,方法级、service级都行

高可用

使用负载均衡

推荐放在消费端:

@DubboReference(loadbalance = LeastActiveLoadBalance.NAME)
MessageService messageService;

总共有5种:

  1. RandomLoadBalance 基于权重的随机负载均衡机制
  2. RoundRobinLoadBalance 轮询
  3. LeastActiveLoadBalance 最少活跃数
  4. ShortestResponseLoadBalance
  5. ConsistentHashLoadBalance 一致性hash(方法名和参数都一致,老熟人方式)

两种降级(底层是zk):

  1. 直接降级:mock=force:return+null直接返回为null值,不发起远程调用。用来屏蔽(block)不重要服务不可用时对调用端的影响,在消费端手动屏蔽提供者。

  2. 失败降级:mock=fail:return+null调用失败后返回null值,不抛异常。用来屏蔽不重要服务不稳定时对调用端的影响,设置容错。(不容错的情况下,超时会有一个控制台类型的页面报错)

集群容错模式:默认是:failover Cluster;

failover Cluster:失败自动切换,当出现失败,重试其他服务器;
failfast Cluster:适合新增等非幂等的写操作;
failsafe Cluster:适合日志写入操作,出现异常直接忽略;
failback Cluster:适合一定要成功的操作,失败记录下来,隔一段时间重试一次;
forking Cluster:并行调用,一个成功即返回,适合实时性要求高的读操作。比较浪费资源;
broadcast Cluster:广播调用,一台报错就报错。适合同步更新缓存或日志等本地资源信息;

容错结合Hystrix

  1. spring-cloud-starter-netflix-hystrix maven依赖引入
  2. @EnableHystrix
  3. 提供端@HystrixCommand,让目标方法被hystrix代理
  4. 消费端@HystrixCommand(fallbackMethod=“methodName”)

dubbo实现(netty)

nio:相比于bio(blocking)使用Socket单开线程然后阻塞,nio用了channel,使用buffer传输,多路复用selector

启动

  1. 标签解析:BeanDefinitionParser#parse 标签解析挨个解析配置文件里面的《标签名+Config》或者通过scan.base-package下声明注解的类以及对应接口进行加载。

  2. 服务暴露:ServiceBean「initializingBean+ApplicationListener」解析过程中ServiceBean做了:容器创建完操作+监听ContextRefreshedEvent操作(触发ContextRefreshEvent时,执行export()暴露服务)。注册中心等信息不仅全局保存了,每个暴露的服务也进行了保存。暴露协议doExportUrls->doExportUrlsFor1Protocol代理工厂暴露接口,协议包含dubbo协议和registry注册中心的协议。最后dubbo协议以及端口底层是用netty提供的接口进行绑定。最后将这些暴露的信息放到注册中心。ProviderConsumerRegTable 注册表类中两个并发hashmap,存了<url, Set对应的执行器们> 方便以后调用。

  3. 服务引用:ReferenceBean「FactoryBean」调用getObject方法,ReferenceConfig,ProxyFactory根据map(里面包含信息)创建代理ref=createProxy(map),返回一个invoker代理封装远程的调用信息

  4. 服务调用:消费端实际调用的是封装的代理,MockClusterInvoker接口FailoverClusterInvoker对象,选择负载均衡对象。在这里插入图片描述

Reference

dubbo官网:https://dubbo.apache.org/en/docs/v2.7/dev/design/

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值