dubbo超時的深思

在dubbo的provider和consumer的配置文件中,如果都配置了timeout的超時時間,dubbo默認以consumer中配置的時間爲準

provider.xml的配置:

<dubbo:service timeout="4000" retries="0" interface="com.dingding.tms.bms.service.BillingZfbCodOrderService" ref="billingZfbCodOrderService" registry="globalRegistry"/>

conusmer中的配置:

<dubbo:reference id="billingInterService" interface="com.dingding.tms.bms.service.BillingInterService" protocol="dubbo" check="false" registry="globalRegistry" timeout="3000"/>


最後這個service在調用時的超時時間就是3秒

另外,

1,consumer會在超過3秒時得到一個調用超時的異常。

2,provider中代碼的執行不會因爲超時而中斷,在執行完畢後,會得到一個dubbo的警告。

在Provider上儘量多配置Consumer端屬性
原因如下:

  1. 作服務的提供者,比服務使用方更清楚服務性能參數,如調用的超時時間,合理的重試次數,等等

  2. 在Provider配置後,Consumer不配置則會使用Provider的配置值,即Provider配置可以作爲Consumer的缺省值。否則,Consumer會使用Consumer端的全局設置,這對於Provider不可控的,並且往往是不合理的

  3. PS: 配置的覆蓋規則:1) 方法級配置別優於接口級別,即小Scope優先 2) Consumer端配置 優於 Provider配置 優於 全局配置,最後是Dubbo Hard Code的配置值(見配置文檔)

比如:
<dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService"
    timeout="300" retry="2" loadbalance="random" actives="0"/>
 
< dubbo:service interface="com.alibaba.hello.api.WorldService" version="1.0.0" ref="helloService"
    timeout="300" retry="2" loadbalance="random" actives="0" >
    <dubbo:method name="findAllPerson" timeout="10000" retries="9" loadbalance="leastactive" actives="5" />
< dubbo:service/>


在Provider可以配置的Consumer端屬性有:

  1. timeout,方法調用超時

  2. retries,失敗重試次數,缺省是2(表示加上第一次調用,會調用3次)

  3. loadbalance,負載均衡算法(有多個Provider時,如何挑選Provider調用),缺省是隨機(random)。還可以有輪訓(roundrobin)、最不活躍優先(leastactive,指從Consumer端併發調用最好的Provider,可以減少的反應慢的Provider的調用,因爲反應更容易累積併發的調用)

  4. actives,消費者端,最大併發調用限制,即當Consumer對一個服務的併發調用到上限後,新調用會Wait直到超時。在方法上配置(dubbo:method )則併發限制針對方法,在接口上配置(dubbo:service),則併發限制針對服務。


Provider上配置合理的Provider端屬性
比如:


<dubbo:protocol threads="200" />
< dubbo:service interface="com.alibaba.hello.api.HelloService" version="1.0.0" ref="helloService"
    executes="200" >
    <dubbo:method name="findAllPerson" executes="50" />
< /dubbo:service>


Provider上可以配置的Provider端屬性有:

  1. threads,服務線程池大小

  2. executes,一個服務提供者並行執行請求上限,即當Provider對一個服務的併發調用到上限後,新調用會Wait(Consumer可能到超時)。在方法上配置(dubbo:method )則併發限制針對方法,在接口上配置(dubbo:service),則併發限制針對服務。

以上爲網上的定義,在實際使用中當服務的消費方調用服務的提供方超時時,會拋出如下異常:

Caused by: com.alibaba.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer. start time: 2016-07-20 16:27:34.873, end time: 2016-07-20 16:27:39.895, client elapsed: 0 ms, server elapsed: 5022 ms, timeout: 5000 ms, request: Request [id=438870, version=2.0.0, twoway=true, event=false, broken=false, data=RpcInvocation [methodName=querySeatByCode, parameterTypes=[class java.lang.String, class java.lang.String], arguments=[99925788, A1], attachments={input=356, path=com.dfire.soa.turtle.service.ISeatService, interface=com.dfire.soa.turtle.service.ISeatService, timeout=5000, version=1.0.0H5_pressuretest}]], channel: /10.1.5.128:34443 -> /10.1.5.172:20880

網上通常的解決辦法是調大超時時間,但是也可能是因爲代碼本身有潛在問題而造成dubbo超時。

比如:在dubbo消費方,調用了dubbo的提供方,此時事務是分部的,但如果自己的service方法中會用到一張表並去做update操作導致產生了行鎖時,如果恰巧你又在之後調用了另一個會操作此表的dubbo服務,那麼問題就產生了,你會在調dubbo服務的時候發生如上的超時異常,就是因爲用spring aop聲明式事務,在你service沒有執行完時產生的行鎖並沒有釋放,而你又在service裏放入了需要操作此表的dubbo服務,這樣當數據庫的死鎖還沒有拋異常的時候,dubbo就已經拋異常了,因此這個超時異常其實坑很深。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章