dubbo的超时机制、集群容错

阳光穿透心脏的1/2处 2022-02-14 03:31 403阅读 0赞

RPC场景

本文所有问题均以下图做为业务场景,一个web api做为前端请求,product service是产品服务,其中调用comment service(评论服务)获取产品相关评论,comment service从持久层中加载数据。

aHR0cHM6Ly9pbWFnZXMyMDE3LmNuYmxvZ3MuY29tL2Jsb2cvMTcwNzEvMjAxNzA4LzE3MDcxLTIwMTcwODA2MDIxODQ2MzgxLTYxNjU3Nzk3LnBuZw

超时是针对消费端还是服务端?

  • 如果是争对消费端,那么当消费端发起一次请求后,如果在规定时间内未得到服务端的响应则直接返回超时异常,但服务端的代码依然在执行。
  • 如果是争取服务端,那么当消费端发起一次请求后,一直等待服务端的响应,服务端在方法执行到指定时间后如果未执行完,此时返回一个超时异常给到消费端。

dubbo的超时是针对客户端的,由于是一种NIO模式,消费端发起请求后得到一个ResponseFuture,然后消费端一直轮询这个ResponseFuture直至超时或者收到服务端的返回结果。虽然超时了,但仅仅是消费端不再等待服务端的反馈并不代表此时服务端也停止了执行。

超时在哪设置?

消费端

  • 全局控制

  • 接口控制

  • 方法控制

    1. <dubbo:method name="方法名" timeout="1000">

服务端

  • 全局控制

  • 接口控制

  • 方法控制

可以看到dubbo针对超时做了比较精细化的支持,无论是消费端还是服务端,无论是接口级别还是方法级别都有支持。

超时设置的优先级是什么?

上面有提到dubbo支持多种场景下设置超时时间,也说过超时是针对消费端的。那么既然超时是针对消费端,为什么服务端也可以设置超时呢?

这其实是一种策略,其实服务端的超时配置是消费端的缺省配置,即如果服务端设置了超时,任务消费端可以不设置超时时间,简化了配置。

另外针对控制的粒度,dubbo支持了接口级别也支持方法级别,可以根据不同的实际情况精确控制每个方法的超时时间。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0ppblhZYW4_size_16_color_FFFFFF_t_70

  • 上图中以timeout为例,显示了配置的查找(优先级)顺序,其它retries, loadbalance, actives等类似。

    • 方法级优先,接口级次之,全局配置再次之。
    • 如果级别一样,则消费方优先,提供方次之。
  • 其中,服务提供方配置,通过URL经由注册中心传递给消费方。
  • 建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置。

超时的实现原理是什么?

  1. dubbo默认采用了netty做为网络组件,它属于一种NIO的模式。消费端发起远程请求后,线程不会阻塞等待服务端的返回,而是马上得到一个ResponseFuture,消费端通过不断的轮询机制判断结果是否有返回。因为是通过轮询,轮询有个需要特别注要的就是避免死循环,所以为了解决这个问题就引入了超时机制,只在一定时间范围内做轮询,如果超时时间就返回超时异常。

重连机制

  1. dubbo在调用服务不成功时,**默认会重试2次**。Dubbo的路由机制,会把超时的请求路由到其他机器上,而不是本机尝试,所以 dubbo的重试机器也能一定程度的保证服务的质量。
  2. 但是如果不合理的配置重试次数,当失败时会进行重试多次,这样在某个时间点出现性能问题,调用方再连续重复调用,系统请求变为正常值的retries倍,系统压力会大增,容易引起服务雪崩,需要根据业务情况规划好如何进行异常处理,何时进行重试。
  3. <!-- 服务调用超时设置为5秒,超时不重试-->
  4. <dubbo:service interface="com.provider.service.DemoService" ref="demoService" retries="0" timeout="5000"/>

