首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在Ubuntu 14.04上使用wrk对HTTP延迟进行基准测试

如何在Ubuntu 14.04上使用wrk对HTTP延迟进行基准测试

原创
作者头像
黑色技术
修改2018-09-26 09:53:23
2.2K0
修改2018-09-26 09:53:23
举报

介绍

本文重点介绍称为开源HTTP基准测试工具WRK,它可以在高负荷下测量HTTP服务的延迟。

延迟是指请求发生的时间(通过wrk)和收到响应的时刻(来自服务)之间的时间间隔。这可用于模拟访问者在使用浏览器或任何其他发送HTTP请求的方法访问网站时在您的网站上遇到的延迟。

wrk对于测试任何依赖HTTP的网站或应用程序非常有用,例如:

  • Rails和其他Ruby应用程序
  • Express和其他JavaScript应用程序
  • PHP应用程序
  • 在Web服务器上运行的静态网站
  • Nginx这样的负载均衡器背后的站点和应用程序
  • 你的缓存层

测试无法真实用户进行比较,但它们应该能够很好地估计预期延迟,以便您可以更好地规划基础架构。测试还可以让您深入了解性能瓶颈。

wrk是开源的,可以在GitHub找到

它非常稳定,并且由于其多线程特性,可以模拟高负载。wrk的最大特点是它能够集成Lua脚本,这增加了许多可能性,例如:

  • 使用cookie对请求进行基准测试
  • 自定义报告
  • 对多个URL进行基准测试 - 也就是现在流行的ab,这个功能也是Apache HTTP服务器基准测试工具所不具备的。

先决条件

我们将在本教程中使用的基础结构如下图所示:

如您所见,我们将在非常简单的场景中使用wrk。我们将在Node.js应用程序上对Express进行基准测试。

我们将启动两个腾讯CVM:一个用于生成负载的wrk,另一个用于应用程序。如果他们在同一个盒子上,他们会竞争资源,我们的结果将不可靠。

基准测试的机器应该足够强大以处理受压系统,但在我们的情况下,应用程序非常简单,我们将使用相同尺寸的机器。

  • 因为它们将通过私有IP进行通信,所以在同一区域中旋转两个腾讯CVM
  • 在本教程中调用一个腾讯CVM wrk1和另一个app1
  • 选择2 GB内存
  • 选择Ubuntu 14.04,没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后在购买服务器
  • 在“ 可用设置”部分中选择“ 专用网络**”**
  • 在每台服务器上创建一个sudo用户

较小的腾讯CVM也可以工作,但是你应该期望测试结果有更多的延迟。在实际测试环境中,您的应用服务器应与您打算在生产中使用的大小相同。

第1步 - 两个服务器:安装Docker

为了让我们的生活更轻松,我们将使用Docker,因此我们可以在容器内启动wrk和我们的应用程序。这让我们可以跳过设置Node.js环境,npm模块和deb软件包; 我们所需要的只是下载并运行相应的容器。节省的时间将用于学习wrk。

注意:本节中的命令应在两个腾讯CVM上执行。

要安装Docker,请登录到您的服务器并执行以下命令。首先,更新包列表:

sudo apt-get update

安装Wget和cURL:

sudo apt-get install -y wget curl

下载并安装Docker:

sudo wget -qO- https://get.docker.com/ | sh

将您的用户添加到docker组中,这样您就可以在不使用sudo的情况下执行Docker命令:

sudo gpasswd -a ${USER} docker
sudo service docker restart
newgrp docker

如果您使用的是其他Linux发行版,Docker的安装文档可能会涵盖您的案例。

要验证docker是否已正确安装,请使用以下命令:

docker --version

你应该得到以下或类似的输出:

OutputDocker version 1.7.1, build 786b29d

第2步 - 准备测试应用程序

app1腾讯CVM上执行这些命令。

出于测试目的,作者在公共Docker注册表中发布了Docker镜像。它包含一个用Node.js编写的HTTP调试应用程序。它不是一个性能野兽(我们今天不打破任何记录)但它足以进行测试和调试。你可以在这里查看源代码。

当然,在现实生活中,您可能希望测试自己的应用程序。

在我们启动应用程序之前,让我们将腾讯CVM的私有IP地址保存到一个名为APP1_PRIVATE_IP的变量中:

export APP1_PRIVATE_IP=$(sudo ifconfig eth1 | egrep -o "inet addr:[^ ]*" | awk -F ":" '{print $2}')

