服务为什么需要 timeout 呢?提前释放资源

记得在上家公司时,一个 python 服务与公网交互,request 库发出去的请求没有设置 timeout ... 而且还是个定时任务,占用了超多 fd

同时微服务场景下某下游的服务阻塞卡顿,这样会造成他的级联上下游都雪崩了。

语言层面:对于使用线程池的语言,会消耗所有线程,work 不够用。其实对于 go 来说,创建大量 goroutine 也会有 runtime 开销的, 只是慢性死亡罢了

内核层面:还有一点超时配置的必要性,如果某服务挂了,那么内核会帮忙收尾,根据情况或走 RST 或走 FIN,访问者就知道链接关了。但如果主机挂了,或者中间网络设备挂了,客户端没有超时配置,就只能 tcp keepalive 来判断死链接,按照默认内核配置语言两个多小时。文末提到 redis 就是例子

Latency

业界都用 P99 分位来衡量服务的 latency, 即使这样如果 QPS 非常高,另外 1% 的请求也会出现 long tail. 再来看几个不同侧重点的概念:

Server Side P99 统计的只是 server handler 处理时间

Client P99 =  client framework 时间 + client 内核处理时间 + 网络传输时间 + server 处理时间

当你发现 latency 比较高,想去 challenge 下游时,请对好口径。通常 client p99 > server p99

这还是普通的 server/client 模式,如果中间涉及了 lb, 或是 mesh 排查问题很要命

可观测性

现在都是微服务场景,一个订单全链路涉及几十个服务,查起问题非常困难,所以分布式的 tracing 系统非常重要

另外现在也都拥抱云原生环境,如果引入 service mesh 的话更难以排查问题

一般 tracing 系统都是根据 google 论文 Dapper, a Large-Scale Distributed Systems Tracing Infrastructure[1] 发展而来的

除了自己造轮子,主流的有 zipkin[2], opentelemetry[3]

底层实现

定时器这块业务早有标准实现:小顶堆, 红黑树时间轮. 感兴趣的同学可以搜索相关文章

原理不难,但是有公司面试都要求手写红黑树!!!这就过份了吧

Linux 内核和 Nginx 的定时器采用了 红黑树 实现,好多长连接系统多采用 时间轮

Go 使用 小顶堆, 四叉堆,比较矮胖,不是最朴素的二叉堆。

最早版本只有一个 timer 堆,所以性能非常差,精度也有问题。一般都用户实现多堆,或是用时间轮实现。这方面的轮子比写公众号的码农都多 ^_^

后来经过优化 Go 内置多堆实现,每个 P 一个 timer 堆,性能好了很多。注意,Go 的 conn timeout 是通过用户层 timer 实现的,而不是内核的 setsockopt

HTTP

这里要区分 http1 和 http2, 以前写过一篇 HOL blocking

Http1 如果超时到了,那么底层库是要关闭 tcp connection 的,强制丢弃未读到的数据,这时会产生大量的 timewait, 要注意

但是对于 Http2 来说,虚拟出来了 stream, 做到了多路复用,只要关闭 stream 即可,底层 socket 还可以正常使用

对于 go http 还有一个坑,可以参考 i/o timeout , 希望你不要踩到这个net/http包的坑[4]

