尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Locust 常见问题深度解析:从故障排查到源码原理的 FAQ 实战指南

Locust 常见问题深度解析:从故障排查到源码原理的 FAQ 实战指南 Locust 常见问题深度解析从故障排查到源码原理的 FAQ 实战指南【免费下载链接】locustWrite scalable load tests in plain Python 项目地址: https://gitcode.com/gh_mirrors/lo/locust本文基于 Locust 官方 FAQ 文档docs/faq.rst逐条展开覆盖压测过程中最常见的疑难问题压测期间出现 5xx / 连接重置等错误如何定位、如何让每次任务迭代模拟新用户、如何控制 HTTP 请求头、跨域跳转后 Basic Auth 失效的解决方法、WSL 环境下运行 Docker、自定义 Web UI 访问路径以及 Web UI 显示 0 RPS 的事件钩子机制。每个问题都会结合当前仓库的源码实现给出可验证的依据帮助你不仅“知道怎么做”还能理解“为什么 Locust 是这样设计的”。压测期间出现 5xx、Connection aborted、Connection reset by peer 等错误怎么办这是 FAQ 中排第一的高频问题。官方 FAQ 给出的结论非常直接查看你的服务器日志。如果低负载时系统工作正常那么几乎可以肯定这不是 Locust 的问题而是你正在测试的系统的自身问题。换句话说当你在 Locust 统计界面看到大量失败请求时第一反应不应是怀疑压测工具而应检查被测系统的日志、容量瓶颈和资源配置。这一点在源码层面可以得到印证。Locust 的 HTTP 客户端在发送请求时使用了一个“安全模式”包装方法 HttpSession._send_request_safe_modedef _send_request_safe_mode(self, method, url, **kwargs) - Response: Send an HTTP request, and catch any exception that might occur due to connection problems. try: return super().request(method, url, **kwargs) except (MissingSchema, InvalidSchema, InvalidURL): raise except RequestException as e: return ResponseContextManager(e)从源码结构看ConnectionError、ProtocolError(Response ended prematurely)等所有RequestException子类包括 “Connection reset by peer”“Connection aborted” 这类底层套接字错误都会被捕获并包装成一个 ResponseContextManager 实例其status_code被设为 0随后作为失败请求上报给统计系统。这正是你在 Web UI 的 Exceptions/Status Codes 页签下能看到大量连接类异常的直接原因——Locust 只是如实记录了“请求失败了”而失败根因通常在被测系统或网络路径上。排查建议先看服务端日志确认错误时间点是否与压测高峰重合降低用户数复跑如果低负载下不复现基本可锁定为被测系统的容量问题检查是否存在连接数上限、超时配置、防火墙/负载均衡器对长连接的策略等基础设施层面的限制。如何让每次任务迭代都像新用户一样清除 CookiesFAQ 建议在任务末尾调用self.client.cookies.clear()使下一次任务迭代对被测系统而言就像一个新的用户。from locust import HttpUser, task, between class WebsiteUser(HttpUser): wait_time between(1, 5) task def browse(self): self.client.get(/page) # ... 其他请求 ... self.client.cookies.clear() # 结束本次“会话”下一次迭代视为新用户为什么需要这样做Locust 的self.client是一个 HttpSession 类其类文档明确说明它负责“执行 Web 请求并在请求之间保持会话cookies以便能够登录和登出网站”。也就是说HttpSession天然继承requests.Session的 cookie 保持行为——同一 User 实例的所有请求共享同一个 Cookie Jar登录态会被自动延续。如果你的测试场景要求“每一轮操作都从全新会话开始”例如反复验证匿名注册流程就必须在任务边界显式清空 cookies否则被测系统始终会把你识别为同一个已登录/已访问过的用户。如何控制 HTTP 请求头及其他请求细节FAQ 给出的核心结论HttpUser的client继承自 requests 库requests 的绝大多数参数和方法在 Locust 中都可以直接使用。因此当你需要控制 headers、timeout、verify、proxies 等细节时先查 requests 的文档和常见问答即可。这一点可以从 HttpSession 类定义 得到确认——它就是requests.Session的子类请求方法get、post、put、patch、delete、head、options、request全部沿用 requests 签名。在此基础上Locust 只额外引入了两个专有的可选参数见 HttpSession.request参数作用name用自定义标签替代 URL 路径作为 Locust 统计中的名称可将多个不同 URL 归并到同一条统计记录catch_response使请求返回上下文管理器可在响应内容不符合预期时手动把请求标记为失败即使状态码是 2xx或反之把 5xx 标记为成功此外还有两个 requests 本身不具备的行为差异写脚本时需要注意URL 可以只写路径。HttpSession._build_url会在 URL 不是绝对地址时自动拼接base_url即 User 的host属性或--host命令行参数所以self.client.get(/page)是合法且推荐的写法部分方法默认跟随重定向。从 HttpSession.get 源码可以看到kwargs.setdefault(allow_redirects, True)GET/OPTIONS默认跟随 30x 跳转而HEAD默认不跟随POST等方法则完全交给调用方决定。完整的 Locust 特有请求 API 用法catch_response、rename_request分组等可以参考 docs/api.rst 与示例 examples/basic.py、examples/response_validations.py。重定向之后 Basic AuthAuthorization 头失效怎么办FAQ 指出这是requests的一个安全机制在发生跨域跳转时requests 会主动丢弃 Authorization 头。这个场景在测试 SSO单点登录时尤为典型——SSO 通常部署在另一个域名上并通过多次 30x 重定向完成认证流程。由于allow_redirectsTrue是 requests 的默认行为Locust 的解决办法是关闭自动重定向手动逐跳跟随跳转并在每一跳重新注入 Authorization 头。FAQ 中的示例代码response self.client.post(url..., allow_redirectsFalse) while location in response.headers: response self.client.get( response.headers[location], allow_redirectsFalse, headers{ Authorization: XXX, # 每一跳都重新注入认证头 }, )这个方案在源码层面也是自洽的如前文所述self.client的请求方法与 requests 完全同签名allow_redirects作为 kwargs 会被原样透传到super().request()因此手动控制重定向没有任何障碍。如何基于浏览器录制的会话生成 Locust 文件FAQ 推荐的工具是har2locust先用浏览器插件或抓包工具把一次完整的浏览会话录制为 HAR 文件再用 har2locust 将其转换为 Locustfile 骨架之后按需改造即可。这是把“人工点一遍”快速转化为可重复压测脚本的常用路径。如何在 WSLWindows 10中运行 Locust 的 Docker 容器FAQ 说明在 Windows 的 WSL 中运行 Locust Docker 容器需要比标准docker run命令多做一步——把 locustfile 复制到一个 Windows 盘符路径下的目录并用该目录而不是 WSL 原生路径作为挂载源$ mkdir /c/Users/[YOUR_Windows_USER]/Documents/Locust/ $ cp ~/path/to/locusttest1.py /c/Users/[YOUR_Windows_USER]/Documents/Locust/ $ docker run -p 8089:8089 -v /c/Users/[YOUR_Windows_USER]/Documents/Locust/:/mnt/locust locustio/locust -f /mnt/locust/locusttest1.py补充说明FAQ 示例中镜像 tag 固定为较旧的1.3.1实际使用时可以替换为当前发布的 tag不指定 tag 即拉取 latest对于非 WSL 的纯 Windows 环境docs/running-in-docker.rst 指出docker run有时会报错建议改用 bind mount 写法docker run -p 8089:8089 --mount typebind,source$pwd,target/mnt/locust locustio/locust -f /mnt/locust/locustfile.py。如何在自定义端点子路径上运行 Locust Web UIFAQ 给出的改造思路以挂载到/locust前缀为例给 locust/web.py 中所有app.route定义加上/locust前缀创建 Flask 应用时指定静态资源路径app Flask(__name__, static_url_path/locust)同步修改前端模板中静态资源的位置引用例如 favicon 的链接写法link relshortcut icon href{{ url_for(static, filenameimg/favicon.ico) }} typeimage/x-icon/。需要注意的版本差异FAQ 的这段指引对应的是早期 Flask Jinja 模板的 Web UI 布局。从当前仓库源码看locust/web.py 中应用已改为app Flask(__name__)静态路径通过self.app.static_url_path /assets/设置业务路由则注册在带url_prefixweb_base_path的 Blueprint 上仓库中也不再有locust/templates/index.htmlWeb UI 已经重构为位于 locust/webui/ 的预构建 React 应用。因此如果你基于当前代码做自定义端点改造具体落点应与上述源码结构对齐——FAQ 描述的“统一路由前缀 修正静态资源路径”这一核心思路依然成立但实现位置需要按当前版本源码调整。Web UI 不显示任务运行、显示 0 RPS 的原因事件钩子机制这是 FAQ 中信息量最大的条目。官方解释Locust 只有在你告诉它你在做什么时才知道你在做什么。Locust 提供了一组 Event Hooks事件钩子用来告知 Locust 你的代码里发生了什么。如果你使用HttpUser并通过self.client发 HTTP 请求相应的事件通常会被自动触发你不需要额外工作除非你想覆盖默认事件。如果你使用纯User或者使用HttpUser但没有通过self.client发请求Locust 就不会替你触发事件——你必须自己触发事件。源码层面的调用链是这样的HttpUser.init在实例化时创建HttpSession并把request_eventself.environment.events.request传入客户端self.client HttpSession( base_urlself.host, request_eventself.environment.events.request, userself, pool_managerself.pool_manager, )每次self.client.get/post/...完成请求后HttpSession.request 会收集request_type、name、response_time、response_length、exception等元数据最终通过 ResponseContextManager._report_request 调用self._request_event.fire(**self.request_meta)触发request事件统计系统stats监听request事件并累计 RPS、响应时间等指标——这正是 Web UI 数据的来源。因此只要你绕过了self.client比如用httpx、数据库驱动、paho-mqtt等自写客户端RPS 自然显示为 0。解决方案是自己向request事件上报。locust/event.py 中的 EventHook 提供了两个关键能力fire(**kwargs)手动触发事件request事件需要携带request_type、name、response_time、response_length、exception等参数详见 Events.request 文档measure(request_type, name, ...)一个上下文管理器自动计算响应时间并在异常时标记失败大幅简化自写客户端的上报代码task def query_database(self): with self.environment.events.request.measure(db, SELECT /users) as meta: # 在这里执行你想被计量的数据库查询 ...仓库中的非 HTTP 客户端示例如 locust/contrib/ 下的 mongodb、mqtt、postgres 等 contrib 模块都遵循了同样的事件上报模式可以作为自写客户端的参照。长时间压测时 HTML 报告被失败请求占满FAQ 对此的指引比较简短指向了社区 issue 列表中的一个已知问题。由于当前仓库文档仅保留了问题编号引用而没有展开讨论具体成因与修复状态这里不建议给出未经证实的技术解释——如果你在长时间运行的测试中遇到 HTML 报告异常建议直接查阅 Locust 社区 issue 列表确认最新状态。其他问题的求助渠道FAQ 最后列出了三个社区渠道Locust 的 Discord 服务器——实时问答Locust 的 GitHub issue 列表——很多“问题/误解”其实早已以 issue 形式被提出并解答提问前值得先搜索Stack Overflow 的 locust 标签——长期沉淀的问答库。另外FAQ 也欢迎社区贡献如果你遇到了 FAQ 没覆盖的问题并自行解决了可以把它补充到 docs/faq.rst 中。小结Locust 的 FAQ 虽然篇幅不长但每一条目都指向一类典型的压测工程问题其背后都有清晰的源码机制支撑常见问题核心结论源码依据压测中出现 5xx / 连接错误先查被测系统日志大概率不是 Locust 的问题locust/clients.py 将连接异常包装为失败请求上报让每次迭代模拟新用户任务末尾调用self.client.cookies.clear()HttpSession 继承 requests.Session 并跨请求保持 cookies控制请求头/参数requests 的 API 基本原样可用另加name、catch_response两个 Locust 参数HttpSession.request重定向后 Basic Auth 失效关闭allow_redirects手动逐跳注入 Authorization 头HttpSession.get 默认跟随重定向WSL 中运行 Docker挂载 Windows 盘符路径而非 WSL 路径docs/running-in-docker.rst 提供 bind mount 变体Web UI 显示 0 RPS事件钩子是统计的唯一入口绕开self.client就要自行 fire 事件locust/event.py、locust/user/users.py掌握这些机制后再遇到统计不符预期、认证流程卡住或环境配置报错的情况就能快速判断问题出在压测脚本、Locust 事件链路还是被测系统本身并沿着本文给出的源码路径继续深挖。【免费下载链接】locustWrite scalable load tests in plain Python 项目地址: https://gitcode.com/gh_mirrors/lo/locust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表