如何编写Nginx+Locust分布式压测脚本?

来源:网站建设教程作者:天穹小白头衔:草根站长
导读:本期聚焦于天穹小白创作的《如何编写Nginx+Locust分布式压测脚本?》,敬请观看详情。单机Locust压测在模拟数万并发时,CPU和网络开销经常先于目标服务到达瓶颈,导致测试数据失真。把Locust改成主从分布式模式,再配合Nginx反向代理统一入口,能有效分散施压节点压力。本文围绕Nginx与Locust的整合过程,说明如何编写Locust任务脚本、搭建主从节点、配置Nginx负载均衡,以及执行分布式压测的具体命令。通过一个HTTP接口压测示例,展示用户任务中wait_time、权重、@task装饰器的用法,并给出Nginx的proxy_pass与upstream配置片段。文章还会分析master与worker之间的通信机制,以及压测过程中需要注意的参数一致性、结果聚合与常见报错处理,帮助读者快速搭建一套稳定的分布式压测环境。

将Nginx与Locust结合进行分布式压测,核心思路是让多个Locust worker节点向同一个Nginx入口发起请求,由Nginx将流量反向代理到后端服务,从而模拟更接近真实用户访问路径的压力场景。这种架构下,Locust master节点负责协调任务分配和统计结果,worker节点各自运行压测脚本,Nginx则作为统一接入层承担连接分发。接下来从脚本编写、节点配置到执行命令逐一展开。

如何编写Nginx+Locust分布式压测脚本?

一、Locust分布式压测脚本的核心写法

Locust的压测脚本通常是一个Python文件,继承HttpUser类并定义任务。分布式模式下,master节点不执行任务,只负责收集worker上报的数据,因此脚本需要保证所有worker加载的代码一致。下面是一个针对HTTP接口的Locustfile.py示例,包含用户行为模拟、等待时间和任务权重。

from locust import HttpUser, task, between

class ApiUser(HttpUser):
    wait_time = between(1, 3)

    @task(3)
    def get_articles(self):
        self.client.get("/api/articles", name="获取文章列表")

    @task(1)
    def create_order(self):
        payload = {"product_id": 101, "quantity": 1}
        self.client.post("/api/orders", json=payload, name="创建订单")

这段代码中,@task(3)表示get_articles被执行的权重是3,create_order权重是1,最终每个用户实例会更频繁地请求文章列表接口。wait_time控制两次任务之间的等待时间,这里设为1到3秒随机。name参数用于在统计报告中聚合不同的URL,避免路径参数不同导致结果分散。分布式执行时,每个worker会按照相同的权重比例生成请求,master汇总后得到总体吞吐量。

如果需要模拟登录态,可以在on_start方法中先调用登录接口并保存Cookie。由于Locust的HttpUser底层封装了requests.Session,Cookie会自动在后续请求中携带。编写时还要注意不要在脚本中使用全局可变状态,因为master和worker加载的是同一份代码,但进程空间独立,全局变量不会跨节点同步。可以通过os.environ或命令行参数来区分节点角色,不过Locust官方已经通过--master和--worker选项处理了角色分配,脚本不用额外判断。

二、Nginx作为统一入口的负载均衡配置

在分布式压测结构中,Nginx可以放在Locust与后端服务之间,也可以作为后端服务的前置代理。如果目标是压测Nginx本身或经过Nginx到达应用,那么Locust请求地址应指向Nginx监听端口。Nginx配置的关键是upstream定义和proxy_pass转发。下面给出一个简单示例,假设后端有两个应用实例,Nginx监听80端口并分发流量。

upstream backend_app {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    keepalive 64;
}

server {
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://backend_app;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

这个配置将发往Nginx 80端口的请求轮询转发到两个后端节点,keepalive 64表示与后端保持64个长连接,降低TCP握手开销。对于压测场景,如果后端服务处理能力较强,而Nginx本身成为瓶颈,可以适当调整worker_processes和worker_connections。在压测开始前,建议先单独测试Nginx的静态页面返回能力,确认其不是误判的瓶颈点。

如果希望模拟不同路径的流量分配,可以利用Nginx的location匹配规则。例如将/api/articles转发到一组后端,将/api/orders转发到另一组,再配合Locust脚本中的不同任务权重,使压力更符合线上业务分布。需要注意的是,当使用proxy_pass时,默认会修改请求头中的Host为后端地址,这可能导致后端应用按错误域名处理。示例中的proxy_set_header Host $host就是保留原始Host,很多Web框架依赖该头进行路由匹配。配置完成后执行nginx -t检查语法,再执行nginx -s reload生效。

三、启动分布式Locust并执行压测

分布式Locust的启动分为master和worker两个角色。首先在控制机上启动master,命令如下。

python -m locust -f locustfile.py --master --host=http://nginx地址或IP

然后在每台worker机器上执行类似命令,指定master节点的IP地址。worker可以是多台物理机,也可以在同一台机器上开启多个进程,但要注意CPU核心数和网络带宽限制。

python -m locust -f locustfile.py --worker --master-host=192.168.1.100 --host=http://nginx地址或IP

启动成功后,打开Locust的Web界面,通常为http://master-ip:8089。在界面中设置并发用户数和每秒启动速率,点击开始即可。master会把任务参数下发给所有worker,worker执行脚本时客户端请求统一指向Nginx地址。压测过程中可以实时查看RPS、响应时间百分位数和错误率。如果某些worker连接master失败,需要检查防火墙是否放行5557和5558端口,以及master的--web-port是否冲突。

命令行无界面模式也常用于CI流程,例如通过--headless --run-time 10m --users 2000 --spawn-rate 100执行一次10分钟的压测。这种方式便于把结果导出为CSV或接入监控。另外,所有worker节点上的Locust版本必须一致,否则可能出现协议不兼容导致统计异常。压测结束后,可以下载报告或使用--csv参数自动保存统计数据。

四、常见问题与性能调优建议

第一个常见问题是worker节点资源打满但RPS上不去。此时应检查Nginx的worker_connections是否足够,以及后端应用是否已经达到处理上限。可以通过nginx -T查看生效配置,确认没有因为默认的1024连接数限制导致排队。增大Nginx的worker_processes为CPU核心数,并调整worker_connections到合适值,例如events { worker_connections 4096; }。同时,后端应用的连接池大小、数据库连接数也需要同步提升,避免刚过Nginx就卡在应用层。

第二个问题是Locust的RPS统计与后端实际日志不一致。这是因为Locust统计的是客户端发起请求到收到响应的时间,而Nginx和后端日志可能只记录接入时间。如果Nginx有重试或长连接复用,数量会有轻微差异。排查时可以在Nginx的access_log中记录request_time和upstream_response_time,对照Locust的报告定位延迟发生在哪一层。

第三个问题是压测脚本中使用了同步阻塞操作。Locust基于gevent协程,如果任务函数里包含time.sleep等阻塞调用,会阻塞整个worker的协程调度,导致并发能力急剧下降。应使用gevent.sleep或直接依赖wait_time。对于数据库查询等IO操作,可以考虑使用异步驱动或放到线程池中执行,但这会引入额外的复杂度,一般情况下HTTP压测不需要这样做。

还有一点是压测数据清理。分布式压测会产生大量真实或模拟数据,如果后端是生产环境,务必先确认数据隔离。测试环境也要在压测后清理测试订单、用户等记录,避免影响后续功能验证。对于只读接口,压测风险较低,但写接口要考虑幂等性和数据回滚。

NginxLocust分布式压测修改时间:2026-08-22 00:11:09

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。