Dubbo基础(未完待续)

不多BB,开门见山
这是阿里巴巴的官方中文文档:https://dubbo.gitbooks.io/dubbo-user-book/content/preface/background.html

image.png
节点说明
image.png

调用关系说明

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

Dubbo的特性

Dubbo 架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及向未来架构的升级性。

连通性

  • 注册中心负责服务地址的注册与查找,相当于目录服务,Provider和Consumer只在启动时与注册中心交互,注册中心不转发请求,压力较小
  • 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示
  • Provider向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销
  • Consumer向注册中心获取Provider地址列表,并根据负载算法直接调用Provider,同时汇报调用时间到监控中心,此时间包含网络开销
  • 注册中心,Provider,Consumer三者之间均为长连接,监控中心除外
  • 注册中心通过长连接感知Provider的存在,Provider宕机,注册中心将立即推送事件通知Consumer
  • 注册中心和监控中心全部宕机,不影响已运行的Provider和Consumer,Consumer在本地缓存了Provider列表
  • 注册中心和监控中心都是可选的,Consumer可以直连Provider

健状性

  • 监控中心宕掉不影响使用,只是丢失部分采样数据
  • 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
  • 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
  • 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
  • Provider无状态,任意一台宕掉后,不影响使用
  • Provider全部宕掉后,Consumer应用将无法使用,并无限次重连等待Provider恢复

伸缩性

  • 注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心
  • Provider无状态,可动态增加机器部署实例,注册中心将推送新的Provider信息给Consumer

演示:

Spring版本的配置

image.png

Provider

image.png



    
    

    
    

    

    


    
    

    
 
    

    


Consumer




    
    

    
    
    
    

调用

public class ConsumerClient {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-hello-consumer.xml");
        context.start();
        while (true){
            Scanner scanner = new Scanner(System.in);
            String message = scanner.next();
            // 获取接口
            ServiceAPI serviceAPI = (ServiceAPI)context.getBean("consumerService");
            // 测试异步调用
            long beginTime = System.currentTimeMillis();
            serviceAPI.sendMessage(message);
     
        }
    }

}

SpringBoot版本的配置

Provider

image.png
spring:
  application:
    name: dubbo-spring-boot-starter
  dubbo:
    server: true
    registry:
      protocol: zookeeper
      address: 192.168.200.131:2181,192.168.200.130:2181,192.168.200.132:2181

提供的接口

import com.alibaba.dubbo.config.annotation.Service;
@Component
@Service(interfaceClass = ServiceAPI.class)
public class QuickstartServiceImpl implements ServiceAPI {

    @Override
    public String sendMessage(String message) {
        System.out.println(message);
        return "quickstart-provider-message="+message;
    }
}

启动

@SpringBootApplication
@EnableDubboConfiguration
public class PrivoderApplication {

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

Consumer

image.png
spring:
  application:
    name: dubbo-spring-boot-starter
  dubbo:
    server: true
    registry:
      protocol: zookeeper
      address: 192.168.200.131:2181,192.168.200.130:2181,192.168.200.132:2181

调用的接口

@Component
public class QuickstartConsumer {

    @Reference(interfaceClass = ServiceAPI.class)
    ServiceAPI serviceAPI;

    public void sendMessage(String message){
        System.out.println(serviceAPI.sendMessage(message));
    }

}

启动

@SpringBootApplication
@EnableDubboConfiguration
public class ConsumerApplication {

    public static void main(String[] args) {

        ConfigurableApplicationContext run =
                SpringApplication.run(ConsumerApplication.class, args);

        QuickstartConsumer quickstartConsumer = (QuickstartConsumer)run.getBean("quickstartConsumer");

        quickstartConsumer.sendMessage("dubbo是好东私");

    }
}

启动项目就可以看到注册中心相应的节点了

image.png

启动检查check

Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,以便上线时,能及早发现问题,默认 check="true"
可以通过 check="false" 关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动的情况下可以关闭了。

另外,如果你的 Spring 容器是懒加载的,或者通过 API 编程延迟引用服务,请关闭 check,否则服务临时不可用时,会抛出异常,拿到 null 引用,如果 check="false",总是会返回引用,当服务恢复时,能自动连上。
spring


或者是springboot

  @Reference(interfaceClass = ServiceAPI.class,check = false)
    ServiceAPI serviceAPI;

负载均衡策略

在集群负载均衡时,Dubbo 提供了多种均衡策略,默认为 Random 随机调用。

Random

随机,按权重设置随机概率。
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

RoundRobin

轮循,按公约后的权重设置轮循比率。
存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

LeastActive

最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

ConsistentHash

一致性 Hash,相同参数的请求总是发到同一提供者。
当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

配置

配置Spring版的:

Provider


Consumer


Provider


    

Consumer


    

配置SpringBoot版

Consumer

