最近在将应用的rpc更换为grpc,使用过程中,发现报“rpc error:code=DeadlineExceeded desc = context deadline exceeded”,这是啥?原来是某位仁兄设置了环境的超时时间,但是设置了1S,看好了,是1S。所以,任何稍微费时的交互,都直接报错了。

如果你不显式设置的话,GRPC自己默认的超时时间是一个很大的值,那就不会出现这种问题。但是给出的错误信息也是无语了,既然是超时,不能给个timeout的提示吗?搞了个什么deadline exceeded,初次看见,还是有点懵。

Anyway,谷歌出品,必属精品。出问题还是反思自己的使用吧。

Rule 1,建议显式的指定一个超时时间,一方面可以节省资源,不然所有的请求都无休止的在发送,在server中运行,有可能导致资源耗尽以致系统崩溃,另一方面,业务本身肯定也需要有一个返回时间,而不是提交请求之后,就傻傻的等着,到天荒地老吗?

Rule 2,没有明确的规则,什么样的超时时间是合适的,这个是开发人员需要加以考虑的。需要考虑网络,如果网络耗时很明显,需要考虑服务器的资源,内存,CPU以及负载,需要考虑外部交互,更重要的,其实是搞清楚业务规则,这个request所对应的业务对时间的要求。虽然只是设置了个时间,但也不是那么容易,不然程序员怎么那么值钱。

Rule 3,当设置超时时间时,需要考虑client和server两方面的情况。首先,设置超时的方式不一样,server端或者在proto文件中指定就行,client端就需要编码了。其次,当client端设置了超时时间,server端就必须有所响应,不然就会发生意料之外的事情。

代码片段一,设置超时

作为客户端,你应该知道自己希望最晚多长时间拿到返回结果吧,那就设置他吧。

 C++

 ClientContext context;
time_point deadline = std::chrono::system_clock::now() +
std::chrono::milliseconds(100);
context.set_deadline(deadline); Go clientDeadline := time.Now().Add(time.Duration(*deadlineMs) * time.Millisecond)
ctx, cancel := context.WithDeadline(ctx, clientDeadline) Java response = blockingStub.withDeadlineAfter(deadlineMs, TimeUnit.MILLISECONDS).sayHello(request);

如上的代码中,都设置了超时时间为100毫秒。

代码片段二,检查超时

作为服务器端,如果客户端设置了超时,服务器端就需要去检测下,否则如果客户端已经超时了,服务器端还傻乎乎的干活?岂不是真傻了。

 C++
if (context->IsCancelled()) {
return Status(StatusCode::CANCELLED, "Deadline exceeded or Client cancelled, abandoning.");
} Go
if ctx.Err() == context.Canceled {
return status.New(codes.Canceled, "Client cancelled, abandoning.")
} Java
if (Context.current().isCancelled()) {
responseObserver.onError(Status.CANCELLED.withDescription("Cancelled by client").asRuntimeException());
return;
}

一般而言,server在拿到request之后就应该检测client的超时时间,如果超时了,就不在执行逻辑。不过,如果在server开始执行逻辑但并没有结束的时候client超时了怎么办,当然可以在server执行逻辑的同时检测是否超时,如果超时,cancel掉逻辑。但是也有特殊情况,比如这个逻辑很耗费资源,但是结果对客户端而言是可重用的,或者说结果是可以缓存的,那么就需要把结果保存下来,别cancel逻辑了。so, it depends。

代码片段三,调整超时

程序员的苦逼就在于需求一直在变,不过没办法,我们学的哲学不就是说变是永恒的,不变是幻觉吗?那么设置了超时,怎么改?废话,怎么设置的就怎么改啊,这么说当然是废话,这里要说的是在不进行新的版本发布的情况下,怎么改。

 C++
#include <gflags/gflags.h>
DEFINE_int32(deadline_ms, 20*1000, "Deadline in milliseconds."); ClientContext context;
time_point deadline = std::chrono::system_clock::now() +
std::chrono::milliseconds(FLAGS_deadline_ms);
context.set_deadline(deadline); Go
var deadlineMs = flag.Int("deadline_ms", 20*1000, "Default deadline in milliseconds.") ctx, cancel := context.WithTimeout(ctx, time.Duration(*deadlineMs) * time.Millisecond) Java
@Option(name="--deadline_ms", usage="Deadline in milliseconds.")
private int deadlineMs = 20*1000; response = blockingStub.withDeadlineAfter(deadlineMs, TimeUnit.MILLISECONDS).sayHello(request);

看到了吧,这样的话,超时时间就不用硬编码了,我们可以动态的设定,直到我们的业务和程序运行都收敛了,或许就可以真正硬编码一个超时时间了。

