Dubbo快速入门学习(二)

Dubbo集群容错:

1)服务路由

服务路由包含一条路由规则,路由规则决定了服务消费者的调用目标,即规定了服务消费者可调用哪些服务提供者

dubbo提供三种服务路由实现,分别为: (条件路由ConditionRouter、脚本路由ScriptRouter、标签路由TagRouter

 

本章重点分析条件路由

条件路由规则的格式: 

[服务消费者匹配条件] => [服务提供者匹配条件] 
host = 10.20.153.10 => host = 10.20.153.11

 

该条规则表示 IP 为 10.20.153.10 的服务消费者只可调用 IP 为 10.20.153.11 机器上的服务,不可调用其他机器上的服务。

如果服务消费者匹配条件为空,表示不对服务消费者进行限制。

如果服务提供者匹配条件为空,表示对某些服务消费者禁用服务。

 

常见路由配置:

白名单:

host != 10.20.153.10,10.20.153.11 =>

 意思:端口号不是10.20.153.10,10.20.153.11)的不可以访问

黑名单:

host = 10.20.153.10,10.20.153.11 =>

 意思:端口号(10.20.153.10,10.20.153.11)的不可以访问

读写分离:

 

method = fifind,list,get,is  => host = 172.22.3.94,172.22.3.95,172.22.3.96

 

  意思:方法fifind , list , get , is)的访问ip为(172.22.3.94,172.22.3.95,172.22.3.96)的服务端

method != fifind,list,get,is => host = 172.22.3.97,172.22.3.98

  意思:方法不是(fifind , list , get , is)的访问ip为(172.22.3.94,172.22.3.95,172.22.3.96)的服务端

前后台分离:

 

application =  front => host = 172.22.3.91,172.22.3.92,172.22.3.93

 

  意思:应用(front【前端】)的访问ip为(172.22.3.91,172.22.3.92,172.22.3.93)的服务端

application != front => host = 172.22.3.94,172.22.3.95,172.22.3.96

  意思:应用不是(front【前端】)的访问ip为(172.22.3.91,172.22.3.92,172.22.3.93)的服务端

 

2)集群容错

  • Failover Cluster    失败自动切换,当出现失败,重试其它服务器。(缺省) 通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。

  重试次数配置如下:

<dubbo:service retries="2" />

  或

<dubbo:reference retries="2" />

 

  • Failfast Cluster      快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
  • Failsafe Cluster     失败安全,出现异常时,直接忽略。通常用于写入日志等操作。
  • Failback Cluster    失败自动恢复,后台记录失败请求,定时重发。 通常用于消息通知操作。
  • Forking Cluster     并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks="2"来设置最大并行数。
  • Broadcast Cluster 广播调用所有提供者,逐个调用,任意一台报错则报错。 通常用于通知所有提供者更新缓存或日志等本地资源信息。

 

3)负载均衡

负载均衡: 在集群负载均衡时,Dubbo提供多种均衡策略,缺省random随机调用

  •   Random LoadBalance:           按照权重设置随机概率,无状态
  •   RoundRobin LoadBalance:     轮询,有状态
  •   LeastActive LoadBalance:      最少活跃数随机,方法维度的统计服务调用数
  •   ConsistentHash LoadBalance:一致性Hash 

 

 

 


 

服务治理

 

1)服务降级

  可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略
  可以向注册中心写入动态配置覆盖规则
RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtensi on();

Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181")); 

registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService? 
            category=configurators&dynamic=false&application=foo&mock=force:return+null" ));

 

mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
 
还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
 
dubbo配置服务降级方式
在dubbo-admin中配置 

 

2)整合hystrix

A) springboot官方提供了对hystrix的集成,直接在pom.xml里加入依赖

<dependency> 
  <groupId>org.springframework.cloud</groupId> 
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> 
  <version>1.4.4.RELEASE</version>
</dependency>

B) Application启动类中新增@EnableHystrix来启用hystrix starter

C) provider增加@HystrixCommand

D) Consumer method上配置@HystrixCommand(fallbackMethod= methodName)) 


 

 

dubbo线程IO模型 

 

BIO

每个客户端连接过来后,服务端都会启动一个线程去处理该客户端的请求。在传统的IO模型中,每个连接创建成功之后都需要一个线程来维护。 
阻塞I/O的通信模型示意图如下

 

 

NIO

NIO,也叫做new-IO或者non-blocking-IO,可理解为非阻塞IO。NIO编程模型中,新来一个连接不再
创建一个新的线程,而是可以把这条连接直接绑定到某个固定的线程,然后这条连接所有的读写都由这个线程来负责
 
 
 

我们用一幅图来对比一下IO与NIO: 

 

如上图所示
 
IO模型中,一个连接都会创建一个线程,对应一个while死循环,死循环的目的就是不断
监测这条连接上是否有数据可以读。但是在大多数情况下,1万个连接里面同一时刻只有少量的连接有
数据可读,因此,很多个while死循环都白白浪费掉了,因为没有数据。
 
