"Go" to "load" test
郭學聰 Hsueh-Tsung KuoSat, 11 Aug 2018
digraph locust {
nodesep=1.0 // increases the separation between nodes
node [color="red" shape=box]
edge [color="blue" style=dashed]
master [label="master (coordinator)"]
client1 [label="client 1...n" shape="oval"]
client2 [label="client 1...n" shape="oval"]
client3 [label="client 1...n" shape="oval"]
master->slave1
master->slave2
master->slave3
slave1->client1 [style=solid]
slave2->client2 [style=solid]
slave3->client3 [style=solid]
client1->server
client1->server
client1->server
client1->server
client1->server
client2->server
client2->server
client2->server
client2->server
client2->server
client3->server
client3->server
client3->server
client3->server
client3->server
}
pip install locustio
run Locust distributed across multiple processes/machines
pip install pyzmq
from locust import HttpLocust, TaskSet, task class WebsiteTasks(TaskSet): def on_start(self): self.client.post("/login", { "username": "test_user", "password": "" }) @task def index(self): self.client.get("/") @task def about(self): self.client.get("/about/") class WebsiteUser(HttpLocust): task_set = WebsiteTasks min_wait = 5000 max_wait = 15000
from locust import HttpLocust, TaskSet, task class WebsiteTasks(TaskSet): def on_start(self): self.client.post("/login", { "username": "test_user", "password": "" }) @task(100) def index(self): self.client.get("/") @task(7) def about(self): self.client.get("/about/") class WebsiteUser(HttpLocust): task_set = WebsiteTasks min_wait = 5000 max_wait = 15000
locust -f locustfile.py --host=http://example.com
locust master->locust slave: ZeroMQ: make a request
note left of locust slave: log start time
locust slave->server: HTTP request
server->locust slave: HTTP response
note left of locust slave: log end time
note left of locust slave: detect response status
locust slave->locust master: ZeroMQ: report status
dummy.py
# -*- coding: utf-8 -*- from locust import Locust, TaskSet, task class MyTaskSet(TaskSet): @task(20) def hello(self): pass class Dummy(Locust): task_set = MyTaskSet
main.go
package main import "github.com/myzhan/boomer" import "time" func foo() { start := boomer.Now() time.Sleep(100 * time.Millisecond) elapsed := boomer.Now() - start // Report your test result as a success, if you write it in python, it will looks like this // events.request_success.fire(request_type="http", name="foo", response_time=100, response_length=10) boomer.Events.Publish("request_success", "http", "foo", elapsed, int64(10)) }
main.go
func bar() { start := boomer.Now() time.Sleep(100 * time.Millisecond) elapsed := boomer.Now() - start // Report your test result as a failure, if you write it in python, it will looks like this // events.request_failure.fire(request_type="udp", name="bar", response_time=100, exception=Exception("udp error")) boomer.Events.Publish("request_failure", "udp", "bar", elapsed, "udp error") }
main.go
func main() { task1 := &boomer.Task{ Name: "foo", Weight: 10, Fn: foo, } task2 := &boomer.Task{ Name: "bar", Weight: 20, Fn: bar, } boomer.Run(task1, task2) }
main_seq.go
package main import "github.com/myzhan/boomer" import "time" func foobar(){ start := boomer.Now() time.Sleep(100 * time.Millisecond) elapsed := boomer.Now() - start // Report your test result as a success, if you write it in python, it will looks like this // events.request_success.fire(request_type="http", name="foo", response_time=100, response_length=10) boomer.Events.Publish("request_success", "http", "foo", elapsed, int64(10)) start = boomer.Now() time.Sleep(100 * time.Millisecond) elapsed = boomer.Now() - start // Report your test result as a failure, if you write it in python, it will looks like this // events.request_failure.fire(request_type="udp", name="bar", response_time=100, exception=Exception("udp error")) boomer.Events.Publish("request_failure", "udp", "bar", elapsed, "udp error") }
main_seq.go
func main(){ sequencialTask1 := &boomer.Task{ Name: "foobar1", Weight: 10, Fn: foobar, } sequencialTask2 := &boomer.Task{ Name: "foobar2", Weight: 20, Fn: foobar, } boomer.Run(sequencialTask1, sequencialTask2) }
go build -o a.out main.go
./a.out --run-tasks foo,bar
locust -f dummy.py --master --master-bind-host=127.0.0.1 --master-bind-port=5557
go build -o a.out main.go
./a.out --master-host=127.0.0.1 --master-port=5557 --rpc=zeromq
resp, err := http.Get("http://example.com/") ... resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf) ... resp, err := http.PostForm("http://example.com/form", url.Values{"key": {"Value"}, "id": {"123"}})
func exampleGet() { start := boomer.Now() resp, err := http.Get("https://dl.google.com/go/go1.10.3.src.tar.gz") //resp, err := http.Get("https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.1.tar.gz") if err == nil { func() { defer resp.Body.Close() _, err = ioutil.ReadAll(resp.Body) }() } elapsed := boomer.Now() - start if err == nil { boomer.Events.Publish("request_success", "http", "example_get", elapsed, resp.ContentLength) } else { boomer.Events.Publish("request_failure", "http", "example_get", elapsed, err.Error()) } }
digraph locust {
nodesep=1.0 // increases the separation between nodes
node [color="red" shape=box]
edge [color="blue" style=dashed]
master [label="master (coordinator)"]
client1 [label="client 1...n" shape="oval"]
master->slave1
slave1->client1 [style=solid]
client1->server
client1->server
client1->server
client1->server
client1->server
}
digraph locust {
nodesep=1.0 // increases the separation between nodes
node [color="red" shape=box]
edge [color="blue" style=dashed]
master [label="master (coordinator)"]
client1 [label="client 1...n" shape="oval"]
client2 [label="client 1...n" shape="oval"]
master->slave1
master->slave2
slave1->client1 [style=solid]
slave2->client2 [style=solid]
client1->server
client1->server
client1->server
client1->server
client1->server
client2->server
client2->server
client2->server
client2->server
client2->server
}
digraph locust {
nodesep=1.0 // increases the separation between nodes
node [color="red" shape=box]
edge [color="blue" style=dashed]
master [label="master (coordinator)"]
client1 [label="client 1...n" shape="oval"]
client2 [label="client 1...n" shape="oval"]
client3 [label="client 1...n" shape="oval"]
master->slave1
master->slave2
master->slave3
slave1->client1 [style=solid]
slave2->client2 [style=solid]
slave3->client3 [style=solid]
client1->server
client1->server
client1->server
client1->server
client1->server
client2->server
client2->server
client2->server
client2->server
client2->server
client3->server
client3->server
client3->server
client3->server
client3->server
}
never live coding
¯\_(ツ)_/¯
never live coding
( O_o) ?
重新定義
"living" live coding
( @д@) !
just do it
( >ω•)b
"倒站即進化"
郭學聰 Hsueh-Tsung Kuo2018_08_11
Sdorica -sunset-
Rayark Careers | Make A Difference