Locust 实战指南:从入门到精通

实战案例:电商网站性能测试
让我们通过一个实际的电商网站性能测试案例来学习 Locust。
1. 测试场景设计
from locust import HttpUser, task, between
import random
class EcommerceUser(HttpUser):
wait_time = between(1, 3)
def on_start(self):
# 用户登录
self.client.post("/login", {
"username": "test_user",
"password": "test_pass"
})
@task(3)
def browse_products(self):
# 浏览商品列表
self.client.get("/products")
# 随机查看商品详情
product_id = random.randint(1, 100)
self.client.get(f"/products/{product_id}")
@task(1)
def add_to_cart(self):
# 添加商品到购物车
product_id = random.randint(1, 100)
self.client.post("/cart/add", {
"product_id": product_id,
"quantity": 1
})
2. 数据驱动测试
import csv
from locust import HttpUser, task, between
class DataDrivenUser(HttpUser):
wait_time = between(1, 2)
def on_start(self):
# 从CSV文件加载测试数据
self.test_data = []
with open('test_data.csv', 'r') as f:
reader = csv.DictReader(f)
self.test_data = list(reader)
@task
def test_with_data(self):
for data in self.test_data:
# 使用测试数据执行请求
self.client.post("/api/order", json=data)
实际应用场景
1. API 性能测试
class APIUser(HttpUser):
wait_time = between(0.1, 0.5)
@task
def test_api_endpoints(self):
# 测试多个API端点
endpoints = [
"/api/users",
"/api/products",
"/api/orders"
]
for endpoint in endpoints:
self.client.get(endpoint)
2. 登录系统测试
class LoginUser(HttpUser):
wait_time = between(1, 2)
@task
def test_login(self):
# 测试登录功能
self.client.post("/login", {
"username": "test_user",
"password": "test_pass"
})
性能测试报告分析
1. 关键指标解读
-
响应时间分布
- 50% 的请求在 100ms 内完成
- 90% 的请求在 500ms 内完成
- 99% 的请求在 1s 内完成
-
错误率分析
- 总请求数:10000
- 成功请求:9850
- 失败请求:150
- 错误率:1.5%
2. 性能瓶颈识别
-
数据库查询优化
# 优化前 def get_products(self): return Product.objects.all() # 优化后 def get_products(self): return Product.objects.select_related('category').all() -
缓存策略
from django.core.cache import cache def get_product_details(self, product_id): cache_key = f'product_{product_id}' result = cache.get(cache_key) if not result: result = Product.objects.get(id=product_id) cache.set(cache_key, result, 3600) return result
实战技巧
1. 测试数据准备
def generate_test_data():
products = []
for i in range(100):
products.append({
'name': f'Product {i}',
'price': random.randint(10, 1000),
'stock': random.randint(0, 100)
})
return products
2. 环境配置
# locust.conf
[locust]
host = http://example.com
users = 100
spawn-rate = 10
run-time = 1h
常见问题解决
1. 连接超时
class CustomHttpUser(HttpUser):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.client.timeout = 30 # 设置超时时间
2. 数据验证
@task
def validate_response(self):
response = self.client.get("/api/data")
assert response.status_code == 200
assert "expected_data" in response.json()
最佳实践总结
-
测试环境准备
- 使用独立的测试数据库
- 准备足够的测试数据
- 配置适当的监控工具
-
测试脚本编写
- 模拟真实用户行为
- 使用参数化测试数据
- 添加适当的断言
-
结果分析
- 关注关键性能指标
- 识别性能瓶颈
- 提出优化建议
高级特性与技巧
1. 自定义事件监听器
from locust import events
import logging
@events.request.add_listener
def on_request(request_type, name, response_time, response_length, **kwargs):
logging.info(f"Request: {name}, Response Time: {response_time}ms")
@events.test_start.add_listener
def on_test_start(**kwargs):
logging.info("Test is starting")
@events.test_stop.add_listener
def on_test_stop(**kwargs):
logging.info("Test is stopping")
2. 分布式负载测试
# master.py
from locust import HttpUser, task, between
from locust.clients import HttpSession
class DistributedUser(HttpUser):
wait_time = between(1, 3)
@task
def distributed_task(self):
self.client.get("/api/data")
# 启动命令
# locust -f master.py --master
# locust -f master.py --worker
3. 自定义负载形状
from locust import LoadTestShape
class CustomLoadShape(LoadTestShape):
time_limit = 600
spawn_rate = 20
def tick(self):
run_time = self.get_run_time()
if run_time < 300:
# 前5分钟线性增加用户数
return (int(run_time/10), self.spawn_rate)
elif run_time < 600:
# 后5分钟保持稳定
return (30, self.spawn_rate)
return None
性能测试场景示例
1. 高并发订单处理
class OrderProcessingUser(HttpUser):
wait_time = between(0.5, 2)
@task(3)
def create_order(self):
order_data = {
"items": [
{"product_id": random.randint(1, 100), "quantity": random.randint(1, 5)}
for _ in range(random.randint(1, 5))
],
"shipping_address": {
"street": "Test Street",
"city": "Test City",
"zip": "12345"
}
}
self.client.post("/api/orders", json=order_data)
@task(1)
def check_order_status(self):
order_id = random.randint(1, 1000)
self.client.get(f"/api/orders/{order_id}/status")
2. 文件上传测试
class FileUploadUser(HttpUser):
wait_time = between(1, 3)
@task
def upload_file(self):
files = {
'file': ('test.txt', 'Hello, World!', 'text/plain')
}
self.client.post("/api/upload", files=files)
监控与报告
1. 自定义指标收集
from locust import events
import time
class MetricsCollector:
def __init__(self):
self.response_times = []
def on_request(self, request_type, name, response_time, response_length, **kwargs):
self.response_times.append(response_time)
def get_statistics(self):
return {
'avg_response_time': sum(self.response_times) / len(self.response_times),
'max_response_time': max(self.response_times),
'min_response_time': min(self.response_times)
}
metrics = MetricsCollector()
events.request.add_listener(metrics.on_request)
2. 实时监控集成
from prometheus_client import start_http_server, Counter, Histogram
import time
# Prometheus metrics
REQUEST_COUNT = Counter('locust_request_count', 'Total requests')
RESPONSE_TIME = Histogram('locust_response_time', 'Response time in seconds')
@events.request.add_listener
def on_request(request_type, name, response_time, response_length, **kwargs):
REQUEST_COUNT.inc()
RESPONSE_TIME.observe(response_time / 1000.0)
故障排除与调试
1. 常见错误处理
class ErrorHandlingUser(HttpUser):
wait_time = between(1, 2)
@task
def handle_errors(self):
try:
response = self.client.get("/api/data")
if response.status_code != 200:
self.environment.runner.stats.log_error(
"request_failed",
f"Request failed with status {response.status_code}"
)
except Exception as e:
self.environment.runner.stats.log_error(
"request_exception",
str(e)
)
2. 调试技巧
import logging
from locust import events
# 设置详细日志
logging.basicConfig(level=logging.DEBUG)
# 添加请求日志
@events.request.add_listener
def log_request(request_type, name, response_time, response_length, **kwargs):
logging.debug(f"Request: {request_type} {name}")
logging.debug(f"Response Time: {response_time}ms")
logging.debug(f"Response Length: {response_length}")
性能优化建议
1. 测试脚本优化
class OptimizedUser(HttpUser):
# 使用连接池
connection_timeout = 30
network_timeout = 30
def on_start(self):
# 预热连接池
self.client.get("/")
@task
def optimized_request(self):
# 使用keep-alive连接
with self.client.get("/api/data", catch_response=True) as response:
if response.status_code == 200:
response.success()
else:
response.failure("Request failed")
2. 资源管理
class ResourceAwareUser(HttpUser):
def on_start(self):
# 初始化资源
self.session_data = {}
def on_stop(self):
# 清理资源
self.session_data.clear()
@task
def resource_aware_task(self):
# 使用资源池
with self.environment.resource_pool.acquire() as resource:
self.client.get("/api/data", headers={"X-Resource-ID": resource.id})
持续集成与自动化
1. CI/CD 集成
# locust_ci.py
import subprocess
import sys
def run_load_test():
# 运行负载测试
result = subprocess.run([
"locust",
"-f", "locustfile.py",
"--headless",
"--users", "100",
"--spawn-rate", "10",
"--run-time", "1m",
"--host", "http://example.com"
])
# 检查测试结果
if result.returncode != 0:
print("Load test failed!")
sys.exit(1)
print("Load test completed successfully!")
if __name__ == "__main__":
run_load_test()
2. 自动化报告生成
import json
from datetime import datetime
def generate_report(stats):
report = {
"timestamp": datetime.now().isoformat(),
"total_requests": stats.total_requests,
"failed_requests": stats.total_failures,
"average_response_time": stats.avg_response_time,
"max_response_time": stats.max_response_time,
"min_response_time": stats.min_response_time
}
with open("load_test_report.json", "w") as f:
json.dump(report, f, indent=2)
安全测试考虑
1. 认证测试
class SecurityTestUser(HttpUser):
wait_time = between(1, 2)
@task
def test_authentication(self):
# 测试无效凭证
self.client.post("/login", {
"username": "invalid_user",
"password": "invalid_pass"
})
# 测试SQL注入
self.client.post("/login", {
"username": "' OR '1'='1",
"password": "' OR '1'='1"
})
2. 压力测试安全措施
class SafeLoadTestUser(HttpUser):
def on_start(self):
# 设置请求头
self.client.headers.update({
"X-Load-Test": "true",
"X-Test-ID": "load-test-123"
})
@task
def safe_request(self):
# 添加速率限制
if self.environment.runner.stats.total_requests > 1000:
self.environment.runner.quit()
总结与最佳实践
-
测试环境准备
- 使用独立的测试环境
- 准备足够的测试数据
- 配置适当的监控工具
- 设置合理的测试参数
-
测试脚本编写
- 模拟真实用户行为
- 使用参数化测试数据
- 添加适当的断言
- 实现错误处理机制
-
性能分析
- 关注关键性能指标
- 识别性能瓶颈
- 提出优化建议
- 生成详细报告
-
持续改进
- 定期更新测试脚本
- 优化测试策略
- 完善监控机制
- 跟进性能改进
Locust 性能测试实战指南
222

被折叠的 条评论
为什么被折叠?



