Apache Dubbo的高级应用


日常学习中,我们只是了解了Apache Dubbo作为RPC通信框架的使用方法,以及服务注册中心的应用及原理,这仅仅是它的冰山一角。其实,Apache Dubbo更像一个生态,它提供了很多比较主流框架的集成,比如:

1、支持多种协议的服务发布,默认是dubbo:/,还可以支持rest://、webservice://、thrift://等。·支持多种不同的注册中心,如Nacos、ZooKeeper、Redis,未来还将会支持Consul、Eureka、Etcd等。

2、支持多种序列化技术,如avro、fst、fastjson、hessian2,kryo等

除此之外,Apache Dubbo在服务治理方面的功能非常完善,比如集群容错、服务路由、负载均衡、服务降级、服务限流、服务监控、安全验证等。

(一)集群容错

在分布式架构的网络通信中,容错能力是必须要具备的。什么叫容错呢?从字面来看,就是服务容忍错误的能力。我们都知道网络通信中会存在很多不确定的因素导致请求失败,比如网络延迟、网络中断、服务异常等。当服务调用者(消费者)调用服务提供者的接口时,如果因为上述原因出现请求失败,那对于服务调用者来说,需要一种机制来应对。Dubbo中提供了集群容错的机制来优雅地处理这种错误。

(1)容错模式
Dubbo默认提供了6种容错模式,默认为Failover Cluster。如果这6种容错模式不能满足你的实际需求,还可以自行扩展。这也是Dubbo的强大之处,几乎所有的功能都提供了插拔式的扩展。

【Failover Cluster】:失败自动切换。当服务调用失败后,会切换到集群中的其他机器进行重试,默认重试次数为2,通过属性retries=2可以修改次数,但是重试次数增加会带来更长的响应延迟。这种容错模式通常用于读操作,因为事务型操作会带来数据重复问题。

【Failfast Cluster】:快速失败。当服务调用失败后,立即报错,也就是只发起一次调用。通常用于一些幂等的写操作,比如新增数据,因为当服务调用失败时,很可能这个请求已经在服务器端处理成功,只是因为网络延迟导致响应失败,为了避免在结果不确定的情况下导致数据重复插入的问题,可以使用这种容错机制。

【Failsafe Cluster】:失败安全。也就是出现异常时,直接忽略异常。

【 Failback Cluster】:失败后自动回复。服务调用出现异常时,在后台记录这条失败的请求定时重发。这种模式适合用于消息通知操作,保证这个请求一定发送成功。

【Forking Cluster】:并行调用集群中的多个服务,只要其中一个成功就返回。可以通过forks=2来设置最大并行数。

【Broadcast Cluster】:广播调用所有的服务提供者,任意一个服务报错则表示服务调用失败。这种机制通常用于通知所有的服务提供者更新缓存或者本地资源信息。

配置方式
配置方式非常简单,只需要在指定服务的@Service注解上增加一个参数即可。注意,在没有特殊说明的情况下,后续代码都是基于前面的Dubbo Spring Cloud的代码进行改造的。在@Service注解中增加cluster=
"failfast"参数,表示当前服务的容错方式为快速失败。

在实际应用中,查询语句容错策略建议使用默认的Failover Cluster,而增删改操作建议使用Failfast Cluster或者使用Failover Cluster ( retries=“O”)策略,防止出现数据重复添加等其他问题!建议在设计接口的时候把查询接口方法单独做成一个接口提供查询。

(二)负载均衡

负载均衡应该不是一个陌生的概念,在访问量较大的情况下,我们会通过水平扩容的方式增加多个节点来平衡请求的流量,从而提升服务的整体性能。简单来说,如果一个服务节点的TPS是100,那么如果增加到5个节点的集群,意味着整个集群的TPS可以达到500。

当服务调用者面对5个节点组成的服务提供方集群时,请求应该分发到集群中的哪个节点,取决于负载均衡算法,通过该算法可以让每个服务器节点获得适合自己处理能力的负载。负载均衡可以分为硬件负载均衡和软件负载均衡,硬件负载均衡比较常见的就是F5,软件负载均衡目前比较主流的是Nginx。

在Dubbo中提供了4种负载均衡策略,默认负载均衡策略是random。同样,如果这4种策略不能满足实际需求,我们可以基于Dubbo中的SPI机制来扩展。

