原创

Dubbo 高可用


一、zookeeper 宕机与 dubbo直连

1. 现象

项目运行一段时间后 zookeeper 注册中心宕机,还可以消费 dubbo 暴露的服务。

2. 原因

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

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

我们可以通过**@Reference** 注解的 url属性设置 消费者直连提供者:

@Service
public class OrderServiceImpl implements OrderService {

    @Reference(url = "127.0.0.1:20880")
    UserService userService;


    @Override
    public List<UserAddress> initOrder(String userId) {
        System.out.println( "用户id : " + userId );
        //查询用户地址
        List<UserAddress> addressList = userService.getUserAddressList( userId );
        return addressList;
    }
}

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

1. 类型

在集群负载均衡时,Dubbo 提供了多种均衡策略。

Random LoadBalance

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

RoundRobin LoadBalance

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

LeastActive LoadBalance

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

ConsistentHash LoadBalance

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

2. 配置

服务端

@Service(loadbalance = "roundrobin")

客户端

@Reference(loadbalance = "roundrobin")

通常我们是使用Dubbo控制台来调节,如下:

三、服务降级

什么是服务降级 ?

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

可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。 向注册中心写入动态配置覆盖规则:

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 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。

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

##四、整合hystrix,服务熔断与降级处理 Hystrix 指在通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备拥有回退机制和断路器功能的线程和信号隔离,请求缓存和请求打包,以及监控和配置等功能,在springcloud基础中,我写过对Hystrix的使用。下面我们使用Dubbo 和 hystrix 整合一下:

服务提供方

1. pom.xml

<!-- Hystrix的依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.0.2.RELEASE</version>
</dependency>

2. 主启动类 UserServiceProviderApplication

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

@EnableHystrix
@EnableDubbo
@SpringBootApplication
public class UserServiceProviderApplication {

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

3. UserServiceImpl

@Service
@Component
public class UserServiceImpl implements UserService{


    //将该方法交给了 Hystrix 代理
    @HystrixCommand
    @Override
    public List<UserAddress> getUserAddressList(String userId) {

        List<UserAddress> list = new ArrayList<>();
        UserAddress address1 = new UserAddress(1 , "上海市杨浦区xxx路xxx号" , "1" , "王某某","0");
        UserAddress address2 = new UserAddress(2 , "上海市徐汇区xxx路xxx号" , "1" , "张某某","1");

        list.add( address1 );
        list.add( address2 );
		
		//构造不定期访问错误
        if(Math.random() > 0.5) {
            throw new RuntimeException();
        }

        return list;
    }
}

服务消费方

1. pom.xml

同服务提供者一样添加 Hystrix 的依赖

2. 主启动类

@EnableHystrix
@EnableDubbo
@SpringBootApplication
public class GmallOrderConsumerApplication {

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

3. OrderServiceImpl

@Service
public class OrderServiceImpl implements OrderService {

    @Reference
    UserService userService;

    @HystrixCommand(fallbackMethod = "hello")
    @Override
    public List<UserAddress> initOrder(String userId) {
        System.out.println( "用户id : " + userId );
        //查询用户地址
        List<UserAddress> addressList = userService.getUserAddressList( userId );
        return addressList;
    }

    public List<UserAddress> hello(String userId) {
        return Arrays.asList( new UserAddress( 3, "出错地址", "1", "出错", "出错" ) );
    }

}

启动提供者和消费者,访问测试如下:

dubbo
  • 作者:程序员果果
  • 发表时间:2018-11-20 15:56
  • 版权声明:自由转载-非商用-非衍生-保持署名 (创意共享4.0许可证)
  • 公众号转载:请在文末添加作者公众号二维码
  • 评论

      微信扫一扫,关注公众号 『 程序员果果 』