Coding Gun

ทำ Load test ด้วย wrk

wrk คือเครื่องมือที่ใช้ทำ Load Test ผ่านทาง Command line ซึ่งเราสามารถติดตั้งได้ง่ายมากๆ

การติดตั้ง wrk บน MacOS

เราสามารถติดตั้ง wrk ผ่านทาง brew ได้เลยด้วยคำสั่ง

$ brew install wrk

เพียงแค่นี้เราก็สามารถเริ่มใช้งาน wrk ได้แล้ว หลังจากติดตั้งเรียบร้อยแล้วให้เราพิมพิ์ wrk เข้าไปใน Shell แบบนี้

$ wrk

wrk จะแสดง help ออกมาแบบนี้

-c, --connections: total number of HTTP connections to keep open with
                   each thread handling N = connections/threads

-d, --duration:    duration of the test, e.g. 2s, 2m, 2h

-t, --threads:     total number of threads to use

-s, --script:      LuaJIT script, see SCRIPTING

-H, --header:      HTTP header to add to request, e.g. "User-Agent: wrk"

    --latency:     print detailed latency statistics

    --timeout:     record a timeout if a response is not received within
                   this amount of time.

Options ต่างๆของ wrk

นี่คือความหมายของ Options แต่ละตัว

  1. Connections(-c, –connections) จำนวน connection ที่เราเชื่อมต่อกับ Web server
  2. Threads(-t, –threads) คือจำนวนของ Thread ที่เราแตกออกมา ยิ่งเราแตกออกมาเยอะเท่าไหร่ก็ยิ่งสร้าง Connections ได้มากขึ้น แต่จำนวน Threads จะต้องขึ้นอยู่กับ Spec ของเครื่องที่เราใช้ด้วย
  3. Durations(-d, –duration) ช่วงเวลาที่เราต้องการให้ Connection เปิดอยู่ ยิ่งเปิดนานยิ่งกิน Resource ของ Server มาก เราสามารถระบุหน่วยเป็น วินาที(s), นาที(m) หรือชั่วโมง(h) ก็ได้
  4. Header(-H, –header) เราสามารถสิ่ง Header เข้าไปเพิ่มหรือเปลี่ยนแปลง Header ไปตามที่เราต้องการได้ เช่นบาง Server จะเช็ค Header ว่าส่งมาจาก Browser ตัวไหน ซึ่งเราสามารถใส่เพิ่มเข้าไปได้
  5. Latency(–latency) เราสามาร print ระยะเวลาที่ใช้ในการ Load แต่ละหน้าออกมาดูได้
  6. Timeout(–timeout) ถ้า Response ไม่กลับมาในเวลาที่กำหนดให้ แสดงผลลัพธ์เป็น Timeout
  7. Script(–script) เราสามารถใส่ LuaJIT script เข้าไปเพื่อเปลี่ยน Http Method หรือ Random parameters ที่เราส่งเข้าไปได้ จะได้ไม่ซ้ำกันในทุกๆ Request

ตัวอย่างการใช้ wrk จะเป็นแบบนี้

$ wrk -c 400 -d 30s -t 10 http://scanme.nmap.org

จาก command นี้ wrk จะส่ง request ไปที่ http://scanme.nmap.org จำนวน 400 connections (-c) โดยใช้ 10 threads(-t) จะใช้เวลาในแต่ละ connection 30 วินาที(-d)

1 thread จะดูแล connections ทั้งหมด 400/10 = 40 connections

ผลลัพธ์จะออกมาดังนี้

Running 30s test @ http://scanme.nmap.org
  10 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   282.99ms  175.73ms   1.99s    87.26%
    Req/Sec   139.15     37.83   330.00     66.99%
  41248 requests in 30.06s, 283.47MB read
  Socket errors: connect 0, read 3, write 0, timeout 55
Requests/sec:   1372.00
Transfer/sec:      9.43MB

ซึ่งจะเห็นว่า wrk ส่ง requests ไปทั้งหมด 41,248 requests จาก 10 threads โดยที่มี timeout ไป 55 requests คิดเป็น 0.13%

ตัวอย่าง LuaJIT

กำหนด Http Method

ในตัวอย่างนีั้จะส่ง request ไปด้วย method post และส่งตัวแปร foo และ baz ไปใน body

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

นับจำนวน Response

ในตัวอย่างนี้เราจะนับจำนวน response เมื่อจำนวน response = 100 ก็จะหยุดการทำงานของ thread นี้ทันที

local counter = 1

function response()
   if counter == 100 then
      wrk.thread:stop()
   end
   counter = counter + 1
end

Delay request

เราสามารถกำหนดว่าจะให้ delay(หน่วยเป็นมิลลิวินาที) ก่อนจะส่ง request ต่อไป ซึ่งในตัวอย่างนี้จะเป็นการ deplay แบบ random(10-50 มิลลิวินาที) ได้ด้วย script นี้

function delay()
   return math.random(10, 50)
end

อ่านวิธีการติดตั้งและใช้งาน wrk ต่อได้ที่นี่

Phanupong Permpimol
Follow me

Software Engineer ที่เชื่อในเรื่องของ Process เพราะเมื่อ Process ดี Product ก็จะดีตาม ปัจจุบันเป็นอาจารย์และที่ปรึกษาด้านการออกแบบและพัฒนา Software และ Web Security