【Random LoadBalance】:随机算法。可以针对性能较好的服务器设置较大的权重值,权重值越大,随机的概率也会越大。
【RoundRobin LoadBalance】:轮询。按照公约后的权重设置轮询比例。
【LeastActive LoadBalance】:最少活跃调用书。处理较慢的节点将会收到更少的请求。
【ConsistentHash LoadBalance】:一致性Hash。相同参数的请求总是发送到同一个服务提供者。

配置方式
在@Service注解上增加loadbalance参数:
@Service(cluster = “failfast”, loadbalance =“roundrobin”)

(三)服务降级

服务降级是一种系统保护策略,当服务器访问压力较大时,可以根据当前业务情况对不重要的服务进行降级,以保证核心服务的正常运行。所谓的降级,就是把一些非必要的功能在流量较大的时间段暂时关闭,比如在双11大促时,淘宝会把查看历史订单、商品评论等功能关闭,从而释放更多的资源来保障大部分用户能够正常完成交易。

【降级有多个层面的分类】:
1、按照是否自动化可分为自动降级和人工降级。
2、按照功能可分为读服务降级和写服务降级。

人工降级一般具有一定的前置性,比如在电商大促之前,暂时关闭某些非核心服务,如评价、推荐等。而自动降级更多的来自于系统出现某些异常的时候自动触发“兜底的流畅”,比如:

【故障降级】:调用的远程服务“挂了”,网络故障或者RPC服务返回异常。这类情况在业务允许的情况下可以通过设置兜底数据响应给客户端。

【限流降级】:不管是什么类型的系统,它所支撑的流量是有限的,为了保护系统不被压垮,在系统中会针对核心业务进行限流。当请求流量达到阈值时,后续的请求会被拦截,这类请求可以进入排队系统,比如12306。也可以直接返回降级页面,比如返回“活动太火爆,请稍候再来”页面。

Dubbo提供了一种Mock配置来实现服务降级,也就是说当服务提供方出现网络异常无法访问时,客户端不抛出异常,而是通过降级配置返回兜底数据,操作步骤如下:

在spring-cloud-dubbo-consumer项目中创建MockHelloService类,这个类只需要实现自动降级的接口即可,然后重写接口中的抽象方法实现本地数据的返回。

(四)主机绑定规则

主机绑定表示的是Dubbo服务对外发布的IP地址,默认情况下Dubbo会按照以下顺序来查找并绑定主机IP地址:

1、查找环境变量中DUBBO_IP_TO_BIND属性配置的IP地址。
2、查找dubbo.protocol.host属性配置的IP地址,默认是空,如果没有配置或者IP地址不合法,则继续往下查找。
3、通过LocalHost.getHostAddress获取本机IP地址,如果获取失败,则继续往下查找
4、如果配置了注册中心的地址,则使用Socket通信连接到注册中心的地址后,使用for循环通过socket.getLocalAddress ( ) .getHostAddress ()扫描各个网卡获取网卡IP地址。

上述过程中,任意一个步骤检测到合法的IP地址,便会将其返回作为对外暴露的服务IP地址。需要注意的是,获取的IP地址并不是写入注册中心的地址,默认情况下,写入注册中心的IP地址优先选择环境变量中DUBBO_IP_TO_REGISTRY属性配置的IP地址。在这个属性没有配置的情况下,才会选取前面获得的IP地址并写入注册中心。

使用默认的主机绑定规则,可能会存在获取的IP地址不正确的情况,导致服务消费者与注册中心上拿到的URL地址进行通信。因为Dubbo检测本地IP地址的策略是先调用LocalHost.getHostAddress,这个方法的原理是通过获取本机的hostname映射IP地址,如果它指向的是一个错误的IP地址,那么这个错误的地址将会作为服务发布的地址注册到ZooKeeper节点上,虽然Dubbo服务能够正常启动,但是服务消费者却无法正常调用。按照Dubbo中IP地址的查找规则,如果遇到这种情况,可以使用很多种方式来解决:

1、在/etc/hosts中配置机器名对应正确的IP地址映射。
2、在环境变量中添加DUBBO_IP_TO_BIND或者DUBBO_IP_TO_REGISTRY属性,Value值为绑定的主机地址。
3、通过dubbo.protocol.host设置主机地址。
除获取绑定主机IP地址外,对外发布的端口也是需要注意的,Dubbo框架中针对不同的协议都提供了默认的端口号:
4、Dubbo协议的默认端口号是20880。. Webservice协议的默认端口号是80。

在实际使用过程中,建议指定一个端口号,避免和其他Dubbo服务的端口产生冲突。

猜你喜欢

转载自blog.csdn.net/Octopus21/article/details/114271738