如何使用Python进行网站负载测试

想象一下,你有一个新的网络应用程序,并且你知道它在小范围用户群体中表现良好。但是,如果流量增加超出预期负载,你的应用程序将如何响应?使用Python对你的网络应用程序进行负载测试吧!

在本文中,你将学习如何通过模拟数百个用户同时访问你的应用程序来进行负载测试。

继续阅读,开始对网站进行负载测试吧!

先决条件

本教程将进行实际演示。如果你想跟着做,请确保你具备以下条件:

设置静态网站

在针对网站运行负载测试之前,首先必须设置一个演示网站。您将为本教程创建一个静态网站和一个演示 API,但在这里您将首先专注于静态网站。静态网站将向您展示负载测试的基础知识,而 API 将向您展示如何传递不同的参数来模拟不同的操作。

如果您更喜欢从 API 运行负载测试,请跳至下一节,在那里您将安装 Locust 并在您的计算机上运行它。本教程中的演示使用Swagger Petstore 演示 API

  1. 在您喜爱的代码编辑器中创建一个新文件,将下面的代码复制到新文件中并使用您喜欢的名称保存。对于本示例,文件名为load_test_page.html

以下是一个 HTML 文档,在网络浏览器中打开时会显示“这是一个测试页面。”的文本。

<!DOCTYPE html>
<html>
	<head>
		<title>ATA Load Balancing Demo</title>
	</head>
	<body>
		<h1>This is a test page.</h1>
	</body>
</html>

2. 接下来,打开您喜爱的网络浏览器,并导航到Azure 门户中的存储帐户。

3. 按照以下步骤在存储帐户中启用静态网站托管,并设置您网站的主页:

  • 点击左侧导航面板上的静态网站静态网站页面是您上传演示站点文件的地方。
  • 点击下面显示的已启用,以启用静态网站托管
  • 索引文档名称字段中输入load_test_page.html,然后点击保存。这样做会自动创建一个 Blob 容器和一个 URL(主要端点),指向您的网站。URL 还不能使用,但请稍后保存。
Enabling Static Website Hosting

4. 在左侧面板中点击存储资源管理器(预览版),然后导航到 Blob 容器 → $web。由静态网站功能创建的$web Blob 容器将托管您的所有静态文件。

点击上传,然后上传您在第一步创建的load_test_page.html

Uploading Static Files (HTML Page)

5. 最后,在您的网络浏览器上打开一个新标签页,导航到您在第二步中记下的 URL,然后查看该 URL 是否正在工作。

Accessing Static Website’s URL

安装 Locust 框架

您现在有一个要测试的站点,但您仍然需要负载测试工具来测试您的网站。编写代码来管理高负载测试耗时且容易出错。为什么不使用Locust 框架呢? Locust 是一个用 Python 编写的开源工具,您可以通过 pip 软件包管理器安装它。

如果您需要学习Python,请查看Python新手函数

Locust可以对静态站点、Web应用程序甚至API运行负载测试。唯一的要求是您要测试的内容具有您的设备可以访问的HTTP(S)端点。

默认情况下,pip软件包管理器在Linux和MacOS上将软件包安装在~/.local目录下,该目录不在系统路径上。该路径仅对Python虚拟环境可用,这就是为什么在本教程中您将使用pip的原因。

  1. 打开终端并运行以下命令以创建新的虚拟环境并安装Locust。
# 使用venv模块创建新的Python虚拟环境
python3 -m venv venv 
# 激活虚拟环境
source venv/bin/activate 
# 在新的虚拟环境中安装locust
python3 -m pip install locust
Starting and installing locust in a virtual environment

2. 运行以下命令创建新目录并导航到该目录。这样做可以使locust文件与代码库的其余部分隔离开来,更容易组织。例如,该目录命名为locust_dir

mkdir locust_dir
cd locust_dir

3. 最后,在locust_dir目录中创建一个名为locustfile.py的新文件,然后将下面的代码复制/粘贴到locustfile.py文件中。此文件将包含您的测试说明,例如如何模拟用户、这些用户将访问哪些端点以及传递什么参数。

当 Locust 运行时,它会寻找一个名为 locustfile.py 的特定文件。因此,最好将该文件保存在一个单独的目录(locust_dir)中,使 Locust 能够找到它,您可以创建额外的测试而不会覆盖其他测试。

下面的代码针对您提供的主机名路径运行 HTTP GET 请求,这相当于从命令行运行 curl http://<Host>/

一旦收到响应,Locust 立即发送下一个请求,并且整个过程对于测试中的每个虚拟用户都会重复。

# 从 Locust 导入类
from locust import HttpUser, task 

# 实例化一个新的虚拟用户
class HelloWorldUser(HttpUser): 
    # 这告诉 locust 处理下面的方法 
    # 作为虚拟用户会执行的操作
    @task 
    # 定义一个新的方法
    def hello_world(self): 
        # 此方法将在路径 `/` 上运行 HTTP GET 请求 
        # 在测试中,这是您要测试的站点的路径
        self.client.get("/") 

