Day172.dubbo配置&高可用性 -Dubbo

Dubbo

一、dubbo配置

1、配置覆盖策略

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rjGqLc2V-1611398396284)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123140108678.png)]

JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。

XML 次之,如果在 XML 中有配置,则 dubbo.properties 中的相应配置项无效。

Properties 最后,相当于缺省值,只有 XML 没有配置时,dubbo.properties 的相应配置项才会生效,通常用于共享公共配置,比如应用名。


2、启动检查

消费者每次启动都会自动检查注册中心中他订阅的方法

spring 配置文件

关闭某个服务的启动时检查 (没有提供者时报错):

<dubbo:reference interface="com.foo.BarService" check="false" />

关闭所有服务的启动时检查 (没有提供者时报错):

<!--配置当前消费者的统一规则,所有的服务都不检查,-->
<dubbo:consumer check="false" />

关闭注册中心启动时检查 (注册订阅失败时报错):

<dubbo:registry check="false" />

dubbo.properties

dubbo.reference.com.foo.BarService.check=false
dubbo.reference.check=false
dubbo.consumer.check=false
dubbo.registry.check=false

配置的含义

dubbo.reference.check=false,强制改变所有 reference 的 check 值,就算配置中有声明,也会被覆盖。

dubbo.consumer.check=false,是设置 check 的缺省值,如果配置中有显式的声明,如:<dubbo:reference check="true"/>,不会受影响。

dubbo.registry.check=false,前面两个都是指订阅成功,但提供者列表是否为空是否报错,如果注册订阅失败时,也允许启动,需使用此选项,将在后台定时重试。


3、超时时间

由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。

1)、Dubbo消费端

全局超时配置
<dubbo:consumer timeout="5000" />

指定接口以及特定方法超时配置
<dubbo:reference interface="com.foo.BarService" timeout="2000">
    <dubbo:method name="sayHello" timeout="3000" />
</dubbo:reference>

2)、Dubbo服务端

全局超时配置
<dubbo:provider timeout="5000" />

指定接口以及特定方法超时配置
<dubbo:provider interface="com.foo.BarService" timeout="2000">
    <dubbo:method name="sayHello" timeout="3000" />
</dubbo:provider>


4、配置原则

配置的覆盖规则

1、精确优先(方法级优先,接口级次之,全局配置再次之)

2、消费者设置优先(如果级别一样,则消费方优先,提供方次之)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8UNaLaS1-1611398396287)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123143921417.png)]


5、重试次数

失败自动切换,当出现失败,重试其它服务器,但重试会带来更长延迟。可通过 retries=“2” 来设置重试次数(不含第一次,也就是说设置为3,则会有4次)。

操作类型

  • 幂等操作:设置重试次数【查询、更新、删除】

  • 非幂等操作:不能设置重试次数【新增】

重试次数配置如下:
<dubbo:service retries="2" /><dubbo:reference retries="2" /><dubbo:reference>
    <dubbo:method name="findFoo" retries="2" />
</dubbo:reference>

6、版本号

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。

可以按照以下的步骤进行版本迁移:

在低压力时间段,先升级一半提供者为新版本

再将所有消费者升级为新版本

然后将剩下的一半提供者升级为新版本

【老】版本服务 【提供者】 配置:
<dubbo:service interface="com.foo.BarService" version="1.0.0" />

【新】版本服务 【提供者】 配置:
<dubbo:service interface="com.foo.BarService" version="2.0.0" />
【老】版本服务 【消费者】 配置:
<dubbo:reference id="barService" interface="com.foo.BarService" version="1.0.0" />

【新】版本服务 【消费者】 配置:
<dubbo:reference id="barService" interface="com.foo.BarService" version="2.0.0" />

如果【不需要区分版本】,可以按照以下的方式配置:
<dubbo:reference id="barService" interface="com.foo.BarService" version="*" />

7、本地存根

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vBZrS5Y3-1611398396290)(http://dubbo.apache.org/imgs/user/stub.jpg)]

在 interface 旁边放一个 Stub 实现,它实现 UserService 接口,并有一个传入远程 UserService 实例的构造函数

<dubbo:service interface="com.achang.gmall.service.UserService" stub="com.achang.gmall.service.UserServiceStub" />

提供 Stub 的实现:【有点过滤器拦截器的味道,先判断是否合法,再去调用】

Stub实例里 必须有可传入 Proxy 的构造函数。【oo】

public class UserServiceStub implements UserService{
    
    
    private final UserService userService;
    //传入的是userService的远程代理对象
    // 构造函数传入真正的远程代理对象【oo】
    public UserServiceStub(UserService userService) {
    
    
        this.userService = userService;
    }
    public List<UserAddress> getUserAddressList(String userId) {
    
    
        System.out.println("UserServiceStub...............");
        // 此代码在客户端执行, 你可以在客户端做ThreadLocal本地缓存,或预先验证参数是否合法,等等
        if (StringUtils.isEmpty(userId)){
    
    
            return userService.getUserAddressList(userId);
        }
        return null;
    }

}

8、SpringBoot整合

上面在<dubbo:service中配置的属性,都可以如下在@Service注解()配置

<dubbo:service interface="com.foo.BarService" version="1.0.0" />

配置timeout属性

@Service(timeout = ) //暴露服务
public class UserServiceImpl implements UserService {
    
    }

SpringBoot与dubbo整合的三种方式

1)、导入dubbo-starter,在application.proterties配置文件中配置,

—使用@Service注解【暴露服务】、使用@Reference注解【引用服务】

—要在application.proterties中配置dubbo.scan.base-packages=告诉其上面注解的位置

2)、保留dubbo,xml配置文件的方式:

—导入dubbo-starter

—通过使用@ImportResource(locations=“classpath:XXXX.xml”),来导入之前原始的xml配置文件

