7实现分布式服务的容错

容错是一个全面而复杂话题
dubbo提供了部分容错能力支持
专门针对容错的框架:sentinel、Hystrix

服务容错的基本概念

访问失败原因

  • 分布式固有特性
    网络异常
  • 自身服务失败
    bug
  • 服务依赖失败
    雪崩效应 b因a不可用,重试耗尽资源也死掉,其他服务也相应挂掉。

应对策略

  • 超时时间
    服务未能在这个时间内响应,将回复一个失败消息
  • 重试
    降低网络瞬态异常造成通信问题,可以使用重试机制
    可设置重试次数、指数级重试(1,3,5秒重试)

Dubbo中的解决方案

  • 集群容错
    满足冗余条件(多实例),根据容错策略选择实例
  • 服务降级
    服务分级管理,必要时关闭不重要服务,给重要服务节省资源
    伪装与存根

Dubbo集群容错

容错机制

  • Failover
    失败转移 需设置转移上限

  • Failfast
    抛异常返回调用发起服务,考虑性能资源消耗,某些允许失败的场景可使用,节省资源

  • Failsafe
    失败记录日志

  • Failback
    定时重试

  • Forking

  • Broadcast

Dubbo集群容错策略使用方法

1
<dubbo:reference id="userService" check="false" interface="....UserService" 	loadbalance="roundrobin" cluster="failover" retries="2"/>

默认开启

服务降级

  • 本地伪装
    当某服务提供者全部挂掉后,客户端不抛出异常,而是通过Mock数据返回失败
    Mock类在服务消费者端配置(远程服务调用失败)

  • 本地存根
    服务的提供方也有在本地执行部分逻辑的场景(例如原先校验参数),从而间接实现服务容错
    Stub类在服务提供者端配置(还未调用服务)

示例

本地伪装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//服务提供者模拟服务超时失败
public class UserServiceImpl implements UserService {
@Override
public User getUserByUserName(String userName) {
try {
Thread.sleep(5000);//模拟服务端响应超时
} catch (InterruptedException e) {
e.printStackTrace();
}

return new User(...);
}
}

//服务消费者实现和配置Mock类
public class UserServiceMock implements UserService {
@Override
public User getUserByUserName(String userName) {
//降级实现
return new User(1L, "mock_username", "mock_password");
}
}
1
2
<dubbo:reference id="userService" check="false"   
interface="...UserService" mock="....mock.UserServiceMock"/>

问题

Dubbo提供了两种服务降级方案,各有什么特性?

答疑