在dubbo中,可以设置服务的超时时间,服务端和消费端可以分别设置,但是服务消费端在调用的时候,会根据timeout配置的优先级,去获取阈值,消费端的配置高于消费端的,那这篇笔记主要记录的是服务消费端超时的原理,或者说,是服务调用方是如何判断服务调用时间超过了设置的阈值
结论
1.首先服务调用方,会根据配置优先级,获取一个超时时间(消费端配置 > 服务提供端配置 接口层面 > 应用层面配置)
2.然后会把超时时间一直进行透传,通过invocation对象
3.然后在调用端通过netty发送了请求之后,会通过Condition.await()来等待指定的时间
3.1 如果休眠指定的时间之后,调用执行完毕,就返回
3.2 如果依旧没有拿到返回信息,就抛出timeout异常
所以:我认为,简单而已,dubbo的超时机制,就是通过condition同步条件队列来完成的
源码阅读
在发起一笔调用的时候,调用链是这样的
com.alibaba.dubbo.rpc.protocol.AbstractInvoker#invoke
com.alibaba.dubbo.rpc.protocol.dubbo.DubboInvoker#doInvoke
调用链是上面这个,就是服务消费端在调用的时候,会通过netty进行服务调用,netty客户端会在服务引入的时候,提前创建好,所以在dubboInvoker的doInvoke()方法中,会直接根据url去集合中取出来一个client,发起请求
protected Result doInvoke(final Invocation invocation) throws Throwable {
RpcInvocation inv = (RpcInvocation) invocation;
final String methodName = RpcUtils.getMethodName(invocation);
inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
inv.setAttachment(Constants.VERSION_KEY, version);
// 这里是获取一个netty服务端,通过exchangeClient去发起netty请求调用
ExchangeClient currentClient;
if (clients.length == 1) {
currentClient = clients[0];
} else {
currentClient = clients[index.getAndIncrement() % clients.length];
}
try {
boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
/**
* 在发起调用时,获取超时时间的源码
* 1.先取方法上的配置,如果方法上未配置
* 2.接着取接口上的配置
* 3.如果接口上也未配置,那就取默认的配置
*
* 总之,这里的timeout是根据优先级过滤之后,得到的超时时间
*/
int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
/**
* 1.如果是单路的,就无需异步或者同步,在调用之后,直接return即可
* 2.如果是异步调用,就通过future获取到返回结果
* 3.如果是同步调用,就等待返回结果
*/
if