Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions content/en/overview/mannual/java-sdk/tasks/framework/timeout.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,25 +55,37 @@ The priority of the above configuration forms from high to low is: `method-level

Let's analyze the above calling chain and the possible timeout situations:
* A calls B and sets a timeout of 5 seconds, therefore the total time for `B -> C -> D` should not exceed 5 seconds, otherwise A will receive a timeout exception.
* In any case, as long as A waits 5 seconds without receiving a response, the entire call chain can be terminated (if C is running at this time, then `C -> D` has no meaning to initiate).
* Theoretically, both `B -> C` and `C -> D` have their own independent timeout settings and the timeout counting is also calculated independently; they do not know whether A as the caller has timed out.
* In any case, once A has waited for 5s without a response, the entire chain can be terminated. If C is still running at that point, initiating `C -> D` becomes meaningless and wastes resources, a problem that is particularly evident in long-chain scenarios.

In the Dubbo framework, the call `A -> B` acts like a switch; once activated, the entire `A -> B -> C -> D` call chain will be executed completely, even if the caller A has already timed out, subsequent calling actions will continue. This can be meaningless in some scenarios, especially in long chains as it leads to unnecessary resource consumption. The deadline is designed to solve this problem by passing a deadline through the call chain (the initial value of the deadline equals the timeout, decreasing as time passes). This ensures the call chain only executes within its validity period; once the deadline is exhausted, other unexecuted tasks in the call chain will be canceled.
To address this, Dubbo introduced the **Deadline mechanism**. By passing a "deadline" (initially equal to the timeout) along the invocation chain, the entire process is constrained within a unified time window. As the call deepens, the deadline is continuously decremented; subsequent services use the remaining time as their effective timeout. If the deadline is exhausted, any remaining tasks in the chain are canceled.

Thus, the deadline mechanism treats `B -> C -> D` as a whole, and this series of actions must be completed within 5 seconds. As time passes, the deadline will decrease from 5 seconds. For each subsequent call, the actual available timeout is the current deadline value; for example, if `C` receives the request 3 seconds later, then the timeout for `C -> D` only has 2 seconds left.
**Example:**

- When A initiates a call with timeout = 5000ms, the initial deadline is 5000ms.

- By the time C initiates its request, if the chain has already consumed 3000ms, the call C -> D is restricted to a maximum of 2000ms.

<img style="max-width:600px;height:auto;" src="/imgs/v3/tasks/framework/timeout-deadline.png"/>

The deadline mechanism is off by default. To enable the deadline mechanism, configure the following parameters:
The Deadline mechanism is disabled by default and must be explicitly enabled. Use the following application-level configuration:

```yaml
dubbo:
provider:
timeout: 5000
parameters.enable-timeout-countdown: true
```

You can also enable the deadline mechanism for a specific service call:
Alternatively, you can configure it for a specific service:
```java
@DubboReference(timeout=5000, parameters={"enable-timeout-countdown", "true"})
private DemoService demoService;
```

In a Dubbo chain, once an upstream service enables enable-timeout-countdown=true, all subsequent nodes **inherit and propagate** the deadline by default (no additional configuration needed), unless a node explicitly sets it to false to break the chain. This constraint covers all synchronous and asynchronous calls initiated by **Dubbo threads**. However, it cannot be automatically propagated by non-Dubbo threads (e.g., custom thread pools, CompletableFuture.supplyAsync),example:
```Java
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return service.invoke("hello");
});
```
29 changes: 22 additions & 7 deletions content/zh-cn/overview/mannual/java-sdk/tasks/framework/timeout.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,41 @@ public class DemoServiceImpl implements DemoService{}
<img style="max-width:600px;height:auto;" src="/imgs/v3/tasks/framework/timeout.png"/>

我们来分析一下以上调用链路以及可能出现的超时情况:

* A 调用 B 设置了超时时间 5s,因此 `B -> C -> D` 总计耗时不应该超过 5s,否则 A 就会收到超时异常
* 在任何情形下,只要 A 等待 5s 没有收到响应,整个调用链路就可以被终止了(如果此时 C 正在运行,则 `C -> D` 就没有发起的意义了)
* 理论上 `B -> C`、`C -> D` 都有自己独立的超时时间设置,超时计时也是独立计算的,它们不知道 A 作为调用发起方是否超时
* 理论上 `B -> C`、`C -> D` 都有配置了独立的超时时间,且超时计时是独立计算的,它们并不知道调用发起方 A 是否已经超时
* 在任何情形下,只要 A 等待 5s 没有收到响应,整个调用链路就可以被终止了。如果此时 C 正在运行,则发起 `C -> D` 就没有意义了,会造成不必要的资源消耗,这在长链路场景中尤为明显

为了解决上述问题,Dubbo 引入了 Deadline 机制,通过在调用链路中透传 deadline(初始值等于超时时间),使得整个调用链能在统一的时间窗口内执行。随着调用深入,deadline 不断被扣减,后续服务的超时时间等于 deadline 剩余时间。如果 deadline 消耗殆尽,调用链路中其他尚未执行的任务将被取消。

例如:

在 Dubbo 框架中,`A -> B` 的调用就像一个开关,一旦启动,在任何情形下整个 `A -> B -> C -> D` 调用链路都会被完整执行下去,即便调用方 A 已经超时,后续的调用动作仍会继续。这在一些场景下是没有意义的,尤其是链路较长的情况下会带来不必要的资源消耗,deadline 就是设计用来解决这个问题,通过在调用链路中传递 deadline(deadline初始值等于超时时间,随着时间流逝而减少)可以确保调用链路只在有效期内执行,deadline 消耗殆尽之后,调用链路中其他尚未执行的任务将被取消。
- A 发起调用时设置 timeout = 5000ms,则 deadline 初始值为 5000ms

因此 deadline 机制就是将 ` B -> C -> D` 当作一个整体看待,这一系列动作必须在 5s 之内完成。随着时间流逝 deadline 会从 5s 逐步扣减,后续每一次调用实际可用的超时时间即是当前 deadline 值,比如 `C` 收到请求时已经过去了 3s,则 `C -> D` 的超时时间只剩下 2s。
- 当 C 发起请求时,整个链路已消耗 3000ms,则 `C -> D` 最多只能再用 2000ms

<img style="max-width:600px;height:auto;" src="/imgs/v3/tasks/framework/timeout-deadline.png"/>

deadline 机制默认是关闭的,如果要启用 deadline 机制,需要配置以下参数:
Deadline 机制默认是关闭的,需显式开启,应用级别的配置如下:

```yaml
dubbo:
provider:
timeout: 5000
parameters.enable-timeout-countdown: true
```

也可以指定某个服务调用开启 deadline 机制:
也可以为某个服务单独配置:

```java
@DubboReference(timeout=5000, parameters={"enable-timeout-countdown", "true"})
private DemoService demoService;
private DemoService demoService;
```

在 Dubbo 链路中,只要链路上游开启 `enable-timeout-countdown=true`,后续所有节点**默认继承并透传** deadline(无需额外开启),除非显式设为 `false` 才会中断。该约束覆盖所有 Dubbo 线程发起的同步/异步调用,但**非 Dubbo 线程**(如自定义线程池、CompletableFuture 等)发起的调用无法自动透传。示例:

```java
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
return service.invoke("hello");
});
```
Loading