如果方法中的路径看起来不完整,那是因为确实如此。Locust 文件中仅定义路径和查询参数,而主机是在运行时传递的。此方法在下一步中将更有意义。

运行静态站点的负载测试

现在你已经安装了Locust,是时候运行一个负载测试了!负载测试不仅仅是编写一系列的网络请求来查看你的应用程序的行为。一个完整的测试会记录不同端点和配置下的响应时间、失败率和错误代码。

Locust 在运行方面非常灵活,可以通过命令行或通过 web 接口进行调用。在本教程中,你将使用 web 接口来对一个静态站点进行负载测试。

运行locust命令,使用你的locustfile.py文件中的测试场景来启动 locust 图形化应用程序。

locust 
Run the locust command

2. 打开一个网页浏览器,导航到 http://localhost:8089/ 来访问 Locust。8089端口是 Locust 默认运行的端口。

还记得你在“设置静态网站”部分中第三步中记下的 URL(主要端点)吗?现在是在下一步中使用它的时候了!

3. 最后,输入 URL(主要端点)到下面截图中看到的主机字段中,然后点击开始扑开始负载测试。这样做会告诉你的locustfile.py中的任何测试运行对你在主机字段中输入的 URL。

对于这个演示,可选的是更改用户数量生成速率字段的值。

用户数是同时创建的虚拟用户的最大数量。同时,生成率是每秒创建的用户数量,直到Locust达到虚拟用户的最大并发。虚拟用户的数量保持在最大值,直到您停止测试。

Running Locust load test on localhost:8089

在运行测试时,Locust会实时添加主机,然后向用户类中的每个路径发送请求。一旦收到响应,Locust立即发送另一个请求。

您将看到下面显示的已测试端点列表,以及有关响应时间、失败和每秒请求数的一些统计信息。

Viewing Locust Chart Showing the Number of Requests, Failures, and Response Times for the Test Case

如果您更喜欢以图形输出的形式查看您网站的性能指标,如下所示,请点击Charts选项卡。

Viewing graphical output of load tests statistics

对API运行负载测试

现在您已经熟悉了Locust的基础知识,让我们看一个更实际的测试案例。静态站点相当稳定,在运行性能测试时不太容易出现问题。那么为什么要对API运行负载测试呢?

API的响应可能有更多的变化,托管选项可能不太稳定,如果它们出现故障,可能对您的组织产生更大的影响。

如果您对API及其工作原理不太熟悉,有一篇文章介绍了身份验证、HTTP方法和JSON响应等基础知识。该文章是为PowerShell准备的,但API的概念将在本文中后面的部分变得重要。

  1. 替换locustfile.py文件的内容为下面的代码,该代码执行了以下几项任务:
  • 当Locust实例化新虚拟用户时,运行GET请求对用户进行身份验证
  • 在主机上运行GET请求,该请求将失败,因为该资源不存在
  • 运行POST请求,通过同一端点上的一系列项目传递JSON主体
import time # 从Python系统库导入时间
from locust import HttpUser, task

class HelloWorldUser(HttpUser):

    # 当用户被实例化时,将运行此任务
		def on_start(self): 
        # 宠物商店API没有用户数据库,
        # 因此任何用户名和密码都可以使用
        username = "foo" 
        password = "bar"
        # 这需要符合API文档中的loginUser端点
        self.client.get("/user/login?username="+username+"&password="+password) 

    # 该任务将失败,因为在https://petstore.swagger.io/v2/上没有端点
    @task
    def hello_world(self): 
        self.client.get("/")

    # 任务装饰器后的(3)告诉Locust将此任务运行3次
    @task(3) 
    def update_pets(self):
        # 使用for循环,从0到4计数,并在下面的HTTP请求中使用
        for pet_id in range(5): 
            # 运行HTTP POST请求并传递JSON主体
            self.client.post(f"/pet?petId={pet_id}", json={"name":"Mittens"}) 
            time.sleep(1) # 在继续之前等待1秒

在你的测试类中没有添加on_start语句,当Locust尝试测试其他方法时,会返回“403未授权”错误。尝试注释掉这个方法,然后重新运行Locust,看看它如何影响测试。

2. 接下来,打开宠物商店API的文档。上述测试用例是专门针对此API编写的,因此在本教程旁边打开此页面将有助于您查看端点。

运行下面的locust命令,就像在“针对静态站点运行负载测试”部分(第一步)中所做的那样。

locust
Run the locust command

最后,在Locust UI中输入https://petstore.swagger.io/v2作为主机。

Viewing endpoints of pet store API being tested

结论

在本教程中,您已经学会了如何针对静态网站和API运行负载测试。现在,您对如何测试您的网站以应对大量用户涌入有了更好的了解。负载测试在准备将应用发布给客户时非常有用。同样,在测试自动扩展配置或应用性能以实现低延迟时也是如此。

现在考虑一下您当前的应用程序或您支持的应用程序。当大量并发用户在使用它时,它们将如何响应?您认为负载测试场景可以指出哪些事情,从而使您的应用程序表现更好?

Source:
https://adamtheautomator.com/load-test/