1、Dubbo体系结构
2、Dubbo容错机制
Dubbo集群容错架构图
各节点关系:
- 这里的Invoker是Provider的一个可调用Service的抽象,Invoker封装了Provider地址及Service接口信息。
- Directory代表多个Invoker,可以把它看成List,但与List不同的是,它的值可能是动态变化的,比如注册中心推送变更。
- Cluster将Directory中的多个Invoker伪装成一个Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。
- Router负责从多个Invoker中按路由规则选出子集,比如读写分离,应用隔离等。
- LoadBalance负责从多个Invoker中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选。
2.1 集群容错模式
Failover Cluster
- 失败自动切换,当出现失败,重试其它服务器。(缺省)
- 通常用于读操作,但重试会带来更长延迟。
- 可通过retries="2"来设置重试次数(不含第一次)。
Failfast Cluster
- 快速失败,只发起一次调用,失败立即报错。
- 通常用于非幂等性的写操作,比如新增记录。
Failsafe Cluster
- 失败安全,出现异常时,直接忽略。
- 通常用于写入审计日志等操作。
Failback Cluster
- 失败自动恢复,后台记录失败请求,定时重发。
- 通常用于消息通知操作。
Forking Cluster
- 并行调用多个服务器,只要一个成功即返回。
- 通常用于实时性要求较高的读操作,但需要浪费更多服务资源。
- 可通过forks="2"来设置最大并行数。
Broadcast Cluster
- 广播调用所有提供者,逐个调用,任意一台报错则报错。(2.1.0开始支持)
- 通常用于通知所有提供者更新缓存或日志等本地资源信息。
<dubbo:service retries="2" />
<dubbo:reference retries="2" />
<!-- 单一方法配置重试次数 -->
<dubbo:reference><dubbo:method name="findFoo" retries="2" />
</dubbo:reference><!-- 配置集群容错模式 -->
<dubbo:service cluster="failsafe" />
<dubbo:reference cluster="failsafe" />
3、Dubbo服务降级
综述:
Dubbo服务降级主要包含两点:屏蔽(mock=force,Dubbo-admin配置)和容错(mock=fail,Mock)。
使用Dubbo时,可能会遇到以下问题:
1)多个服务之间可能由于服务没有启动或者网络不通,调用中会出现远程调用失败;
- 服务请求过大,需要停止部分服务以保证核心业务的正常运行;
mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回 null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
以上两个问题可以使用Dubbo的服务降级来实现;
即:在服务宕掉或者并发数太高导致的RpcException异常时,进行友好的处理或者提示,而不是内部报错导致系统不可用。
查看dubbo的官方文档,可以发现有个mock的配置,mock只在出现非业务异常(比如超时,网络异常等)时执行。mock的配置支持两种,一种为boolean值,默认的为false。如果配置为true,则缺省使用mock类名,即类名+Mock后缀;另外一种则是配置返回默认字符串,如:”return null”或者"return 123456",可以很简单的忽略掉异常。
/**接口定义*/
public interface IUser {public void addUser(User u);public User getUserById(int id);}/**实现类*/
public class UserImpl implements IUser {private static List<User> USER_LIST = new ArrayList<User>();static{for(int i=0;i<10;i++){User u = new User();u.setAddress("address"+i);u.setId(i);u.setName("name"+i);USER_LIST.add(u);}}public void addUser(User u) {USER_LIST.add(u);System.out.println("total:"+USER_LIST.size());}public User getUserById(int id) {for(int i=0;i<USER_LIST.size();i++){if(USER_LIST.get(i).getId() == id){return USER_LIST.get(i);}}return null;}
}public class IUserMock implements IUser {@Overridepublic void addUser(User u) {throw new RuntimeException("add user fail!");}@Overridepublic User getUserById(int id) {return null;}
}
<dubbo:reference id="iUser" interface="com.dubbosample.iface.IUser" timeout="10000" check="false" mock="true"><dubbo:reference id="iUser" interface="com.dubbosample.iface.IUser" timeout="10000" check="false" mock="return null">
以上配置还可以在dubbo-admin界面中配置
分别是屏蔽和容错:
其中屏蔽只能在dubbo-admin中配置,不能在dubbo配置文件里配置
屏蔽:force.mock (即:屏蔽请求,直接返回某个值,如上面的字符串,mock=“return 123456”);
容错:fail.mock (即:允许请求,在请求失败的时候,再返回某个值,如:mock=“fail:return 123456”);
4、Dubbo服务限流
Dubbo限流主要依赖Sentinel(哨兵)中间件一起使用
服务提供端限流:
对服务提供方的限流可分为服务提供方的自我保护能力和服务提供方对服务消费方的请求分配能力这两个维度。
QPS & 定向限流
服务消费端限流:
对服务提供方的限流可分为对控制并发线程数,和服务降级两个维度。
详见:
https://yq.aliyun.com/articles/624053?utm_content=m_1000013383
拓展:
https://blog.csdn.net/world_snow/article/details/79080314
5、Dubbo负载均衡
dubbo有四种负载均衡的方式:
1)RandomLoadBalance:加权随机算法(默认)
2)LeastActiveLoadBalance:最小活跃负载均衡
3)ConsistentHashLoadBalance:一致性hash负载均衡
4)RoundRobinLoadBalance:加权轮询负载均衡
6、Dubbo结果缓存
https://dubbo.apache.org/zh-cn/docs/user/quick-start.html