Dubbo是阿里开源的分布式远程调用方案(RPC),由于网络或服务端不可靠,会导致调用出现一种不确定的中间状态(超时)。为了避免超时导致客户端资源(线程)挂起耗尽,必须设置超时时间。
Provider可以配置的Consumer端主要属性有timeout、retries、loadbalance、actives和cluster。Provider上应尽量多配置些Consumer端的属性,让Provider实现者一开始就思考Provider的服务特点与服务质量。配置之间存在着覆盖,具体规则如下:
1. 方法级配置别优于接口级别,即小Scope优先
2. Consumer端配置优于Provider配置,优于全局配置
3. Dubbo Hard Code的配置值(默认)
根据规则2,纵使消费端配置优于服务端配置,但消费端配置超时时间不能随心所欲,需要根据业务实际情况来设定。如果超时时间设置得太短,复杂业务本来就需要很长时间完成,服务端无法在设定的超时时间内完成业务处理;如果超时时间设置太长,会由于服务端或者网络问题导致客户端资源大量线程挂起。
Dubbo消费端
全局超时配置
1
指定接口以及特定方法超时配置
1
2
3
Dubbo服务端
全局超时配置
1
指定接口以及特定方法超时配置
1
2
3
Dubbo协议超时实现使用了Future模式,主要涉及类DubboInvoker,ResponseFuture, DefaultFuture。
ResponseFuture.get()在请求还未处理完或未到超时前一直是wait状态;响应达到后,设置请求状态,并进行notify唤醒。
public Object get() throws RemotingException {
return get(timeout);
}
public Object get(int timeout) throws RemotingException {
if (timeout <= 0) {
timeout = Constants.DEFAULT_TIMEOUT;
}
if (! isDone()) {
long start = System.currentTimeMillis();
lock.lock();
try {
while (! isDone()) {
done.await(timeout, TimeUnit.MILLISECONDS);
if (isDone() || System.currentTimeMillis() - start > timeout) {
break;
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
if (! isDone()) {
throw new TimeoutException(sent > 0, channel, getTimeoutMessage(false));
}
}
return returnFromResponse();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static void received(Channel channel, Response response) {
try {
DefaultFuture future = FUTURES.remove(response.getId());
if (future != null) {
future.doReceived(response);
} else {
logger.warn("The timeout response finally returned at "
+ (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()))
+ ", response " + response
+ (channel == null ? "" : ", channel: " + channel.getLocalAddress()
+ " -> " + channel.getRemoteAddress()));
}
} finally {
CHANNELS.remove(response.getId());
}
}
private void doReceived(Response res) {
lock.lock();
try {
response = res;
if (done != null) {
done.signal();
}
} finally {
lock.unlock();
}
if (callback != null) {
invokeCallback(callback);
}
}
--------------------- 本文来自 盖世胖胖 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/peerless_hero/article/details/68922880?utm_source=copy