您可以使用以下方式查看私有IP:

echo $APP1_PRIVATE_IP

输出:

Output
10.135.232.163

您的私人IP地址会有所不同,请注意。

现在只需执行以下命令即可启动应用程序:

docker run -d -p $APP1_PRIVATE_IP:3000:3000 --name=http-debugging-application czerasz/http-debugger

上面的命令将首先下载所需的Docker镜像,然后运行Docker容器。容器以分离模式启动,这意味着它将在后台运行。该选项-p $APP1_PRIVATE_IP:3000:3000将代理3000端口上本地容器和主机私有IP之间的所有通信

现在测试curl以查看应用程序是否正在运行:

curl -i -XPOST http://$APP1_PRIVATE_IP:3000/test -d 'test=true'

预期产量:

Output
HTTP/1.1 200 OK
X-Powered-By: Express
X-Debug: true
Content-Type: text/html; charset=utf-8
Content-Length: 2
ETag: W/"2-79dcdd47"
Date: Wed, 13 May 2015 16:25:37 GMT
Connection: keep-alive
​
ok

该应用程序非常简单,只返回一条ok消息。所以每次wrk请求这个应用程序时,它都会收到一条简短的ok消息。

最重要的部分是我们可以通过分析应用程序日志来查看wrk对我们的应用程序的请求。

使用以下命令查看应用程序日志:

docker logs -f --tail=20 http-debugging-application

您的示例输出应如下所示:

