wrk is a relatively advanced HTTP stress testing tool. Wrk can run on one or more core CPUs during load testing. Wrk combines multi-threaded design ideas such as epoll and kqueue, a scalable event notification system. Currently wrk can be installed on Linux systems and Mac systems. With just one command line, you can do many basic http performance tests.
The open source of wrk, the code is on github. https://github.com/wg/wrk
The first thing to say is: wrk can only run on Unix-like systems. Such as linux, mac, solaris, etc. Compile on these systems.
I have to say here, why many people say that mac is the best development environment. Not because of how high the use of mac is. But you can get the benefits of windows and linux at the same time. Most under linux All development tools can be used on mac. Many of them are precompiled, and some can be used only after compiling.
A good feature of wrk is that it can squeeze a large amount of concurrency with few threads. The reason is that It uses some operating system-specific high-performance io mechanisms, such as select, epoll, kqueue, etc. In fact, it reuses the ae asynchronous event-driven framework of redis. To be precise, the ae event-driven framework is not invented by redis, it comes As for the Tcl interpreter jim, this small and efficient framework is more well-known because it was adopted by redis.
To use wrk, first compile wrk.
You need to have git and a basic c compilation environment installed on your machine. wrk itself is written in c. There is very little code. And it does not use many third-party libraries. What is the problem.
1. git clone https://github.com/wg/wrk.git
1. src/wrk.h:11:25: fatal error: openssl/ssl.h: No such file or directory
2. #include <openssl/ssl.h>
It is because the library of openssl is not installed in the system.
sudo apt-get install libssl-dev
or
sudo yum install openssl-devel
The installation is complete, configure the environment variable /etc/profile
export PATH=$PATH:/letv/wrk
Effective profile file
source /etc/profile
Let's do a simple performance test first:
1.wrk -t2 -c10 -d30s -T30s --latency http://10.58.100.90/jsondatedemo.txt
Waiting for this test to complete
Running 30s test @ http://10.58.100.90/jsondatedemo.txt
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 209.38ms 300.23ms 1.99s 90.36%
Req/Sec 21.81 10.55 60.00 62.24%
Latency Distribution
50% 106.14ms
75% 188.97ms
90% 491.26ms
99% 1.56s
1218 requests in 30.04s, 1.76MB read
Socket errors: connect 0, read 540, write 0, timeout 30
Non-2xx or 3xx responses: 540
Requests/sec: 40.55
Transfer/sec: 60.02KB
------------------------------------------------------------------------------------------------
Parameter meaning:
-t thread mode -c simulated concurrency -d duration m minutes s seconds -T set the delay time, the default is 1 second --latency shows the percentage of the user's response time
-------------------------------------------------------------------------------------------------
-c Generally, the number of threads should not be too much. 2 to 4 times the number of cores is enough. If it is too much, the efficiency will be reduced due to too many thread switching. Because wrk does not use a model of one thread per connection, but improves through asynchronous network io Concurrency. So network communication will not block thread execution. This is why wrk can simulate a large number of network connections with few threads. Now many performance tools do not use this method, but use increasing the number of threads to achieve high Concurrency. So once the concurrency is set high, the pressure on the test machine itself will be very high. The test effect will decrease instead.
-T wrk The default timeout is 1 second. This is a bit short. I usually set it to 30 seconds. This seems reasonable.
Thread Stats Avg Stdev Max +/- Stdev
Latency 209.38ms 300.23ms 1.99s 90.36%
Req/Sec 21.81 10.55 60.00 62.24%
Latency: It can be understood as response time, with mean, standard deviation, maximum value, plus or minus one standard deviation ratio.
Req/Sec: The number of completed requests per thread per second, also has mean, standard deviation, The maximum value, plus or minus one standard deviation.
Generally speaking, we mainly focus on the mean value and the maximum value. If the standard deviation is too large, the sample itself has a relatively high degree of dispersion. It is possible that the system performance fluctuates greatly.
--latency
Latency Distribution
50% 106.14ms
75% 188.97ms
90% 491.26ms
99% 1.56s
In 30 seconds, a total of 1218 requests were completed and the amount of data read was 30.04s.
Then there were error statistics. The above statistics can see that there were 540 read errors and 30 timeouts.
Then, the threads completed an average of 40.55 requests per second. . Reads 60.02 megabytes of data per second.
1218 requests in 30.04s, 1.76MB read
Socket errors: connect 0, read 540, write 0, timeout 30
Non-2xx or 3xx responses: 540
Requests/sec: 40.55
Transfer/sec: 60.02KB
wrk supports lua language script. In this script, you can modify the method, header, body, and do a custom analysis of the response. Because it is a lua script, it actually gives you unlimited possibilities. But such a powerful function if If not used carefully, the performance of the test terminal will be degraded, and the test results will also be affected.
Generally, modifying the method, header, and body will not affect the performance of the test terminal, but the operation of request and response should be extra cautious.
Let's see how to use lua scripts through some test scenarios.
POST + header + body.
First create a post.lua file:
1. wrk.method = "POST"
2. wrk.body = "devId=C80E7776704A"
3. wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
Just these three lines are enough, of course headers can add as much content as you want.
Then execute:
1. wrk -t12 -c100 -d30s -T30s --script=post.lua --latency http://h5.itv.cp21.ott.cibntv.net/api/lottery/draw.json?
---------------------------------------------------------------------------------------------------------------------------------------------
The following are not verified:
Several lua hook functions provided by wrk:
setup function
This function is called when the target IP address has been resolved, and all threads have been generated, but not yet started. Each thread executes this function once.
You can pass thread:get( name), thread:set(name, value) to set thread-level variables.
init function Called before
each request is sent.
Can accept additional arguments on the wrk command line. Specify with --.
delay function
This function returns a value, which is How long to delay the execution of the next request after this request is executed. It can correspond to the scenario of thinking time.
request
function This function can modify the properties of this request before each request. Returns a string. This function should be used with caution. It will affect the performance of the test terminal. The
response function is called after
each request returns. Special processing can be done according to the content of the response, such as stopping the execution of the test when encountering a special response, or outputting to the console, etc.
1. function response(status, headers, body)
2. if status ~= 200 then
3. print(body)
4. wrk.thread:stop()
5. end
6. end
The done function
is called after all requests are executed, and is generally used to customize statistical results.
1. done = function(summary, latency, requests)
2. io.write("------------------------------\n")
3. for _, p in pairs({ 50, 90, 99, 99.999 }) do
4. n = latency:percentile(p)
5. io.write(string.format("%g%%,%d\n", p, n))
6. end
7. end
Here is the complete example given in the wrk source code:
1. local counter = 1
2. local threads = {}
3.
4. function setup(thread)
5. thread:set("id", counter)
6. table.insert(threads, thread)
7. counter = counter + 1
8. end
9.
10. function init(args)
11. requests = 0
12. responses = 0
13.
14. local msg = "thread %d created"
15. print(msg:format(id))
16. end
17.
18. function request()
19. requests = requests + 1
20. return wrk.request()
21. end
22.
23. function response(status, headers, body)
24. responses = responses + 1
25. end
26.
27. function done(summary, latency, requests)
28. for index, thread in ipairs(threads) do
29. local id = thread:get("id")
30. local requests = thread:get("requests")
31. local responses = thread:get("responses")
32. local msg = "thread %d made %d requests and got %d responses"
33. print(msg:format(id, requests, responses))
34. end
35. end
When testing compound scenarios, you can also access multiple urls through lua.
For example, this complex lua script randomly reads the url list in the paths.txt file, and then accesses.:
1. counter = 1
2.
3. math.randomseed(os.time())
4. math.random(); math.random(); math.random()
5.
6. function file_exists(file)
7. local f = io.open(file, "rb")
8. if f then f:close() end
9. return f ~= nil
10. end
11.
12. function shuffle(paths)
13. local j, k
14. local n = #paths
15. for i = 1, n do
16. j, k = math.random(n), math.random(n)
17. paths[j], paths[k] = paths[k], paths[j]
18. end
19. return paths
20. end
21.
22. function non_empty_lines_from(file)
23. if not file_exists(file) then return {} end
24. lines = {}
25. for line in io.lines(file) do
26. if not (line == '') then
27. lines[#lines + 1] = line
28. end
29. end
30. return shuffle(lines)
31. end
32.
33. paths = non_empty_lines_from("paths.txt")
34.
35. if #paths <= 0 then
36. print("multiplepaths: No paths found. You have to create a file paths.txt with one path per line")
37. os.exit()
38. end
39.
40. print("multiplepaths: Found " .. #paths .. " paths")
41.
42. request = function()
43. path = paths[counter]
44. counter = counter + 1
45. if counter > #paths then
46. counter = 1
47. end
48. return wrk.format(nil, path)
49. end
Regarding cookies
, sometimes we need to simulate some scenarios of passing data through cookies. wrk does not have special support, it can be implemented through wrk.headers["Cookie"]="xxxxx".
Here is an example found on the Internet, taking the cookie of Response as a cookie for subsequent requests
1. function getCookie(cookies, name)
2. local start = string.find(cookies, name .. "=")
3.
4. if start == nil then
5. return nil
6. end
7.
8. return string.sub(cookies, start + #name + 1, string.find(cookies, ";", start) - 1)
9. end
10.
11. response = function(status, headers, body)
12. local token = getCookie(headers["Set-Cookie"], "token")
13.
14. if token ~= nil then
15. wrk.headers["Cookie"] = "token=" .. token
16. end
17. end
The positioning of wrk itself is not used to replace professional performance testing tools such as loadrunner. In fact, these functions can fully cope with some performance verification in the usual development process.
Transfer: http://sanwen8.cn/p/1d4kAUJ.html
Mount: 224 /letv/wrk