dubbo超時時間的配置問題


問題

線上一個超時時間設置不合理引起的血案

解決方案

 

配置超時時間的時候,有兩個地方,一個是provider提供的超時參數,一個是consumer提供的超時參數
provider的超時時間就是本系統向外提供的facade的請求超時時間,默認1000ms。consumer是指調用外部的系統接口的超時時間,默認1000ms。
provider的超時時間設置主要是為分析日志提供一些系統運行的情況,並不影響實際的調用過程,因為provider接受到一個請求時,會一直把整個處理邏輯走完,並不會管你是否設置了時間,dubbo只會在方法執行完,判斷下

是否超時,如果超時,記一個warn日志。

dubbo的源碼如下:
public class TimeoutFilter implements Filter {

private static final Logger logger = LoggerFactory.getLogger(TimeoutFilter.class);

public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
long start = System.currentTimeMillis();

Result result = invoker.invoke(invocation);//實際的dubbo接口業務處理

long elapsed = System.currentTimeMillis() - start;
if (invoker.getUrl() != null
 && elapsed > invoker.getUrl().getMethodParameter(invocation.getMethodName(),
"timeout", Integer.MAX_VALUE)) {
if (logger.isWarnEnabled()) {
logger.warn("invoke time out. method: " + invocation.getMethodName()
+ "arguments: " + Arrays.toString(invocation.getArguments()) + " , url is "
 + invoker.getUrl() + ", invoke elapsed " + elapsed + " ms.");
}
}
return result;
}

}

 

 

consumer的超時時間就完全不一樣了,當一個請求發出去,當前的請求線程處於鎖等待的阻塞狀態,而這個condition的喚醒條件1、超時,2、接收到provider的返回。

如果此時我們的provider在升級,又假使jenkins的升級腳本配置的是 kill -9(和運維確認過,是通過kill -9的方式關閉tomcat進程),那條件2是滿足不了了,就只能寄希望於條件1即超時。如果此時我們的超時時間設置過大,那整個線程就處於假死狀態,直至消耗完整個超時時間。

條件1、等待結果返回

private final Lock lock = new ReentrantLock();

private final Condition done = lock.newCondition();
done.await(timeout, TimeUnit.MILLISECONDS);

條件2、判斷超時

private static class RemotingInvocationTimeoutScan implements Runnable {

public void run() {
while (true) {
try {
for (DefaultFuture future : FUTURES.values()) {
if (future == null || future.isDone()) {
continue;
}
if (System.currentTimeMillis() - future.getStartTimestamp() > future.getTimeout()) {
// create exception response.
  Response timeoutResponse = new Response(future.getId());
// set timeout status.
  timeoutResponse.setStatus(future.isSent() ? Response.SERVER_TIMEOUT : Response.CLIENT_TIMEOUT);
timeoutResponse.setErrorMessage(future.getTimeoutMessage(true));
// handle response.
  DefaultFuture.received(future.getChannel(), timeoutResponse);
}
}
Thread.sleep(30);
} catch (Throwable e) {
logger.error("Exception when scan the timeout invocation of remoting.", e);
}
}
}
}

綜上:

<dubbo:provider timeout="" >盡量設置下,log4j的日志級別需要warn級別,定期到線上去查看warn的日志(如果系統有監控最好了,比如cat,就有比較直觀的統計信息),實時關注自己的系統調用情況
<dubbo:consumer timeout="" >如果設(盡量設置下,因為默認是1s,考慮的系統的調用鏈,1s並不是一個非常適合我們現在系統的設置),一定要設置一個合理的區間(1-5s),不要太大,不要太大,不要太大!!!
如果provider和consumer都設置了超時時間,dubbo會默認優先使用provider的配置。所以作為服務提供者,應該對自己的服務響應時間有所評估。盡量設置為合理的區間


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM