Locust.io中含/#/的请求被识别为/导致大量失败的问题
这个问题的核心是HTTP协议的片段标识符规则,咱们一步步拆解清楚:
问题根源
URL中#后面的部分叫做「片段标识符」,这部分内容是给浏览器用的,不会被发送到服务器。所以你写self.client.get("/#/bubblesu")时,Locust实际发给服务器的请求路径就是/——和login_page里的请求完全一样。
你的应用应该是个SPA(单页应用),/#/是前端路由的hash模式,服务器只返回首页的index.html,路由逻辑全在浏览器端的JS里处理。但Locust是纯HTTP客户端,不会执行JS,所以你以为在请求dashboard页面,实际拿到的还是首页内容,后续业务流程(比如依赖该页面的接口调用、业务校验)自然走不通,就出现了大量“失败”;但服务器返回的是200 OK,所以命令行没HTTP报错。
解决方案
根据你的测试需求,有两种实用处理方式:
1. 模拟真实用户的完整业务流程(推荐)
真实用户访问SPA的不同路由时,是先加载首页,然后前端JS根据路由调用对应的后端API。所以你需要在Locust里直接模拟这些API请求,而不是纠结前端路由的URL:
from locust import HttpLocust, TaskSet, task class UserBehavior(TaskSet): @task(2) def load_homepage(self): # 加载首页,获取基础资源 self.client.get("/") @task(1) def use_dashboard(self): # 先加载首页(模拟用户打开页面) self.client.get("/") # 模拟前端进入dashboard时调用的后端API,替换成你实际的接口路径 self.client.get("/api/dashboard/get-bubble-data") @task(1) def use_parents_page(self): self.client.get("/") # 模拟parents页面对应的后端接口,替换成实际接口路径 self.client.get("/api/parents/list") class WebsiteUser(HttpLocust): task_set = UserBehavior
2. 保留路由统计(仅用于区分业务场景)
如果你只是想在Locust的统计面板里区分不同的前端路由场景,不需要模拟API,可以给请求加上name参数自定义统计名称:
from locust import HttpLocust, TaskSet, task class UserBehavior(TaskSet): @task(2) def login_page(self): self.client.get("/") @task(1) def dashboard_page(self): # 实际请求还是/,但统计里显示为/#/bubblesu self.client.get("/", name="/#/bubblesu") @task(1) def parents_page(self): self.client.get("/", name="/#/pages/parents") class WebsiteUser(HttpLocust): task_set = UserBehavior
这样Locust会把这两个请求分开统计,方便你查看不同业务场景的性能数据,同时完全符合HTTP协议的规则。
额外提醒
如果你的应用可以配置为history模式(不带#的前端路由),也可以让后端服务器配置支持对应路由的跳转(比如Nginx配置try_files),然后直接用/bubblesu这类路径请求,但这需要后端的配合,不是Locust层面能单独解决的。
内容的提问来源于stack exchange,提问作者Paul Laguna