超时与服务降级

  1. 按我们文章之前的场景,web api 请求产品明细时调用product service,为了查询产品评论product service调用comment service。如果此时由于comment service异常,响应时间增大到10S(远大于上游服务设置的超时时间),会发生超时异常,进而导致整个获取产品明细的接口异常,这也就是平常说的强依赖。这类强依赖是超时不能解决的,解决方案一般是两种:
  • 调用comment service时做异常捕获,返回空值或者返回具体的错误码,消费端根据不同的错误码做不同的处理。
  • 调用coment service做服务降级,比如发生异常时返回一个mock的数据,dubbo默认支持mock。

    只有通过做异常捕获或者服务降级才能确保某些不重要的依赖出问题时不影响主服务的稳定性。而超时就可以与服务降级结合起来,当消费端发生超时时自动触发服务降级, 这样即使我们的评论服务一直慢,但不影响获取产品明细的主体功能,只不过会牺牲部分体验,用户看到的评论不是真实的,但评论相对是个边缘功能,相比看不到产品信息要轻的多,某种程度上是可以舍弃的。

Dubbo的集群容错策略

正常情况下,当我们进行系统设计时候,不仅要考虑正常逻辑下代码该如何走,还要考虑异常情况下代码逻辑应该怎么走。当服务消费方调用服务提供方的服务出现错误时候,Dubbo提供了多种容错方案,缺省模式为failover,也就是失败重试。

Dubbo提供的集群容错模式

下面看下Dubbo提供的集群容错模式:

Failover Cluster:失败重试

  1. 当服务消费方调用服务提供者失败后自动切换到其他服务提供者服务器进行重试。这通常用于读操作或者具有幂等的写操作,需要注意的是重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。
  2. 接口级别配置重试次数方法 <dubbo:reference retries="2" /> ,如上配置当服务消费方调用服务失败后,会再重试两次,也就是说最多会做三次调用,这里的配置对该接口的所有方法生效。当然你也可以针对某个方法配置重试次数如下:
  3. <dubbo:reference>
  4. <dubbo:method name="sayHello" retries="2" />
  5. </dubbo:reference>

重试后失败自动切换,重试其它服务器。(缺省)

Failfast Cluster:快速失败

当服务消费方调用服务提供者失败后,立即报错,也就是只调用一次。通常这种模式用于非幂等性的写操作。

Failsafe Cluster:失败安全

当服务消费者调用服务出现异常时,直接忽略异常。这种模式通常用于写入审计日志等操作。

Failback Cluster:失败自动恢复

当服务消费端用服务出现异常后,在后台记录失败的请求,并按照一定的策略后期再进行重试。这种模式通常用于消息通知操作。

Forking Cluster:并行调用

当消费方调用一个接口方法后,Dubbo Client会并行调用多个服务提供者的服务,只要一个成功即返回。这种模式通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks=”2” 来设置最大并行数。

Broadcast Cluster:广播调用

当消费者调用一个接口方法后,Dubbo Client会逐个调用所有服务提供者,任意一台调用异常则这次调用就标志失败。这种模式通常用于通知所有提供者更新缓存或日志等本地资源信息。

如上,Dubbo本身提供了丰富的集群容错模式,但是如果您有定制化需求,可以根据Dubbo提供的扩展接口Cluster进行定制。在后面的消费方启动流程章节会讲解何时/如何使用的集群容错。

参考:https://www.cnblogs.com/ASPNET2008/p/7292472.html

发表评论

表情:
评论列表 (有 0 条评论,403人围观)

还没有评论,来说两句吧...

相关阅读

    相关 dubbo容错

    为了避免单点故障,现在的应用通常至少会部署在两台服务器上。对于一些负载比较高的服务,会部署更多的服务器。这样, 在同一环境下的服务提供者数量会大于1。对于服务消费者来说,同一环

    相关 谈谈dubbo容错

    从继承图可以看出有以下几种策略: Failover Cluster(失败转移) 当调用提供者的服务器发生错误时,再试下一个服务器。 用于读操作。重试有延时。设置重试次数

    相关 Dubbo容错

    Dubbo官网:[dubbo 2.7  集群容错][dubbo 2.7_] 集群容错指的是,当消费者调用提供者集群时发生异常的处理方案 一、Dubbo内置的容错策略

    相关 Dubbo-容错

    当一个项目(应用或服务)放在多台服务器上时,怎么实现高可用,这就是集群容错。 \------------------------------------------

    相关 Dubbo——容错

    Cluster层概述 在微服务环境中,为了保证服务的高可用,很少会有单点服务出现,服务通常都是以集群的形式出现的。然而,被调用的远程服务并不是每时每刻都保持良好状况,当某