写点什么

浅谈高并发系统性能调优

  • 2019-11-20
  • 本文字数:4048 字

    阅读完需:约 13 分钟

浅谈高并发系统性能调优

今天带来的是一个篇长文,主要讲解高并发系统架构指标及调优测试经验,希望能对您的研究有所帮助。本文最先发布于 OpsDev,转载已获取作者授权。


高并发系统的优化一直以来都是一个很重要的问题,下面基于笔者的实践,和大家聊聊高并发系统的一些调优和优化策略。

1 系统性能的关键指标

  • 吞吐量(Throughput)系统单位时间内处理任务的数量

  • 延迟(Latency)系统对单个任务的平均响应时间


一般来说,考量一个系统的性能主要看这两个指标。而这两个指标之间又存在着一些联系:对于指定的系统来说,系统的吞吐量越大,处理的请求越多,服务器就越繁忙,响应速度就会慢下来;而延迟越低的系统,能够承载的吞吐量也相应的更高一些。


一方面,我们需要提高系统的吞吐量,以便服务更多的用户,另一方面我们需要将延迟控制在合理的范围内,以保证服务质量。

2 系统性能测试

  • 业务场景

  • 对于不同的业务系统,可以接受的延迟(Latency)也有所不同,例如邮件服务可以忍受的延迟显然要比 Web 服务高得多,所以首先我们需要根据业务场景的不同来定义理想的 Latency 值。

  • 测试工具

  • 我们需要一个能够制造高吞吐的工具来测试系统的性能,本文中使用的 Tsung,它是一个开源的支持分布式的压力测试工具,它功能丰富,性能强大,配置简单,并支持多种协议(HTTP、MySQL、LDAP、MQTT、XMPP 等)。

  • 测试流程

  • 测试的过程中需要不断加大吞吐量,同时注意观察服务端的负载,如果负载没有问题,那就观察延迟。一般这个过程需要反复很多次才能测出系统的极限值,而每次测试消耗的时间也比较长,需要耐心一些。

3 通用的系统参数调优

Linux 内核默认的参数考虑的是最通用的场景,不能够满足高并发系统的需求。

4 服务器参数调优

编辑文件/etc/sysctl.conf,添加以下内容:


fs.nr_open = 100000000  fs.file-max = 100000000
复制代码


关于这两项配置的含义可以查看系统手册:



可以看到 file-max 的含义:它是系统所有进程一共可以打开的文件数量,它是系统级别的,因此应该尽量将它调的大一些,这里将它修改为一亿。 这里说到需要增大/proc/sys/fs/inode-max 的值,但是执行如下命令时发现没有该配置项:


$ cat /proc/sys/fs/inode-max  cat: /proc/sys/fs/inode-max: No such file or directory
复制代码


再看 inode-max 说明:



可以看到有的系统中没有这个参数,所以先不管了。


对于 nr_open,系统手册里没有找到关于它的定义,不过我们可以参考kernel文档


nr_open:      This denotes the maximum number of file-handles a process can      allocate. Default value is 1024*1024 (1048576) which should be      enough for most machines. Actual limit depends on RLIMIT_NOFILE      resource limit.
复制代码


可以看到 nr_open 的描述与 file-max 十分相近,不仔细看几乎分辨不出区别。重点在于,file-max 是对所有进程(all processes)的限制,而 nr_open 是对单个进程(a process)的限制。这里给出了 nr_open 的默认值:


1024*1024 = 1048576


编辑文件/etc/security/limits.conf,添加如下内容:


