3018 words, 9 mins
linux 性能优化学习第八周总结,本周是综合实战以及总结
服务器吞吐量下降
- 调大内核最大连接跟踪数 nf_conntrack.
- 调大php程序的工作进程数量
- 队列偏小,导致高并发时的丢包.
- 调大系统分配的临时端口号范围.
- CPU 占用过高,通过 perf 火焰图分析
- 配置系统的端口重用参数.
性能分析方法
系统监控法
USE法:
- Utilization(使用率): 表示资源用于服务的时间或容量百分比。100% 的使用率,表示容量已经用尽或者全部时间都用于服务
- Saturation(饱和度):表示资源的繁忙程度,通常与等待队列的长度相关。100% 的饱和度,表示资源无法接受更多的请求。
- Errors(错误率): 表示发生错误的事件个数。错误数越多,表明系统的问题越严重。
常用开源监控工具:
- Zabbix
- Nagios
- Prometheus + Grafana
- Netdata
应用监控
RED 法:
是 Weave Cloud 在监控微服务性能时,结合 Prometheus 监控,所提出的一种监控思路。即对微服务来说,监控它们的请求数(Rate)、错误数(Errors)以及响应时间(Duration)。所以,RED 方法适用于微服务应用的监控,而 USE 方法适用于系统资源的监控。
- 应用进程的资源使用情况: 比如进程占用的 CPU、内存、磁盘 I/O、网络等
- 应用程序之间调用情况:比如调用频率、错误数、延时等
- 应用程序内部核心逻辑的运行情况: 比如关键环节的耗时以及执行过程中的错误等
可以将指标整合进 Prometheus + Grafana,和系统资源进行统一监控
全链路跟踪:Zipkin + Jaeger + Pinpoint
日志监控
ELK 技术栈,即使用 Elasticsearch、Logstash 和 Kibana 这三个组件的组合。
- Logstash 负责对从各个日志源采集日志,然后进行预处理,最后再把初步处理过的日志,发送给 Elasticsearch 进行索引。
- Elasticsearch 负责对日志进行索引,并提供了一个完整的全文搜索引擎,这样就可以方便你从日志中检索需要的数据。
- Kibana 则负责对日志进行可视化分析,包括日志搜索、处理以及绚丽的仪表板展示等。
ELK 技术栈中的 Logstash 资源消耗比较大。所以,在资源紧张的环境中,我们往往使用资源消耗更低的 Fluentd,来替代 Logstash(也就是所谓的 EFK 技术栈)。
应用程序瓶颈
除了基本的系统配置优化,大多数的情况还是我们自己研发的应用程序导致的瓶颈。
我们希望自己的程序能抗住高并发,能支持高吞吐量,较低的错误率,响应时间足够快,占用资源尽量少。
一些性能问题原因:
- 多线程处理不当
- 死锁
- 算法复杂度高
很多情况下,系统资源瓶颈和应用程序瓶颈都是同一个问题导致的,所以没必要重复分析
性能问题的来源:
- 资源瓶颈跟系统资源瓶颈,本质是一样的。
- 依赖服务瓶颈,你可以使用全链路跟踪系统进行定位。
- 而应用自身的问题,你可以通过系统调用、热点函数,或者应用自身的指标监控以及日志监控等,进行分析定位。
性能优化方法
CPU 优化
CPU 性能优化的核心,在于排除所有不必要的工作、充分利用 CPU 缓存并减少进程调度对性能的影响。
- 第一种,把进程绑定到一个或者多个 CPU 上,充分利用 CPU 缓存的本地性,并减少进程间的相互影响。
- 第二种,为中断处理程序开启多 CPU 负载均衡,以便在发生大量中断时,可以充分利用多 CPU 的优势分摊负载。
- 第三种,使用 Cgroups 等方法,为进程设置资源限制,避免个别进程消耗过多的 CPU。同时,为核心应用程序设置更高的优先级,减少低优先级任务的影响。
内存优化
内存性能优化的核心,是解决可用内存不足、内存泄漏、Swap 过多、缺页异常过多以及缓存过多等等问题
- 第一种,除非有必要,Swap 应该禁止掉。这样就可以避免 Swap 的额外 I/O ,带来内存访问变慢的问题。
- 第二种,使用 Cgroups 等方法,为进程设置内存限制。这样就可以避免个别进程消耗过多内存,而影响了其他进程。对于核心应用,还应该降低 oom_score,避免被 OOM 杀死。
- 第三种,使用大页、内存池等方法,减少内存的动态分配,从而减少缺页异常。磁
磁盘和文件系统 IO 优化
- 第一种,也是最简单的方法,通过 SSD 替代 HDD、或者使用 RAID 等方法,提升 I/O 性能。
- 第二种,针对磁盘和应用程序 I/O 模式的特征,选择最适合的 I/O 调度算法。比如,SSD 和虚拟机中的磁盘,通常用的是 noop 调度算法;而数据库应用,更推荐使用 deadline 算法。
- 第三,优化文件系统和磁盘的缓存、缓冲区,比如优化脏页的刷新频率、脏页限额,以及内核回收目录项缓存和索引节点缓存的倾向等等。
- 除此之外,使用不同磁盘隔离不同应用的数据、优化文件系统的配置选项、优化磁盘预读、增大磁盘队列长度等,也都是常用的优化思路。
网络优化
从 Linux 的网络协议栈出发,针对每个协议层的工作原理进行优化
从内核资源和网络协议的角度来说,我们可以对内核选项进行优化:
- 你可以增大套接字缓冲区、连接跟踪表、最大半连接数、最大文件描述符数、本地端口范围等内核资源配额;
- 也可以减少 TIMEOUT 超时时间、SYN+ACK 重传数、Keepalive 探测时间等异常处理参数;
- 还可以开启端口复用、反向地址校验,并调整 MTU 大小等降低内核的负担。
从网络接口的角度来说,我们可以考虑对网络接口的功能进行优化:
- 你可以将原来 CPU 上执行的工作,卸载到网卡中执行,即开启网卡的 GRO、GSO、RSS、VXLAN 等卸载功能;
- 也可以开启网络接口的多队列功能,这样,每个队列就可以用不同的中断号,调度到不同 CPU 上执行;
- 还可以增大网络接口的缓冲区大小以及队列长度等,提升网络传输的吞吐量。
极限性能情况下(C10M):
- 你可以使用 DPDK 技术,跳过内核协议栈,直接由用户态进程用轮询的方式,来处理网络请求。同时,再结合大页、CPU 绑定、内存对齐、流水线并发等多种机制,优化网络包的处理效率。
- 你还可以使用内核自带的 XDP 技术,在网络包进入内核协议栈前,就对其进行处理。这样,也可以达到目的,获得很好的性能。
应用程序优化
在观察性能指标时,你应该先查看应用程序的响应时间、吞吐量以及错误率等指标,因为它们才是性能优化要解决的终极问题
- 第一,从 CPU 使用的角度来说,简化代码、优化算法、异步处理以及编译器优化等,都是常用的降低 CPU 使用率的方法,这样可以利用有限的 CPU 处理更多的请求。
- 第二,从数据访问的角度来说,使用缓存、写时复制、增加 I/O 尺寸等,都是常用的减少磁盘 I/O 的方法,这样可以获得更快的数据处理速度。
- 第三,从内存管理的角度来说,使用大页、内存池等方法,可以预先分配内存,减少内存的动态分配,从而更好地内存访问性能。
- 第四,从网络的角度来说,使用 I/O 多路复用、长连接代替短连接、DNS 缓存等方法,可以优化网络 I/O 并减少网络请求数,从而减少网络延时带来的性能问题。
- 第五,从进程的工作模型来说,异步处理、多线程或多进程等,可以充分利用每一个 CPU 的处理能力,从而提高应用程序的吞吐能力。
- 除此之外,你还可以使用消息队列、CDN、负载均衡等各种方法,来优化应用程序的架构,将原来单机要承担的任务,调度到多台服务器中并行处理。这样也往往能获得更好的整体性能。
分析性能问题的步骤
- 第一步,从性能瓶颈出发,根据系统和应用程序的运行原理,确认待分析的性能指标。
- 第二步,选出最合适的性能工具,然后了解并使用工具,从而更快观测到需要的性能数据。