Home | 简体中文 | 繁体中文 | 杂文 | 知乎专栏 | Github | OSChina 博客 | 云社区 | 云栖社区 | Facebook | Linkedin | 视频教程 | 打赏(Donations) | About
知乎专栏多维度架构 微信号 netkiller-ebook | QQ群:128659835 请注明“读者”

第 4 章 多维度架构之超时时间

目录

4.1. 无处不在的超时时间
4.2. 流量漏斗
4.3. 微服务的超时时间
4.4. 容器技术的超时时间
4.5. 最后总结

超时时间俗称 Timeout 它是引起应用程序无响应或者网络服务雪崩灾难的罪魁祸首。

超时时间设置非常讲究,太长不行,太短也不行。

超时时间由哪些

  1. 网络超时
  2. 文件系统超时
  3. 执行时间超时

4.1. 无处不在的超时时间

早期架构相对简单,拓扑成线性,例如:

		
用户 —> WEB服务器 —> 应用服务器 —> 缓存 —> 数据库
		
		

这是最典型的应用了,我们就用这个来举例,所有例子都是我职业生涯中遇到过的,绝对真实。

很早的时候,那时还没有分布式文件系统,不过我们的系统IO压力不大,仅仅是为了高可用。我们使用 NFS 共享 WEB服务器上的HTML文件和图片。然后通过DNS轮询做负载均衡,这是 2005年之前常用的做法。

发生了什么呢,NFS 发神经,用一段时间后出现卡顿,读不出数据,Apache httpd 的超时时间设置为 60s 秒,此时WEB服务器进来一个用户启动一个进程(那时 httpd 还不支持多线程),读取NFS共享的HTML,httpd 一直读不出来文件内容,直到60秒后 httpd 才会返回 500 错误给用户,用户始终超时等待。就这样,来一个用户,启动一个进程,用不了多久 httpd 最大连接数将被尽。

如果我们将超时时间30秒,可以加速进程的释放时间,可能会缓解 NFS 问题。设置成10秒呢? 答案是不行,有些请求过程中会出现网络不稳定的情况,设置成10秒钟,httpd 就会终止用户连接。这种情况在大文件下载,上传的过程中较为明显。

从WEB服务器到应用服务器,可能是 cgi-bin, fastcgi, servlet 等等,连接方式有反向代理,也有特别的协议(好久不用忘记Tomcat 插件,好像叫 mod-jk)也有超时设置。设置不当会出现什么问题呢?

开发中我们要计算一个请求所花费的时间,尽量在5秒之内完成执行并返回结果,大于五秒就会产生用户流失,用于没有耐心等待页面完成加载,就会跳到其他网站。所以超时时间设置 60 秒基本上没有什么意义,只有下载和上传服务可能会用到。正常控制在 20-30秒可以应对大多数需求。同时 WEB 服务器 与 应用服务器的设置需要匹配,例如 WEB服务器设置为 30秒,应用服务器设置为 60秒的后果是,程序还没有执行完成,WEB服务器就切断了与后面应用服务器的联系,并返回500错误。所以说后面应用服务器的超时时间设置,不能大于前面WEB服务器的超时时间设置。WEB切断与应用服务器通信后,应用服务器仍会继续执行,如果是 fastcgi 就可能看到非常多的进程在运行,并处于等待状态。

从应用服务器到缓存服务器,我遇到过这样一个事故,一名初级开发人员首次使用 memcached (那时还没有 Redis)没有经验,正确应该将一个数据结构序列化后存储到 memcache 中,他将这组数据,一条一条的写入memcache ,使用的时候使用循环遍历所有的 key。导致执行时间超过一分钟。 这样程序始终无法在规定的超时时间执行完成。上线后立即崩溃,虽然也做了压力测试,但是有很多代码在测试环境是无法展现的。压力测不是万能的。

最后是数据库超时时间,数据库超时时间的设置,执行超时时间比网络超时时间更重要。所谓执行超时时间,就是控制执行SQL语句的时间,在规定时间没有完成查询就直接返回超时。这样做的目的是为了保护数据库,否则数据库很容易就崩溃了。跟前面的例子一样,如果将数据库执行超时时间设置为60秒,有一条SQL执行很慢,运行时间超过60秒,查询就会堆积,直到数据库连接数被占用完为止。所以我们要经常审计慢查询日志。

再说说网络设备造成的延迟,前面谈到的各种服务器应用出现问题都比较好排查,基本都是可见。网络设备造成的故障就比较难,理由水晶头氧化了,网络偶尔出现丢包卡顿。重新插拔一次水晶头故障就消失了。