王欣的博客

王欣的博客

马上订阅 王欣的博客 RSS 更新: https://wangxin.io/atom.xml

Dubbo代码分析—超时和重试设计

2019年2月11日 18:01

dubbo提供在provider和consumer端,都提供了超时(timeout)和重试(retries)的参数配置。

一、Dubbo协议中的超时机制

​ 超时机制是dubbo中的一个很重要的机制。在“快速失败”设计中,能将客户端断掉,防止服务端资源耗尽而被压挂。

​ 我们先看一下Dubbo协议中的超时机制是怎么实现的。

​ 超时的实现原理是什么?

我们先回顾一下dubbo的大致流程图。

在生产过程中都是客户端向服务端发送请求,在流程4。

​ 我们可以看到:4的流程是: 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

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

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

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

​ 超时的实现原理是什么?

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

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//ResponseFuture接口定义

public interface ResponseFuture {

/**
* get result.
*
* @return result.
*/
Object get() throws RemotingException;

/**
* get result with the specified timeout.
*
* @param timeoutInMillis timeout.
* @return result.
*/
Object get(int timeoutInMillis) throws RemotingException;

/**
* set callback.
*
* @param callback
*/
void setCallback(ResponseCallback callback);

/**
* check is done.
*
* @return done or not.
*/
boolean isDone();
}


//ReponseFuture的实现类:DefaultFuture
//只看它的get方法,可以清楚看到轮询的机制。

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);...

剩余内容已隐藏

查看完整文章以阅读更多