func init() {tr = &http.Transport{MaxIdleConns: 100,Dial: func(netw, addr string) (net.Conn, error) {conn, err := net.DialTimeout(netw, addr, time.Second*2) //设置建立连接超时if err != nil {return nil, err}err = conn.SetDeadline(time.Now().Add(time.Second * 3)) //设置发送接受数据超时if err != nil {return nil, err}return conn, nil},}
}

上面代码是错误使用,这个导致每次 conn 连接后只设置一次超时时间

client := &http.Client{Transport: tr,Timeout: 3*time.Second,  // 超时加在这里,是每次调用的超时}

正确的应该在 http.Client 结构体里设置,感兴趣的去参考全文吧

另外服务端也要设置 timeout, 以防把服务端压跨,请参考 So you want to expose Go on the Internet[5]

srv := &http.Server{ReadTimeout:  5 * time.Second,WriteTimeout: 10 * time.Second,IdleTimeout:  120 * time.Second,TLSConfig:    tlsConfig,Handler:      serveMux,
}
log.Println(srv.ListenAndServeTLS("", ""))

数据库相关

做为 CRUD Boy, 经常和 DB 打交道,让我们来看下常见的超时设置与坑

Redis 服务端要注意两个参数:timeouttcp-keepalive

其中 timeout 用于关闭 idle client conn, 默认是 0 不关闭,为了减少服务端 fd 占用,建议设置一个合理的值

tcp-keepalive 在很早的 redis 版本是不开启的,这样经常会遇到因为网格抖动等原因,socket conn 一直存在,但实际上 client 早己经不存在的情况

Redis Client 实现有一个重大问题,对于集群环境下,有些请求会做 Redirect 跳转,默认是 16 次,如果 tcp read timeout 设置了 100ms, 那总时间很可能超过了 1s

这就是一直强调的问题,tcp timeout 设置不代表实际的调用时间,因为业务层会多次调用 socket 读写。最好外面包一层 context 或是 circuit breaker

MySQL 也同样服务端可以设置 MAX_EXECUTION_TIME 来控制 sql 执行时间。不同发行版本还不一样,有的只支持 select, 有的同时支持 dml ddl ...

其它

Q: 有同事问 timeout 与 sla 什么关系?

A: 要大于 sla. 没有经过 toB 业务的重锤,感触不深,有朋友了解的可以留言讲讲 toB 业务的玩法

Q: 如何传递 timeout ?

A: 一般都是框架层传递的,比如 grpc 会在 header 里传递服务的 timeout, 每经过一个 backend, 减去相应的耗时

Q: 依赖的下游出现大量超时,应该如何处理?

A: 要做到 fast fail, 一定得有降级 (circuit breaker 熔断)措施,否则会拖垮整条链路。

小结

这次分享就这些,以后面还会分享更多的内容,如果感兴趣,可以关注并点击左下角的分享转发哦(:

参考资料

[1]

Dapper, a Large-Scale Distributed Systems Tracing Infrastructure: https://research.google/pubs/pub36356/,

[2]

zipkin: https://zipkin.io/,

[3]

opentelemetry: https://opentelemetry.io/docs/concepts/distributions/,

[4]

i/o timeout , 希望你不要踩到这个net/http包的坑: https://mp.weixin.qq.com/s/UBiZp2Bfs7z1_mJ-JnOT1Q,

[5]

So you want to expose Go on the Internet: https://blog.cloudflare.com/exposing-go-on-the-internet/,

你真的懂 timeout 吗?相关推荐

  1. “三次握手,四次挥手”你真的懂吗?

    来源:码农桃花源 解读:"拼多多"被薅的问题出在哪儿?损失将如何买单? 之前有推过一篇不错的干货<TCP之三次握手四次挥手>,前几天有兄弟投稿,开始还以为是同一篇,后经 ...

  2. 【原创】“三次握手,四次挥手”你真的懂吗?

    记得刚毕业找工作面试的时候,经常会被问到:你知道"3次握手,4次挥手"吗?这时候我会"胸有成竹"地"背诵"前期准备好的"答案&qu ...

  3. 示波器_你真的懂示波器嘛?面试中会用到的示波器知识

    示波器是电子工程师经常使用到的电子测量仪器,用途十分广泛,可将肉眼看不见的电信号变换成看得见的图像,便于人们研究各种电现象的变化过程.利用示波器能观察各种不同信号幅度随时间变化的波形曲线,还可以用它测 ...

  4. 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截...

    程序猿修仙之路--数据结构之你是否真的懂数组? 数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构  .要想在之后的江湖历练中通关,数据结构必不可少.数据 ...

  5. 【转】先说IEnumerable,我们每天用的foreach你真的懂它吗?

    [转]先说IEnumerable,我们每天用的foreach你真的懂它吗? 我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq ...

  6. 你真的懂TensorFlow吗?Tensor是神马?为什么还会Flow?

    本文的ipynb 格式见CSDN下载. 0维张量/标量 标量是一个数字 1维张量/向量 1维张量称为"向量". 2维张量 2维张量称为矩阵 3维张量 公用数据存储在张量 时间序列数 ...

  7. 关于Spring底层原理面试的那些问题,你是不是真的懂Spring?

    转载自  关于Spring底层原理面试的那些问题,你是不是真的懂Spring? 1.什么是 Spring 框架?Spring 框架有哪些主要模块? Spring 框架是一个为 Java 应用程序的开发 ...

  8. 你真的懂Redis的5种基本数据结构吗?

    摘要: 你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看. 本文分享自华为云社区<你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看>,作者:李子捌. 一 ...

  9. 你真的懂语音特征吗?

    摘要:本文指在详细介绍语音转化声学特征的过程,并详细介绍不同声学特征在不同模型中的应用. 本文分享自华为云社区<你真的懂语音特征背后的原理吗?>,作者: 白马过平川 . 语音数据常被用于人 ...

最新文章

  1. ie浏览器在线使用_全球浏览器5月份市场份额公布!Chrome和Edge浏览器迎来新一轮“撕X”大战...
  2. python文件操作与异常处理_Python学习——文件操作和异常处理
  3. js粘贴板为什么获取不到图片信息_JavaScript 学习笔记(3):图片库
  4. mysql数据库安全审计_MySQL数据库安全日志审计工具
  5. Python 写各大聊天系统的屏蔽脏话功能原理
  6. 前端学习(8):HTML的基本属性和结构
  7. 线程池选择使用的hash算法
  8. 用GDB调试PHP扩展
  9. C#图片处理之:图片缩放和剪裁
  10. 2014-07-22 如何成为一名合格的职业人士
  11. 译: 6. 任务调度(定时执行任务)
  12. nginx 没有cookie_nginx实现负载均衡的原理及策略
  13. 论如何用cmd命令做出数字雨特效
  14. 双光耦开关电源电路图_几种常见开关电源电路图
  15. 骨骼动画详解-Spine
  16. 蓝桥杯2016年第七届真题-碱基
  17. 【热门】女孩取名:女孩名字带歆什么寓意
  18. win10 sublime text3配置c++
  19. java中OOP的概念之我见
  20. ElasticSearch 从零到入门

热门文章

  1. android相册拍照剪切上传封装,安卓,图片裁剪上传真机测试好使,打包后显示:无法保存裁剪的图像...
  2. aosp 为什么某些目录没有编译_编译Android AOSP代码
  3. 使用支持向量机进行光学字符识别_从零推导支持向量机 (SVM)
  4. 210130阶段三socket服务器
  5. [DeeplearningAI笔记]卷积神经网络2.9-2.10迁移学习与数据增强
  6. koa-mysql(三)
  7. Linux:让普通用户临时性获得root用户权限
  8. log4j(六)——log4j.properties简单配置样例说明
  9. AJAX——基于请求加载数据
  10. 外包女程序员-----励志段子 留着 等没事的时候看看