在你的代码之外,服务时延过长的三个追查方向(上)

来源:互联网 发布:c语言有多少个函数 编辑:程序博客网 时间:2024/05/26 05:52

服务化体系里一般都有着严格的超时设定,为业务部门排查那些毛刺慢响应,也是基础架构部门的专家坐诊服务之一。

有时候,即使你的代码写的很努力了,但还是会出现慢响应,因为这本就是艰难的世界。 本文从三个方向上各举一些例子:

第一方面主要是热身,更加有趣的两方面见下集。

 

第一方面,操作系统篇

准备知识: 《从Apache Kafka 重温文件高效读写》中Swap 和 PageCache的部分。

1. 禁用swap

Linux有个很怪的癖好,当内存不足时,看心情,有很大机率不是把用作IO缓存的Page Cache收回,而是把冷的应用内存page out到磁盘上(具体算法看准备知识)。当这段内存重新要被访问时,再把它重新page in回内存(所谓的主缺页错误),这个过程进程是停顿的。增长缓慢的老生代,池化的堆外内存,都可能被认为是冷内存,用 cat /proc/[pid]/status 看看 VmSwap的大小, 再dstat里看看监控page in发生的时间。

在 /etc/sysctl.conf 放入下面一句,基本可以杜绝swap。设成0会导致OOM,案例在此,有些同学就设成1,喜欢就好。

 

vm.swappiness = 10

 

2. 加快Page Cache Flush的频率

又是一个Linux自己的奇怪设置,Linux的Page Cache机制说来话长(还是看看准备知识), 简单说IO其实都默认不是先写磁盘,而是写进Page Cache内存,inode脏了30秒,或脏数据达到了10%可用内存(Free+PageCache -mmap),才开始起flusher线程写盘。

我们的生产机内存起码都剩20G的样子,想想要以普通硬盘100MB/s级别的速度,一次写2G文件的速度....好在一般都达不到这个条件,一般是由几个日志文件轮流30秒触发,一次写几百M,花个三秒左右的时间。

文章里说,后台刷盘线程不会阻塞应用程序的write(2)。但是,

应用的write 过程是这样的:
锁inode -> 锁page -> 写入page -> 解锁page -> 解锁inode -> 锁inode page -> 写inode page -> 解锁inode page

而flusher的过程是这样的:
锁page -> 将page放进IO队列,等待IO调度写盘完成返回 -> 解锁page

可见,还是有锁,IO调度器也不是绝对公平,当IO繁忙,应用还是会发生阻塞 。

我们的做法是用一个100MB的绝对值来代替可用内存百分比来作为阀值。

在 /etc/sysctl.conf 里加入

 

vm.dirty_background_bytes = 104857600

在第二篇举的JVM停顿的例子,全和IO相关,即使不做后面JVM的调优,光降低这个阀值,也能大大缓解。

当然什么值是最优,必须根据机器配置,应用特性来具体分析。

 

3. 网络参数

太多可配置的地方,可以参考阿里云团队的一个很好的文章 Linux TCP队列相关参数的总结。 还是那句,不能看着文章就开始设,必须根据自己的情况。

比如我们自己设置网卡软中断队列的CPU亲和度:

平时网卡中断可能只用一个核来响应,在大流量下那个核会跑满。
运行irqbalance,也只是用到了1个CPU,12个核。
最后自己设定24条网卡中断队列对应24个核,效果最佳。。。。。。但你的情况就不一定一样啊。

 

原创粉丝点击