    @Reference(interfaceClass = ServiceAPI.class,loadbalance = "roundrobin")
    ServiceAPI serviceAPI;

协议

Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。

列举几个
Dubbo多协议

SpringBoot版

配置

spring:
  application:
    name: dubbo-spring-boot-starter
  dubbo:
    server: true
    registry:
      protocol: rmi/*协议在这里改*/
      address: 192.168.200.131:2181,192.168.200.130:2181,192.168.200.132:2181

本地存根

远程服务后,客户端通常只是调用一下生产端的接口,而接口实现全都在生产者端,但生产者端有些时候想在客户端也执行部分逻辑,比如:做 ThreadLocal 缓存,提前验证参数,调用失败后服务降级等等,此时就需要在 API 中带上 Stub,客户端生成 Proxy 实例,会把 Proxy 通过构造函数传给 Stub 然后把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。

本地存根需要Stub类的有参构造函数,把Provider端提供的接口传入,本地存根的原理就是强制让Consumer先走Stub类对应的实现接口进行逻辑处理

image.png

演示

Provider

创建Stub类

public class Mystub implements ServiceAPI {

    private ServiceAPI serviceAPI;

    public Mystub(ServiceAPI serviceAPI) {
        this.serviceAPI = serviceAPI;
    }

   @Override
    public String sendMessage(String message) {
        if ("tzb".equals(message)){
            System.out.println("provider的本地存根");
            return this.serviceAPI.sendMessage(message);
        }else {
            System.out.println("符合规则,降级");
            return "符合规则,降级";
        }
    }
}

public class QuickStartServiceImpl implements ServiceAPI {

    @Override
    public String sendMessage(String message) {
        System.out.println("message="+message);
        return "quickstart-provider-message="+message;
    }
}

    

    
    

    
    
    
    

    
    
Consumer

在消费者端需要从生产者端拷贝一份Stub类,然后修改一下逻辑,其他不变

public class Mystub implements ServiceAPI {
    private ServiceAPI serviceAPI;
    public Mystub(ServiceAPI serviceAPI) {
        this.serviceAPI = serviceAPI;
    }
    @Override
    public String sendMessage(String message) {
        if ("tzb".equals(message)){
            System.out.println("这里是Consumer端的本地存根");
            return this.serviceAPI.sendMessage(message);
        }else {
            System.out.println("这里是Consumer端");
            System.out.println("符合规则,降级或者是参数验证");
        }
        return null;
    }
}

我们看到本地存根,虽然是远程调用dubbo的接口,但是先走的是消费者的Stub类,通过Stub类进行一些逻辑处理在调用远程调用dubbo的接口

这里是provider端的输出,并没有走provider端的本地存根方法

本地伪装(服务降级神器)

这个是本地存根的子集,调用这个需要Mock类的空参构造函数,如果Provider的接口出现异常就会走Consumer端的Mock类,本地伪装通常用于服务降级,比如某验权服务,当服务提供方全部挂掉后,客户端不抛出异常,而是通过 Mock 数据返回授权失败。

本地伪装的原理就是在发生Provider的接口发生异常时,强制使Consumer端的走Mock类对应的实现接口,从而达到服务器的降级

本地伪装和本地存根不同的地方就在于,本地存根是会拦截所有的对应接口对应的方法,而本地伪装只是在异常时才去拦截对应接口对应的方法

演示

Provider

mock类(说白了就是服务降级的处理类)

//关于ServiceAPI的服务降级
public class Mymock implements ServiceAPI {
//ServiceAPI类的sendMessage方法异常或者超时就触发服务降级
    @Override
    public String sendMessage(String message) {
        System.out.println("服务降级被触发了");
        return "mock服务降级";
    }

    @Override
    public String sendMessage02(String message) {
        return null;
    }
}

我给被调用的方法设置一个超时,2秒肯定超时了的,看看超时会不会触发降级

public class QuickStartServiceImpl implements ServiceAPI {

    @Override
    public String sendMessage(String message) {
        System.out.println("message="+message);

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "quickstart-provider-message="+message;
    }
........
}

    

    
    

    
    
    
    

    
    
Consumer

在消费者端需要从生产者端拷贝一份Mock类

public class Mymock implements ServiceAPI {
    @Override
    public String sendMessage(String message) {
        System.out.println("这里是Consumer端");
        System.out.println("Provider端出现异常,降级!!!");
        return message;
    }
}
    
    

    
    
    
    

你可能感兴趣的:(Dubbo基础(未完待续))