3)、使用注解API方式:

—将每一个组件手动创建到容器中,让dubbo来扫描其他的自己

在这里插入图片描述

写一个配置类,来手动创建到容器中,对比上面和下面的写法

@Configuration
public class MyDubboConfig {
    
    

    @Bean
    public ApplicationConfig applicationConfig(){
    
    
        ApplicationConfig config = new ApplicationConfig();
        config.setName("boot-user-service-provider");
        return config;
    }

    @Bean
    public RegistryConfig registryConfig(){
    
    
        RegistryConfig config = new RegistryConfig();
        config.setAddress("localhost:2181");
        config.setProtocol("zookeeper");

        return config;
    }

    @Bean
    public ProtocolConfig protocolConfig(){
    
    
        ProtocolConfig config = new ProtocolConfig();
        config.setName("dubbo");
        config.setPort(20880);

        return config;
    }

    @Bean
    public MonitorConfig monitorConfig(){
    
    
        MonitorConfig config = new MonitorConfig();
        config.setProtocol("registry");

        return config;
    }

}

并在主启动类上标注@EnableDubbo(scanBasePackages=com.achang.gamll)指定dubbo接口的扫描路径中的@Service暴露的服务位置


二、高可用

1、zookeeper宕机与dubbo直连

现象:zookeeper注册中心宕机,还可以消费dubbo暴露的服务。

原因:

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

高可用:通过设计,减少系统不能提供服务的时间;

也可以通过dubbo直连的方式:

通过@Reference(url =)来指定提供者的ip地址:端口

@Reference(url = "localhost:20882")
UserService userService;

2、集群下dubbo负载均衡配置

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yEECsDMo-1611398396294)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123164635368.png)]

负载均衡策略

  • Random LoadBalance

—>基于权重的随机负载均衡机制【默认】

随机,按权重设置随机概率。

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iTVAyfSZ-1611398396297)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123164611160.png)]

  • RoundRobin LoadBalance

—>基于权重的轮询负载均衡机制

轮循,按公约后的权重设置轮循比率。

存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rQjwCEfn-1611398396298)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123164617352.png)]

  • LeastActive LoadBalance

—>最少活跃数-负载均衡机制

最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。

使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XEqBMSeA-1611398396300)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123164622769.png)]

  • ConsistentHash LoadBalance

—> 一致性hash-负载均衡机制

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

当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。算法参见:http://en.wikipedia.org/wiki/Consistent_hashing

缺省只对第一个参数 Hash,如果要修改,请配置

 <dubbo:parameter key="hash.arguments" value="0,1" />

缺省用 160 份虚拟节点,如果要修改,请配置

<dubbo:parameter key="hash.nodes" value="320" />

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-seBos5T3-1611398396302)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123164630327.png)]

  • 设定引用注册中心时,使用什么负载机制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7L0jbOYU-1611398396304)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123170243788.png)]

  • 通过dubbo页面来快速设置 提供者 权重

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yV578S0g-1611398396308)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123170954952.png)]


3、整合hystrix,服务熔断与降级处理

1)、服务降级

什么是服务降级?

当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理或换种简单的方式处理,从而释放服务器资源以保证核心交易正常运作或高效运作。

可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。

向注册中心写入动态配置覆盖规则:

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
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 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IbTVZp3z-1611398396311)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123173641907.png)]

  • 还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fXKDZ0rr-1611398396312)(C:\Users\PePe\AppData\Roaming\Typora\typora-user-images\image-20210123173704792.png)]

2)、集群容错

在集群调用失败时,Dubbo 提供了多种容错方案,缺省为 failover 重试。

集群容错模式

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

重试次数配置如下:
<dubbo:service retries="2" /><dubbo:reference retries="2" /><dubbo:reference>
    <dubbo:method name="findFoo" retries="2" />
</dubbo:reference>

Failfast Cluster
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

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

Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。

Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错 [2]。通常用于通知所有提供者更新缓存或日志等本地资源信息。

集群模式配置
按照以下示例在服务提供方和消费方配置集群模式
<dubbo:service cluster="failsafe" /><dubbo:reference cluster="failsafe" />

3)、整合hystrix

Hystrix 旨在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能

1、配置spring-cloud-starter-netflix-hystrix

spring boot官方提供了对hystrix的集成,直接在pom.xml里加入依赖:

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

然后在主Application配置启动类上增加@EnableHystrix来启用hystrix starter:

@SpringBootApplication
@EnableHystrix //启用hystrix starter
public class ProviderApplication {
    
    }

2、配置Provider端

在Dubbo的Provider上增加@HystrixCommand配置,fallbackMethod指明如果调用出错就会调用hello方法

@Component
@Service() //暴露服务
public class UserServiceImpl implements UserService {
    
    

    @HystrixCommand(fallbackMethod = "hello")
    public List<UserAddress> getUserAddressList(String userId) {
    
    
        UserAddress userAddress1 = new UserAddress(1, "温州市1楼", "1", "郑老师", "112233445566", "Y");
        UserAddress userAddress2 = new UserAddress(2, "温州市2楼", "2", "昌老师", "778899665544", "Y");

        if (Math.random()>0.5){
    
    
            throw new RuntimeException();
        }

        return Arrays.asList(userAddress1,userAddress2);
    }
    
    public String hello(String name) {
    
    
    return "hystrix fallback value";
}

}

3、配置Consumer端

@Service
public class OrderServiceImpl implements OrderService {
    
    
    @Reference
    UserService userService;

    public List<UserAddress> initOrder(String userId) {
    
    
            //1、查询用户收货地址
            System.out.println("用户id:"+userId);
            List<UserAddress> userAddressList = userService.getUserAddressList(userId);

            return userAddressList;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43284469/article/details/113060079