关于这两个概念的理解,我们还可以举一个例子来说明。有8个人在排队玩一个打地鼠的游戏机,要求1分钟之内要打完100个地鼠,如果有人一分钟之内没有完成这个任务,那么就需要重新排队,等待下一轮。游戏机在这里相当于CPU,正在或等待玩打地鼠游戏的人就相当于任务数量。
在玩游戏的过程中,肯定有的人在规定的1分钟之内打完100个地鼠,完成任务之后就离开了,有人没有完成任务而去重新排队,还有可能有新增的人来玩这个游戏,人数的变化相当于任务的增减。有的人拿起打地鼠的锤子就开始玩,一直打完1分钟,而有的人可能在前20秒看手机,后40秒才开始玩打地鼠。把游戏机看作CPU,排队的人数看作任务数,我们说前一种人(任务)的CPU利用率高,后一种人(任务)的CPU利用率低。
当然CPU不会在前20秒休息、后40秒工作,只是说,有的程序可能涉及的计算量比较大,CPU利用率就高,而有的程序涉及的计算少,CPU的利用率就低。不管CPU利用率是高是低,跟后面有多少人(任务)在排队没有必然的联系。
之所以花了一些篇幅来介绍CPU的这两个概念,因为这两个指标实在是太重要了,在线上生产环境中是需要重点监控的。鉴于API网关的访问量大和依赖系统多的特点,如果调用的API性能突然变差,在大访问量的情况下,线程数会逐渐升高,直至将CPU资源耗尽。蔓延到整个网关集群,这就是雪崩的效应。
关注磁盘
磁盘有两个比较重要的指标分别是磁盘使用率和磁盘负载百分比。磁盘使用率比较容易理解,我们重点说一下磁盘负载百分比这个指标。在Linux系统下查看该指标的命令为 iostat -x 1 10 (如果没有iostat ,则需要使用yum install sysstat进行安装),笔者下面的图中示例值还构不成威胁,但如果 %util 接近 100%,则说明产生的I/O请求太多,I/O系统已经满负荷,该磁盘可能存在瓶颈,如下图所示。
程序运行的过程中我们可能都不会关注磁盘的使用,如果处理不当,这有可能是一个“定时炸弹”。网关的特性访问量大,再加上有的程序里面的日志打印不规范,比如日志的级别设置得不合理,把info日志打印出来。即使在日志级别合理的情况下,比如error日志,这时又涉及网关的第二个特性,依赖系统多。当有API返回失败错误的时候,就会有大量的error日志写入磁盘,很容易把磁盘打满,尤其在容器时代,每台服务器分配的磁盘容量相对物理机来说都比较小,如果集群的所有机器磁盘被打满,对网关系统来说无疑是一场灾难。
关注网络
在微服务系统架构下,应用离不开网络,尤其是网关系统,它的特点之一就是依赖系统多。依赖就是RPC调用和网络。在一个RPC环境下,网络占据了一次RPC调用所耗时间的很大比重。网络质量的好坏直接影响了一次请求从进入API网关到返回给用户响应的时间长短。如下图所示,网关到依赖系统B之间的网络突然变差,调用时长增加,在请求访问量多的时候,一请求一线程的模式下,会直接导致API 网关系统的任务线程数增多,如果短时间内不能恢复,则整个API网关的集群所有机器的CPU资源都会被线程耗尽。
同时现有的线上生产环境部署并不能完全保证同机房调用,甚至还有跨地区调用,因此网络是我们要考虑的一个重要因素,同时网络的因素需要和上面讲到的CPU的线程资源相关联去考虑。
现在可以总结一个传统API网关系统会有几种“死”法了,因为依赖的某个系统的API性能突然变差导致请求线程数量逐渐升高直至线程占满了CPU,也就是API网关依赖系统多的特点因素,可以认为是被其他系统“拖死”的。线上生产环境下日志输出不规范,过度打印日志,再加上请求量突然变大,导致清理工具来不及清理日志,最后磁盘满了,可以认为是被日志“打死”的。网络一直是一个除系统本身外最不稳定的因素,在系统之间调用的时候,网络发生故障导致请求变慢,这一点和第一条被其他系统“拖死”类似,只是这次是网络。
查理.芒格有一句名言:“如果我知道我会死在哪里,我将永远不去那个地方”。同样对于一个API网关系统,如果我们知道哪些因素会导致一个网关“挂掉”,那么我们就会提前防范,以避免这种“灾难”的发生。当然并不是宣扬传统网关不好,它也有自己的优势,比如编程模型简单、开发调试运维方便等。如果业务规模较小,比如每天调用量不足千万,或者不到亿级,那么可以继续使用这种类型的网关,甚至达到亿级规模之后再配合有效的容错机制(比如Netflix的zuul1+Hystrix)也可以支撑上亿规模的访问量。不过我们有更好的异步网关解决方案,接下来介绍异步网关技术实现。