gRPC为什么使用截止时间而不是超时时间?

开发 前端
截止时间相当于设置整个请求生命周期的时间,也就是这个请求,我要多久拿到结果。很明显,这个时间应该在客户端发起请求的时候设置。

在 HTTP 请求中,我们发送请求的时候,可以设置一个请求超时时间-connectTimeout,即在指定的时间内,如果请求没有到达服务端,为了避免客户端一直进行不必要的等待,就会抛出一个请求超时异常。

但是在微服务系统中,我们却很少设置请求超时时间,一般都是用另外一个概念代替,那就是请求截止时间。

这是什么原因呢?今天我们就来简单聊一聊这个话题。

在微服务中我们客户端的请求在服务端往往会有比较复杂的链条,我想起来 Spring Cloud Sleuth 官方给的一个请求链路追踪的图,我们直接拿来看下:

图片

这张图中,请求从客户端发起之后,在服务端一共经历了四个 SERVICE,对于这样的请求,如果我们还是按照之前发送普通 HTTP 请求的方式,设置一个 connectTimeout 显然是不够的。

我举个例子:

假设我们发送一个请求,为该请求设置 connectTimeout 为 5s,那么这个时间只对第一个服务 SERVICE1 有效,也就是请求在 5s 之内没有到达 SERVICE1,那么就会抛出连接超时异常;请求如果在 5s 之内到达 SERVICE1,那么就不会抛出异常,但是!!!,请求到达 SERVICE1 并不意味着请求结束,后面从 SERVICE1 到 SERVICE2,从 SERVICE2 到 SERVICE3,从 SERVICE3 到 SERVICE4,还有四个 HTTP 请求待处理,这些请求超时了怎么办?很明显,connectTimeout 属性对于后面几个请求就鞭长莫及了。

所以,对于这种场景,我们一般使用截止时间来处理。

截止时间相当于设置整个请求生命周期的时间,也就是这个请求,我要多久拿到结果。很明显,这个时间应该在客户端发起请求的时候设置。

gRPC 中提供了对应的方法,我们可以非常方便的设置请求的截止时间 DeadLineTime,如下:

public class LoginClient {
public static void main(String[] args) throws InterruptedException {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 50051)
.usePlaintext()
.build();
LoginServiceGrpc.LoginServiceStub stub = LoginServiceGrpc.newStub(channel).withDeadline(Deadline.after(3, TimeUnit.SECONDS));
login(stub);
}

private static void login(LoginServiceGrpc.LoginServiceStub stub) throws InterruptedException {
CountDownLatch countDownLatch = new CountDownLatch(1);
stub.login(LoginBody.newBuilder().setUsername("javaboy").setPassword("123").build(), new StreamObserver<LoginResponse>() {
@Override
public void onNext(LoginResponse loginResponse) {
System.out.println("loginResponse.getToken() = " + loginResponse.getToken());
}

@Override
public void onError(Throwable throwable) {
System.out.println("throwable = " + throwable);
}

@Override
public void onCompleted() {
countDownLatch.countDown();
}
});
countDownLatch.await();
}
}

服务端通过 Thread.sleep 做个简单的休眠就行了,超时之后,客户端的 onError 方法会被触发,抛出如下异常:

throwable = io.grpc.StatusRuntimeException: DEADLINE_EXCEEDED: deadline exceeded after 2.939621462s. [closed=[], open=[[buffered_nanos=285550823, remote_addr=localhost/127.0.0.1:50051]]]

好啦,一个简单的小细节,感兴趣的小伙伴不妨去试试啦~

责任编辑:武晓燕 来源: 江南一点雨
相关推荐

2013-03-25 10:14:18

NginxApache

2020-09-15 09:23:19

C++WindowsC#

2021-03-26 11:50:28

Linuxexals

2021-06-30 12:47:12

标签HTML分辨率

2021-02-26 05:30:25

元素For-Each代码

2020-02-20 09:55:46

LinuxPython数据

2019-04-19 11:56:48

框架AI开发

2016-09-19 09:15:49

Windows 10锁屏超时

2021-10-30 19:57:00

HTTP2 HTTP

2012-10-10 16:52:21

CentOSDebianUbuntu

2021-08-14 09:04:58

TypeScriptJavaScript开发

2017-09-11 19:58:06

PostgreSQLMySQL数据库

2020-06-02 14:17:55

QWER排列键盘打印机

2023-11-02 08:20:54

SocketZygoteAndroid

2020-07-24 09:20:44

MapObject前端

2023-09-29 11:50:10

接口编程代码

2022-11-14 07:52:14

时间序列数据库CPU

2016-10-11 11:13:15

Linus Torva

2019-09-24 09:33:53

MySQLB+树InnoDB

2023-01-11 12:14:50

NeoVimVim开发
点赞
收藏

51CTO技术栈公众号