grpc deadlines的更多相关文章

  1. 带入gRPC:gRPC Deadlines

    带入gRPC:gRPC Deadlines 原文地址:带入gRPC:gRPC Deadlines项目地址:https://github.com/EDDYCJY/go... 前言 在前面的章节中,已经介 ...

  2. Golang gRPC学习(04): Deadlines超时限制

    为什么要使用Deadlines 当我们使用gRPC时,gRPC库关系的是连接,序列化,反序列化和超时执行.Deadlines 允许gRPC客户端设置自己等待多长时间来完成rpc操作,直到出现这个错误 ...

  3. Go gRPC进阶-超时设置(六)

    前言 gRPC默认的请求的超时时间是很长的,当你没有设置请求超时时间时,所有在运行的请求都占用大量资源且可能运行很长的时间,导致服务资源损耗过高,使得后来的请求响应过慢,甚至会引起整个进程崩溃. 为了 ...

  4. gRPC源码分析1-SSL/TLS

    引子 前几天看到微信后台团队分享了TLS相关文章,正好gRPC里TLS数据加密是很重要的一块,于是整理出了这篇文章. 在gRPC里,如果仅仅是用来做后端微服务,可以考虑不加密.本文太长,先给个大纲. ...

  5. gRPC源码分析2-Server的建立

    gRPC中,Server.Client共享的Class不是很多,所以我们可以单独的分别讲解Server和Client的源码. 通过第一篇,我们知道对于gRPC来说,建立Server是非常简单的,还记得 ...

  6. gRPC源码分析0-导读

    gRPC是Google开源的新一代RPC框架,官网是http://www.grpc.io.正式发布于2016年8月,技术栈非常的新,基于HTTP/2,netty4.1,proto3.虽然目前在工程化方 ...

  7. 谷歌发布的首款基于HTTP/2和protobuf的RPC框架:GRPC

    Google 刚刚开源了grpc,  一个基于HTTP2 和 Protobuf 的高性能.开源.通用的RPC框架.Protobuf 本身虽然提供了RPC  的定义语法,但是一直以来,Google 只开 ...

  8. gRPC .NET Core跨平台学习

    前些天发布gRPC C# 学习,在.NET Framework 中使用gRPC ,今天来学习 .NET Core gRPC. gRPC 的.NET Core 包在NuGet 上发布了,结合.NET C ...

  9. gRPC C#学习

    前些天gRPC 发布1.0 版本,代表着gRPC 已经正式进入稳定阶段. 今天我们就来学习gRPC C# .而且目前也已经支持.NET Core 可以实现完美跨平台. 传统的.NET 可以通过Mono ...

随机推荐

  1. Ajax提交乱码

    1. 页面码 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&g ...

  2. C++ primer 练习9.52 适配器stack 中缀表达式

    //调试环境 VS2015//本人菜鸟一枚,不喜勿喷! 谢谢!!!//主要思想引自  http://www.cnblogs.com/dolphin0520/p/3708602.html//主要代码引自 ...

  3. springboot的aop编程

    以下内容是模仿杨开振<<深入浅出springboot 2.x>>的4.2章节内容. 开始前,需要先修改pom.xml,加入以下内容 <!-- https://mvnrep ...

  4. jQuery 切换图片(图标)效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. 百度app红包? 百度全家桶?果断卸载

    听说今年的春晚红包与百度合作.这不 刚又下载了一个百度app,之前下载过,太卡了,用户体验极.本身对百度也没啥好感,再加上这周看了:百度已死的文章,搜索全百家号.具体啥情况,你们百度搜一搜吧

  6. hive 从Excel中导入数据

    拿到Excel表后将数据保留,其他的乱七八糟都删掉,然后另存为txt格式的文本,用nodepad++将文本转换为UTF-8编码,此处命名为cityprovince.txt 将cityprovince. ...

  7. POJ2739 Sum of Consecutive Prime Numbers 确定某个数以内的所有素数

    参考:https://www.cnblogs.com/baozou/articles/4481191.html #include <iostream> #include <cstdi ...

  8. python2.7练习小例子(十八)

    19):题目:一个数如果恰好等于它的因子之和,这个数就称为"完数".例如6=1+2+3.编程找出1000以内的所有完数.      #!/usr/bin/python # -*- ...

  9. phpMyAdmin出现错误 Access denied for user 'root'@'localhost' (using password: NO)

    今天安装wmpp,之后启动后点击phpMyAdmin 报拒绝连接错误:#1045 - Access denied for user 'root'@'localhost' (using password ...

  10. linux shell中读写操作mysql数据库

    本文介绍了如何在shell中读写mysql数据库.主要介绍了如何在shell 中连接mysql数据库,如何在shell中创建数据库,创建表,插入csv文件,读取mysql数据库,导出mysql数据库为 ...