编辑文件/etc/sysctl.conf,添加以下内容:



    关于这两项配置的含义可以查看系统手册:



    这里的意思很明确:hard 意为硬资源限制:一旦被 superuser 设置后不能增加;soft 为软资源设置:设置后在程序运行期间可以增加,但不能超过 hard 的限制。程序读取的是 soft,它是一个告警值。 nofile 意为用户打开最大文件描述符数量,在 Linux 下运行的网络服务器程序,每个 tcp 连接都要占用一个文件描述符,一旦文件描述符耗尽,新的连接到来就会返回"Too many open files"这样的错误,为了提高并发数,需要提高这项配置的数值。


    这里有一点需要特别注意,而手册里面也没有细说:在 CentOS7 下(其他系统还未测试过),nofile 的值一定不能高于 nr_open,否则用户 ssh 登录不了系统,所以操作时务必小心:可以保留一个已登录的 root 会话,然后换个终端再次尝试 ssh 登录,万一操作失败,还可以用之前保留的 root 会话抢救一下。


    修改完毕执行:


    # sysctl -p
    复制代码


    通过以上,我们修改了/etc/security/limits.conf 和/etc/sysctl.conf 两个配置文件,它们的区别在于 limits.conf 是用户层面的限制,而 sysctl.conf 是针对整个系统层面的限制。

    5 压测客户机参数调优

    对于压测机器来说,为了模拟大量的客户端,除了需要修改文件描述符限制外,还需要配置可用端口范围,可用端口数量决定了单台压测机器能够同时模拟的最大用户数量。


    • 文件描述符数量:修改过程同服务器

    • 可用端口数量:1024 以下的端口是操作系统保留的,我们可用的端口范围是 1024-65535,由于每个 TCP 连接都要用一个端口,这样单个 IP 可以模拟的用户数大概在 64000 左右 修改/etc/sysctl.conf 文件,添加如下内容:


    net.ipv4.ip_local_port_range = 1024 65535
    复制代码


    修改完毕执行:


    # sysctl -p
    复制代码


    需要注意的是,服务器最好不要这样做,这是为了避免服务监听的端口被占用而无法启动。如果迫于现实(例如手头可用的机器实在太少),服务器必须同时用作压测机器的话,可以将服务监听端口添加到 ip_local_reserved_ports 中。下面举例说明:


    修改/etc/sysctl.conf 文件,添加如下内容:


    net.ipv4.ip_local_reserved_ports = 5222, 5269, 5280-5390
    复制代码


    修改完毕执行:


    # sysctl -p
    复制代码


    TCP/IP 协议栈从 ip_local_port_range 中选取端口时,会排除 ip_local_reserved_ports 中定义的保留端口,因此就不会出现服务端口被占用而无法启动的情况。

    6 程序调优

    对于不同的业务系统,需要有针对性的对其进行调优,本文中测试的目标服务使用 Erlang/OTP 写就,Erlang/OTP 本身带有许多的限制,对于一般场景来说这些默认的设置是足够的;但是为了支持高并发,需要对 Erlang 虚拟机进行一些必要的参数调优,具体可以参考官方性能指南

    7 服务程序参数调优

    进程(process)数量

    Erlang 虚拟机默认的进程数量限制为 2^18=262144 个,这个值显然是不够的,我们可以在 erl 启动时添加参数+P 来突破这个限制


    $ erl +P 10000000
    复制代码


    需要注意的是:这样启动,erlang 虚拟机的可用进程数量可能会比 10000000 大,这是因为 erlang 通常(但不总是)选择 2 的 N 次方的值作为进程数量上限。

    原子(atom)数量

    Erlang 虚拟机默认的原子数量上限为 1048576,假如每个会话使用一个原子,那么这个默认值就不够用了,我们可以在 erl 启动时添加参数+t:


    $ erl +t 10000000
    复制代码


    从另一个角度来说,我们在编写 Erlang 程序时,使用原子需要特别小心:因为它消耗内存,而且不参与 GC,一旦创建就不会被移除掉;一旦超出原子的数量上限,Erlang 虚拟机就会 Crash,参见 How to Crash Erlang


    端口(port)数量 端口提供了与外部世界通讯的基本机制(这里的端口与 TCP/IP 端口的概念不同,需要注意区别),每个 Socket 连接需要消耗 1 个端口,官方文档里面说默认端口上限通常是 16384,但根据实测,Linux 系统默认为 65536,Windows 系统默认为 8192,无论多少,在这里都是需要调整的:在 erl 启动时添加参数+Q Number,其中 Number 取值范围是[1024-134217727]:


     $ erl +Q 10000000
    复制代码

    8 压测脚本调优

    压测工具使用 Tsung。Tsung 支持多种协议,有着丰富的功能,并且配置简单灵活。下面是几点需要注意的地方:

    内存

    对于单个 Socket 连接来说消耗内存不多,但是几万甚至几十万个连接叠加起来就非常可观了,配置不当会导致压测端内存成为瓶颈。


    • TCP 发送、接收缓存 Tsung 默认的 TCP/UDP 缓存大小为 32KB,本例中我们测试的服务采用 MQTT 协议,它是一种非常轻量级的协议,32KB 还是显得过大了,我们将它设置为 4KB 大小就足够了:


    <option name="tcp_snd_buffer" value="4096"></option>  <option name="tcp_rcv_buffer" value="4096"></option>
    复制代码


    • Tsung 能够让模拟用户的进程在空闲时间(thinktime)进入休眠,用以降低内存消耗,默认空闲 10 秒触发,我们可以将它降低到 5 秒:


    <option name="hibernate" value="5"></option>
    复制代码

    IO

    • 不要启用 dumptraffic,除非用于调试,因为它需要将客户机和服务器往来的协议写入磁盘日志中,是一个 IO 开销非常大的行为。笔者曾经遇到过一次这样的问题,测试部门的同事使用 JMeter,压测过程中,服务端一直处于较低的负载,但 JMeter 最终得出的压测报告却包含很多超时错误。经过仔细排查,才定位到原来是压测端默认开启了 debug 日志,海量的 debug 日志生生拖垮了压测机器。所以遇到这种情况时,可以先检查一下压测端配置是否正确。


    <tsung loglevel="error" dumptraffic="false" version="1.0">
    复制代码


    日志等级要调高一些,日志等级过低会打印很多无用信息:一方面会加大 IO 开销,另一方面会让有用的 ERROR 信息淹没在海量的调试日志中。


    如果 Tsung 从 CSV 文件读取用户名密码,那么该 CSV 文件不能过大,否则读取该 CSV 将会变成一个极其耗时的操作,特别是当压测程序需要每秒产生大量用户时。

    网络

    有时候为了避免网络拥塞,需要限制压测客户机的带宽,使流量以比较平滑的速率发送和接收。


    <option name="rate_limit" value="1024"></option>
    复制代码


    其采用令牌桶算法(token bucket),单位 KB/s,目前只对流入流量有效。

    9 定位系统性能瓶颈

    当系统吞吐和延迟上不去时,首先需要定位问题,而不是急于修改代码。


    常见的性能瓶颈包括 CPU/内存/磁盘 IO/网络带宽等,其中每一项都有一到多个简单实用的工具: 对于 CPU 和内存,我们只要使用 top 就可以了;对于磁盘 IO,可以用 iotop 或 iostat;对于网络带宽,可以使用 iftop。


    如果依然没能定位到问题,可能系统配置不当,参考通用的系统参数调优。


    最后检查代码是否有单点瓶颈,例如程序被阻塞了:在笔者实测过程中,发现每个用户创建会话进程都需要对同一个 supervisor 发起同步请求,同时登录的用户数量很大时,这些同步请求会排队,甚至引发超时。

    10 结束语

    以上就是笔者做压力测试时遇到的一些问题以及应对办法,鉴于笔者水平有限,错漏难免。抛砖引玉,欢迎交流指正。


    本文转载自公众号 360 云计算(ID:hulktalk)。


    原文链接:


    https://mp.weixin.qq.com/s/4LclaIGDBj4y6xZQRFiDeg


    2019-11-20 17:101678

    评论

    发布
    暂无评论
    发现更多内容

    建信信托真的可靠吗?投资者含泪控诉

    鳄鱼视界

    【从零开始学爬虫】采集全国历史天气数据

    前嗅大数据

    数据采集 爬虫软件 爬虫教程 爬虫入门 爬虫入门教程

    女生通过java编程学习好找工作吗?

    小谷哥

    备受企业青睐的华为云CDN优势到底在哪?

    路过的憨憨

    华为云CDN,助力安全企业下载服务,更好提升用户体验

    路过的憨憨

    既要速度与激情,也要稳定和安全,华为云CDN让你速度和安全兼得

    路过的憨憨

    恭喜 KubeVela 获得中国开源云联盟 2022 “优秀开源项目”

    阿里巴巴云原生

    阿里云 开源 云原生 KubeVela

    惊喜来袭!阿里内部Java开发成长手册(2022纯享版)开源

    程序知音

    Java 阿里 java面试 后端技术 Java面试八股文

    MonographDB获得IT168“2022年度创新产品奖”

    极客天地

    华为云CDN加速服务,引领企业数字化发展潮流!

    路过的憨憨

    阿里云弹性预测 AHPA:助力厨芯科技降本增效

    阿里巴巴云原生

    阿里云 云原生 弹性预测

    2022“易观之星”奖项公布,聚焦数字经济,助力数智创新

    易观分析

    金融 易观 颁奖

    大数据培训后的就业因素有哪些

    小谷哥

    前端开发培训机构有什么推荐?

    小谷哥

    大数据培训学习有前途吗?

    小谷哥

    读书|我的2022年度阅读推荐

    MavenTalker

    推荐书单

    华为云CDN提升网站响应速度,让下载快人一步

    路过的憨憨

    架构中实时引擎与离线渲染的主要优势

    3DCAT实时渲染

    Unity 渲染 实时渲染 AEC

    开源全球公司贡献 49 名,涛思数据荣登 2022 中国开发者影响力年度榜单

    TDengine

    tdengine 时序数据库

    腾讯云在中国公有云开发和基础设施平台分析师报告中入选领导者阵营

    科技热闻

    编程培训后程序员怎么提升自身开发水平?

    小谷哥

    一个深度学习框架的年度报告

    MegEngineBot

    深度学习 年终总结 MegEngine

    Databend in 2022

    Databend

    什么是3D可视化,为什么要使用3D可视化

    3DCAT实时渲染

    Unity 3D渲染 3D可视化

    2022年最全大厂面试真题解析:java集合+spring+并发编程+MyBatis

    钟奕礼

    程序员 Java 面试 Java、 java 编程

    对标阿里P7:高并发+Nginx+微服务+消息中间件+Netty+Redis+MySQL

    程序知音

    Java 数据库 JVM 高并发 后端技术

    【喜报】OpenCloudOS 荣获2022 中国技术力量年度榜单「十大开源新锐项目」

    腾源会

    开源 opencloudOS

    Flink Shuffle 3.0: Vision, Roadmap and Progress

    Apache Flink

    大数据 flink 实时计算

    模块二作业-分析微信朋友圈的高性能复杂度

    Geek_e3a35c

    数据报告 | 美国民众健康状况和医疗需求研究报告

    前嗅大数据

    大数据 数据分析 数据报告

    浅谈高并发系统性能调优_文化 & 方法_OpsDev- 杨玉东_InfoQ精选文章