Output
[2015-05-13 16:25:37] Request 1
​
POST/1.1 /test on :::3000
​
Headers:
 - user-agent: curl/7.38.0
 - host: 0.0.0.0:32769
 - accept: */*
 - content-length: 9
 - content-type: application/x-www-form-urlencoded
​
No cookies
​
Body:
test=true

如果您愿意,可以在运行基准测试时保持运行。用CTRL-C退出尾巴。

第3步 - 安装wrk

登录wrk1服务器,准备安装wrk

由于我们有Docker,因此非常容易。只需使用以下命令从Docker注册表中心下载映像williamyeh/wrk

docker pull williamyeh/wrk

上面的命令下载了包含wrk的Docker镜像。我们不需要构建wrk,也不需要安装任何其他软件包。要运行wrk(在容器内),我们只需要根据此图像启动容器就可以完成,这也是我们即将去做的事情。

下载应该只需几秒钟,因为图像非常小 - 小于3 MB。如果您想直接在您喜爱的Linux发行版上安装wrk,请访问此Wiki页面并按照说明操作。

我们还将在此服务器上设置变量APP1_PRIVATE_IP。我们需要来自app1 腾讯CVM 的私有IP地址。

导出变量:

export APP1_PRIVATE_IP=10.135.232.163

请记住将10.135.232.163IP地址更改为app1 腾讯CVM的私有IP。此变量仅保存在当前会话中,因此请记住在下次登录使用wrk时重新设置它。

第4步 - 运行wrk基准测试

在本节中,我们将最终看到wrk的运行。

本节中的所有命令都应该在wrk1腾讯CVM上执行。

让我们看看wrk为我们提供的选项。仅使用--version标志运行wrk容器将打印出关于其用法的简短总结:

docker run --rm williamyeh/wrk --version

输出:

Output
wrk 4.0.0 [epoll] Copyright (C) 2012 Will Glozer
Usage: wrk <options> <url>
  Options:
    -c, --connections <N>  Connections to keep open
    -d, --duration    <T>  Duration of test
    -t, --threads     <N>  Number of threads to use
​
    -s, --script      <S>  Load Lua script file
    -H, --header      <H>  Add header to request
        --latency          Print latency statistics
        --timeout     <T>  Socket/request timeout
    -v, --version          Print version details
​
  Numeric arguments may include a SI unit (1k, 1M, 1G)
  Time arguments may include a time unit (2s, 2m, 2h)

现在我们已经有了一个很好的概述,现在让我们编写命令来运行我们的测试。请注意,此命令不会执行任何操作,因为我们没有从容器内部运行它。

我们可以用wrk运行的最简单的情况是:

wrk -t2 -c5 -d5s -H 'Host: example.com' --timeout 2s http://$APP1_PRIVATE_IP:3000/

意思是:

  • -t2:使用两个单独的线程
  • -c5:打开六个连接(第一个客户端为零)
  • -d5s:运行测试五秒钟
  • -H 'Host: example.com':传递Host 标题
  • --timeout 2s:定义两秒超时
  • http://$APP1_PRIVATE_IP:3000/ 目标应用程序正在监听 $APP1_PRIVATE_IP:3000
  • 对我们的应用程序/的路径进行基准测试

这也可以描述为六个用户重复请求我们的主页五秒钟。

下图显示了这种情况:

请记住,无法将连接与真实用户进行比较,因为真实用户在查看主页时也会下载CSS,图像和JavaScript文件。

这是测试的实际命令:

让我们在我们的wrk 腾讯CVM容器中运行所描述的场景:

docker run --rm williamyeh/wrk -t2 -c5 -d5s -H 'Host: example.com' --timeout 2s http://$APP1_PRIVATE_IP:3000/

等待测试运行几秒钟,然后查看结果,我们将在下一步中对其进行分析。

第5步 - 评估输出

输出:

OutputRunning 5s test @ http://10.135.232.163:3000
  2 threads and 5 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.82ms    2.64ms  26.68ms   85.81%
    Req/Sec   550.90    202.40     0.98k    68.00%
  5494 requests in 5.01s, 1.05MB read
Requests/sec:   1096.54
Transfer/sec:    215.24KB
  • 当前配置摘要: Running 5s test @ http://10.135.232.163:3000 2 threads and 5 connections 在这里,我们可以看到我们的基准配置的简短摘要。基准测试时间为5秒,基准测试机IP为10.135.232.163,并且测试使用了两个线程。
  • 延迟和req / sec统计信息的正态分布参数: Thread Stats Avg Stdev Max +/- Stdev Latency 3.82ms 2.64ms 26.68ms 85.81% Req/Sec 550.90 202.40 0.98k 68.00% 这部分向我们展示了我们基准测试的正态分布细节 - 高斯函数将具有哪些参数。 基准并不总是具有正态分布,这就是为什么这些结果可能会产生误导。因此,请始终查看Max+/- Stdev值。如果这些值很高,那么您可以预期您的分布可能会有很重的尾巴。
  • 有关请求编号,传输数据和吞吐量的统计信息: 5494 requests in 5.01s, 1.05MB read Requests/sec: 1096.54 Transfer/sec: 215.24KB 在这里,我们看到在5.01几秒钟内,wrk可以进行5494请求和1.05MB数据传输。结合简单的math(total number of requrests/benchmark duration),我们得到1096.54每秒请求的结果。

通常,您设置的客户端越多,您应该获得的每秒请求越少。延迟也会增加。这是因为应用程序将承受更重的负载。

什么结果最好?

你的目标是保持Requests/sec尽可能高和Latency尽可能低。

理想情况下,延迟不应该太高,至少对于网页而言。当资产大约两秒或更短时,资产的页面加载时间限制是最佳的。

现在你可能会问自己: 550.90 Requests/sec3.82ms的延迟是否是一个好的结果?不幸的是,没有简单的答案。这取决于许多因素,如:

  • 客户数量,正如我们之前讨论的那样。
  • 服务器资源 - 是大型还是小型实例?
  • 为应用程序提供服务的机器数量
  • 您的服务类型 - 是提供静态文件的缓存还是提供动态响应的广告服务器?
  • 数据库类型,数据库簇大小,数据库连接类型
  • 请求和响应类型 - 它是一个小的AJAX请求还是胖API调用?
  • 还有很多其他因素

第6步 - 采取措施改善延迟

如果您对服务表现不满意,您可以:

  • 调整您的服务 - 检查您的代码,看看可以更有效地完成哪些工作
  • 检查您的数据库,看看它是否是您的瓶颈
  • 垂直扩展 - 为您的计算机添加资源
  • 水平扩展 - 添加服务的另一个实例并将其添加到负载均衡器
  • 添加缓存层

请记住在对其进行更改后对您的服务进行基准测试 - 只有这样才能确保您的服务得到改进。

你可能会想,如果没有Lua的话,那事情可能就是这样了。。。

使用Lua脚本模拟高级HTTP请求

因为wrk有一个内置的LuaJIT(Lua的即时编译器),所以可以使用Lua脚本进行扩展。正如介绍中所提到的,这为wrk增加了许多功能。

在wrk中使用Lua脚本很简单。只需将文件路径附加到-s标志即可。

因为我们在Docker中使用wrk,所以我们必须先与容器共享此文件。这可以通过Docker的-v选项实现。

wrk的Lua脚本的一部分

在通用形式中,使用调用的脚本test.lua,会使整个命令可能如下所示:

docker run --rm -v `pwd`/scripts:/scripts williamyeh/wrk -c1 -t1 -d5s -s /scripts/test.lua http://$APP1_PRIVATE_IP:3000

我们在前面的步骤中解释了wrk命令及其选项。这个命令不会增加太多; 只是脚本的路径和一些额外的命令告诉Docker如何在容器外找到它。

--rm标志将在停止后自动删除容器。

但我们真的知道如何编写Lua脚本吗?不要害怕; 你会轻松学习它。我们将在这里介绍一个简单的示例,您可以自己运行自己的更高级脚本。

首先让我们谈谈反映wrk内部逻辑的预定脚本结构。下图说明了一个线程:

wrk执行以下执行阶段:

  • 解析域的IP地址
  • 从线程设置开始
  • 执行压力测试阶段,称为运行阶段
  • 最后一步简称为完成

使用多个线程时,您将拥有一个分辨率阶段和一个完成阶段,但有两个设置阶段和两个运行阶段:

此外,运行阶段可以分为三个步骤:initrequestresponse

根据提供的图表和文档,我们可以在Lua脚本中使用以下方法:

  • setup(thread):所有线程初始化但尚未启动时执行。用于将数据传递给线程
  • init(args):初始化每个线程时调用 此函数接收脚本的额外命令行参数,我们必须用--将该参数与wrk参数分开。 例: wrk -c3 -d1s -t2 -s /scripts/debug.lua http://$APP1_PRIVATE_IP:3000 -- debug true
  • request():需要为每个请求返回HTTP对象。在这个函数中,我们可以修改方法,标题,路径和正文 使用wrk.format辅助函数来塑造请求对象。 例: return wrk.format(method, path, headers, body)
  • response(status, headers, body):响应回来时调用
  • done(summary, latency, requests):在完成所有请求并计算统计信息时执行 在此功能中,可以使用以下属性: 属性描述summary.duration运行持续时间,以微秒为单位summary.requests完成的请求总数summary.bytes收到的总字节数summary.errors.connect总套接字连接错误summary.errors.read总套接字读错误summary.errors.write总套接字写错误summary.errors.status总HTTP状态代码> 399summary.errors.timeout总请求超时latency.min测试期间达到的最小延迟值latency.max测试期间达到的最大延迟值latency.mean测试期间达到的平均延迟值latency.stdev潜伏期标准差latency:percentile(99.0)第99百分位值latency[i]请求的原始延迟数据 i

每个线程都有自己的Lua上下文,并在其中有自己的局部变量。

现在我们将通过一些实际示例,但您可以在wrk项目的scripts目录中找到更多有用的基准测试脚本。

示例:POST请求

让我们从最简单的例子开始,我们模拟一个POST请求。

POST请求通常用于将数据发送到服务器。这可用于基准测试:

  • HTML表单处理程序:使用HTML表单在action属性中的地址: <form action="/login.php"> ... </form>
  • POST API端点:如果您有一个restful API,请创建文章的地方使用该端点: POST /articles

首先在wrk1腾讯CVM 上创建一个scripts/post.lua文件。

cd ~
mkdir scripts
nano scripts/post.lua

添加以下内容:

wrk.method = "POST"
wrk.body   = "login=sammy&password=test"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

这个脚本非常简单,甚至没有使用任何提到的方法,我们就修改了全局wrk对象属性。

我们将请求方法更改为POST,添加了一些登录参数,并将Content-Type标头指定为HTML表单使用的MIME类型。

现在是关键时刻 - 使用此命令对应用程序进行基准测试(在wrk1 腾讯CVM上执行):

docker run --rm -v `pwd`/scripts:/scripts williamyeh/wrk -c1 -t1 -d5s -s /scripts/post.lua http://$APP1_PRIVATE_IP:3000

输出:

OutputRunning 5s test @ http://10.135.232.163:3000
  1 threads and 1 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.04ms  718.38us  12.28ms   90.99%
    Req/Sec     1.02k   271.31     1.52k    66.00%
  5058 requests in 5.00s, 0.97MB read
Requests/sec:   1011.50
Transfer/sec:    198.55KB

输出类似于我们之前看到的输出。

请注意,我们仅使用一个连接进行基准测试。这对应于只有一个用户想要连续登录,传递用户名和密码的情况。这不是请求任何CSS,图像或JavaScript文件。

对于更现实的场景,您应该增加客户端和线程的数量,同时观察延迟参数,以查看应用程序验证用户凭据的速度。

示例:多个URL路径

另一个常见需求是同时测试应用程序的多个路径。

让我们创建一个名为paths.txt的文件,该文件可以在data目录中调用,并添加我们想要在基准测试期间使用的所有路径。

cd ~
mkdir data
nano data/paths.txt

查找以下示例data/paths.txt

/feed.xml
/contact/
/about/
/blog/
/2015/04/21/nginx-maintenance-mode/
/2015/01/06/vagrant-workflows/
/2014/12/10/top-vagrant-plugins/

然后抓住这个简单的脚本并将其保存为scripts/multiple-url-paths.lua

-- Load URL paths from the file
function load_url_paths_from_file(file)
  lines = {}

  -- Check if the file exists
  -- Resource: http://stackoverflow.com/a/4991602/325852
  local f=io.open(file,"r")
  if f~=nil then
    io.close(f)
  else
    -- Return the empty array
    return lines
  end

  -- If the file exists loop through all its lines
  -- and add them into the lines array
  for line in io.lines(file) do
    if not (line == '') then
      lines[#lines + 1] = line
    end
  end

  return lines
end

-- Load URL paths from file
paths = load_url_paths_from_file("/data/paths.txt")

print("multiplepaths: Found " .. #paths .. " paths")

-- Initialize the paths array iterator
counter = 0

request = function()
  -- Get the next paths array element
  url_path = paths[counter]

  counter = counter + 1

  -- If the counter is longer than the paths array length then reset it
  if counter > #paths then
    counter = 0
  end

  -- Return the request object with the current URL path
  return wrk.format(nil, url_path)
end

虽然本教程并未尝试详细讲授Lua脚本,但如果您阅读脚本中的注释,则可以很好地了解它的作用。

multiple-url-paths.lua脚本将打开该/data/paths.txt文件,如果此文件包含路径,则会将它们保存到内部paths数组中。然后,对于每个请求,将采用下一个路径。

要运行此基准测试,请使用以下命令(在wrk1 腾讯CVM上执行)。您会注意到我们正在添加一些换行符以便于复制:

docker run --rm \
           -v `pwd`/scripts:/scripts \
           -v `pwd`/data:/data \
           williamyeh/wrk -c1 -t1 -d5s -s /scripts/multiple-url-paths.lua http://$APP1_PRIVATE_IP:3000

输出:

Outputmultiplepaths: Found 7 paths
multiplepaths: Found 7 paths
Running 5s test @ http://10.135.232.163:3000
  1 threads and 1 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     0.92ms  466.59us   4.85ms   86.25%
    Req/Sec     1.10k   204.08     1.45k    62.00%
  5458 requests in 5.00s, 1.05MB read
Requests/sec:   1091.11
Transfer/sec:    214.17KB

使用JSON和YAML的Avanced请求

现在您可能会认为其他基准测试工具也可以执行这些类型的测试。但是,wrk还能够使用JSON或YAML格式处理高级HTTP请求。

例如,您可以加载JSON或YAML文件,该文件详细描述了每个请求。

作者在作者的技术博客上发布了一个带有JSON请求的高级示例。

您可以使用wrk和Lua对您能想到的任何类型的HTTP请求进行基准测试。

结论

阅读本文后,您应该能够使用wrk来对您的应用程序进行基准测试。作为旁注,您还可以看到Docker的优点以及它如何极大地最小化您的应用程序和测试环境的设置。

最后,您可以使用带有wrk的Lua脚本进行高级HTTP请求。

更多 Ubuntu教程请前往腾讯云+社区学习更多知识。


参考文献:《 How To Benchmark HTTP Latency with wrk on Ubuntu 14.04》

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
  • 先决条件
  • 第1步 - 两个服务器:安装Docker
  • 第2步 - 准备测试应用程序
  • 第3步 - 安装wrk
  • 第4步 - 运行wrk基准测试
  • 第5步 - 评估输出
  • 第6步 - 采取措施改善延迟
  • 使用Lua脚本模拟高级HTTP请求
    • wrk的Lua脚本的一部分
      • 示例:POST请求
        • 示例:多个URL路径
          • 使用JSON和YAML的Avanced请求
          • 结论
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档