而在NIO模型中,可以把这么多的while死循环变成一个while死循环,这个死循环由一个线程控制。这就是
NIO模型中选择器(Selector)的作用,一条连接来了之后,现在不创建一个while死循环去监听是否有
数据可读了,而是直接把这条连接注册到选择器上,通过检查这个选择器,就可以批量监测出有数据可
读的连接,进而读取数据

举个栗子:

  在一家餐厅里,客人有点菜的需求,一共有100桌客人,有两种方案可以解决客人点菜的问题:
 
方案一:
  每桌客人配一个服务生,每个服务生就在餐桌旁给客人提供服务。如果客人要点菜,服务生就可以立刻提供点菜的服务。
  那么100桌客人就需要100个服务生提供服务,这就是IO模型,一个连接对应一个线程。
方案二:
  一个餐厅只有一个服务生(假设服务生可以忙的过来)。这个服务生隔段时间就询问所有的客人是否需要点菜,
  然后每一时刻处理所有客人的点菜要求。这就是NIO模型,所有客人都注册到同一个服务生,对应的就是所有的连接都注册到一个线程,然后批量轮询。
 
这就是NIO模型解决线程资源受限的方案,实际开发过程中,我们会开多个线程,每个线程都管理着一批连接,相对于IO模型中一个线程管理一条连接,消耗的线程资源大幅减少。

 

SPI

SPI 全称为 Service Provider Interface,是一种服务发现机制。SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类。

这样可以在运行时,动态为接口替换实现类。正因此特性,我们可以很容易的通过 SPI 机制为我们的程序提供拓展功能。SPI 机制在第三方框架中也有所应用,

比如 Dubbo 就是通过 SPI 机制加载所有的组件。不过,Dubbo 并未使用 Java 原生的SPI 机制,而是对其进行了增强,使其能够更好的满足需求。

在 Dubbo 中,SPI 是一个非常重要的模块。

 

1)JAVA原生SPI机制

 

a)新建一个接口Czbk和两个实现类Czxy、Itheima

包结构图:

 

 

 代码:

package com.itheima.service;
public interface Czbk {
    void service();
}
//-----------------------------------------
package com.itheima.service.impl;
import com.itheima.service.Czbk;
public class Czxy implements Czbk {
    public void service() {
        System.out.println("kerrykerrykerry");
    }
}
//-----------------------------------------
package com.itheima.service.impl;
import com.itheima.service.Czbk;
public class Itheima implements Czbk {
    public void service() {
        System.out.println("carrycarrycarry");
    }
}
b)配置映射文件
在resources中新建/META-INF/services目录,在新建的目录中新建文件,注意文件名必须是接口
的全类名,此处为Czbk的接口全路径,文件内容为接口实现类的全类名,每一个实现类占一行 
包结构图:

 

 

代码:

com.itheima.service.impl.Czxy
com.itheima.service.impl.Itheima

 

c)新建测试类SpiTest,主方法测试 
package com.itheima.test;
import com.itheima.service.Czbk;
import java.util.Iterator;
import java.util.ServiceLoader;
public class SpiTest {
    public static void main(String[] args) {
        ServiceLoader<Czbk> serviceLoader = ServiceLoader.load(Czbk.class);
        Iterator<Czbk> iterator = serviceLoader.iterator();
        while (iterator.hasNext()){
            Czbk czbkImpl = iterator.next();
            czbkImpl.service();
        }
    }
}

运行结果:

 

 

 

 


配置的优先级

方法级优先,接口级次之,全局配置再次之。
如果级别一样,则消费方优先,提供方次之。
其中,服务提供方配置,通过 URL 经由注册中心传递给消费方

 

 

Redis作为注册中心时调用过程

1.服务提供方启动时,向 Key:/dubbo/XXXServer/providers 下,添加当前提供者的地址
2.并向 Channel:/dubbo/com.wow.DemoService/providers 发送 register 事件
3.服务消费方启动时,从 Channel:/dubbo/com.wow.DemoService/providers 订阅 register 和 unregister 事件
4.并向 Key:/dubbo/com.wow.DemoService/providers 下,添加当前消费者的地址
5.服务消费方收到 register 和 unregister 事件后,从 Key:/dubbo/com.wow.DemoService/providers 下获取提供者地址列表

 

zookeeper作为注册中心调用过程

1.服务提供者启动时: 向 /dubbo/com.wow.DemoService/providers 目录下写入自己的 URL 地址
2. 服务消费者启动时: 订阅 /dubbo/com.wow.DemoService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.wow.DemoService/consumers 目录下写入自己的 URL 地址
3.监控中心启动时: 订阅 /dubbo/com.wow.DemoService 目录下的所有提供者和消费者 URL 地址

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
posted @ 2021-04-21 11:12  _kerry  阅读(100)  评论(0编辑  收藏  举报