Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Goとコンテナで作るWebアプリケーションベンチマーカー / Benchmarker built with Go and Container

Goとコンテナで作るWebアプリケーションベンチマーカー / Benchmarker built with Go and Container

FUJIWARA Shunichiro

June 30, 2018
Tweet

More Decks by FUJIWARA Shunichiro

Other Decks in Technology

Transcript

  1. ͳͥ΍Δͷ͔ - ੑೳධՁ / ݶքଌఆ • XXXϢʔβ·ͰͷΞΫηεʹ଱͑ΒΕΔ͔ • ໨ඪϢʔβ਺ʹ଱͑ΒΕͳ͍ =

    ͓ۚʹͳΒͳ͍ • ΠϯελϯεαΠζɺ୆਺ = ͓ۚ͸͍͘Β͔͔Δͷ͔ • ίετֻ͕͔Γ͗ͯ͢͸͍͚ͳ͍ • ϨεϙϯελΠϜ • ϢʔβʹշదͳମݧΛͯ͠΋Β͑Δ͔
  2. ͳͥ΍Δͷ͔ - ຊ൪ϦϦʔεͷ४උ ΞϓϦέʔγϣϯ / ϛυϧ΢ΣΞͷෆඋΛચ͍ग़͢ • ϘτϧωοΫݕग़ • DB

    ͷ index ͕ͳ͍ͱ͔ • ֤छઃఆ஋͕ద੾͔ • failover ͸ਖ਼ৗʹಈ࡞͢Δ͔
  3. ۩ମతʹ΍Γ͍ͨ͜ͱ REST API Λୟ͍ͯͦͷ݁ՌΛ࢖ͬͯ࣍ͷϦΫΤετ • ྫ / → /signup →

    /login → /mypage → /infomation ೝূ͕ಠࣗ • CookieͰ͸ͳ͍ HTTP ϦΫΤετϔομʹ token • ຖճ unique ͳ஋Λૹ৴ɺ࠶ૹʹΑΔଟॏϦΫΤετݕ஌ • Challenge & Response • ϦϓϨΠ߈ܸͳͲΛ๷͙
  4. ͳʹͰ΍Δͷ͔ طʹੈʹ͋Δෛՙࢼݧπʔϧ ApacheBench (ab) • Apache HTTPd ʹ෇ଐ • 1

    URL ʹͻͨ͢ΒϦΫΤετ͢Δ $ ab -c 10 -n 1000 http://example.com/
  5. wrk - ϦΫΤετΛ Lua ͰΧελϚΠζ wrk.method = "POST" wrk.body =

    "foo=bar&baz=quux" wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
  6. JMeter or Gatling ? ͲͪΒ΋ • WebSocket ͕ѻ͑Δ • JMeter͸ϓϥάΠϯ

    • γφϦΦϨίʔμʔ͕͋Δ • HTTP Proxy ͱͯ͠ಈ࡞ͯ͠ϒϥ΢βૢ࡞Λ capture ͢Δ
  7. Go Ͱࣗ࡞͢Δ ձࣾͷڞ௨ݴޠ͕ Go / Perl / Ruby (ಛʹαʔό͕ Go

    ͷ৔߹) • JSON API / WebSocket Payload ͷߏ଄ମ͕ڞ௨ʹͰ͖Δ Ϩϙʔτ͕͖Ε͍Ͱ͋Δඞཁ͸ͳ͍ • αʔόଆͷϞχλϦϯάͰ࣮ݱ͞Ε͍ͯΔඞཁ͕͋Δ • req/sec, εςʔλείʔυͷׂ߹ ϨεϙϯελΠϜ
  8. ࣮ࡍͷϕϯνϚʔΫࢼߦ func (s *Scenario) Run(ctx context.Context) (score int64) { //

    websocketܨ͙ conn, _, _ := s.client.ConnectWebsocket() defer conn.Close() // room ೖࣨ res, _ := s.client.Post("/api/room/join") EVENT: for { _, b, err := conn.ReadMessage() ev, _ := event.Decode(b) switch ev := ev.(type) { case event.RoomJoinEvent: // ...
  9. γφϦΦΛ࠷େNฒྻͰಈ͔͢ channel Λ࢖ͬͨ semaphore ύλʔϯ func Run() { sem :=

    make(chan struct{}, 100) // ࠷େ100ฒྻ for { sem <- struct{}{}: // 100 Ҏ্ʹͳΒͳ͍Α͏ʹηϚϑΥऔಘ go func() { sc := newScenario() // γφϦΦੜ੒ defer func() { <-sem // ऴΘͬͨͱ͜ΖͰηϚϑΥ։์ }() sc.Run() // ϕϯνϚʔΫ }() time.Sleep(spawnInterval) // ࣍ͷγφϦΦੜ੒͸ͪΐͬͱ଴ͭ } }
  10. sem := make(chan struct{}, 4) // □□□□ // main scenario

    sem <- struct{}{} ▪□□□ // (1) sem <- struct{}{} ▪▪□□ // (2) sem <- struct{}{} ▪▪▪□ // (3) sem <- struct{}{} ▪▪▪▪ // (4) sem <- struct{}{} ▪▪▪▪◆ // (5) ▪▪▪□ <- sem // (1) ▪▪▪▪ // (5) sem <- struct{}{} ▪▪▪▪◆ // (6) ▪▪▪□ <- sem // (2) ▪▪▪▪ // (6)
  11. ద౰ʹ(෼ࢄͯ͠) Sleep ͢Δ ͖ͬͪΓ 100ms ͣͭͣΒͯ͠͠·͏ͱ ຖඵ 0, 100, 200,

    ... 900 ms ͷλΠϛϯάʹෛՙ͕ूத͢Δ ద౰ʹฏۉ100msͰ෼ࢄ͢Δ஋ΛٻΊΔʹ͸…?
  12. Go Ͱਖ਼نཚ਺ΛٻΊΔ - math/rand func NormFloat64() float64 returns a normally

    distributed float64 in the range [-math.MaxFloat64, +math.MaxFloat64] with standard normal distribution (mean = 0, stddev = 1) sample = NormFloat64() * desiredStdDev + desiredMean
  13. rand.NormFloat64()*4 + 10 0 ########## 1 ############## 2 ############# 3

    ############################ 4 ######################################## 5 ######################################################## 6 ############################################################## 7 ################################################################################### 8 ############################################################################################### 9 ############################################################################################## 10 ############################################################################################################ 11 ############################################################################################## 12 ################################################################################## 13 ###################################################################### 14 ############################################## 15 ######################################## 16 ##################### 17 #################### 18 ######### 19 #####
  14. net/http.Get() ౳Λ࢖Θͳ͍ resp, err := http.Get("http://example.com/") ҉໧ʹ http.DefaultClient ͕࢖ΘΕΔ •

    ಉҰϗετ΁ͷϦΫΤετΛ KeepAlive ͍ͯ͠ΔίωΫγϣ ϯʹ·ͱΊͯ͠·͏ͷͰίωΫγϣϯ͕ݮΔ • ࣮ࡍʹϢʔβͷ୺຤͕ͦΕͧΕ઀ଓΛுΔঢ়گͷγϛϡϨʔ γϣϯʹͳΒͳ͍
  15. ͏͔ͬΓ HTTP/2 ʹ஫ҙ AWS ALB ͸σϑΥϧτͰ HTTP/2 ରԠ͍ͯ͠Δ net/http.Client ΋σϑΥϧτͰ

    HTTP/2 Ͱܨ͛ΔͳΒܨ͙ ࣮ࡍͷΫϥΠΞϯτ͕ HTTP/1 ͷ৔߹ͷ γϛϡϨʔγϣϯʹͳΒͳ͍ ࣮ߦ࣌ʹ؀ڥม਺ GODEBUG=http2client=0 ͰແޮԽͰ͖Δ ৄ͘͠͸ godoc.org/net/http
  16. ઀ଓΛͪΌΜͱෳ਺ுΔ http.Client Λผʹ༻ҙͨ͠৔߹ c := &http.Client{} req, _ := http.NewRequest("GET",

    "https://example.com/", nil) resp, err := c.Do(req) //... • http1 ͳΒͦΕͧΕͷΫϥΠΞϯτ͕ผͷTCP઀ଓΛ࣋ͭ • http2 ͩͱͻͱͭͷίωΫγϣϯΛ࢖͍ճ͢(!!)
  17. http.Transport Λผʑʹ࡞Ε͹ h2 Ͱ΋ผ઀ଓ c := &http.Client{ Transport: &http.Transport{}, }

    req, _ := http.NewRequest("GET", "https://example.com/", nil) resp, err := c.Do(req) //...
  18. ࣮ࡍͷϢʔβ਺෼ϕϯνϚʔΫΛ࣮ߦ͢Δ 1ϓϩηε/ϗετ͔Β઀ଓͰ͖Δྔʹ͸੍໿͕͋Δ ͨͱ͑͹10ສಉ࣌Ϣʔβͷ݁Ռ͕΄͍͠ͱͯ͠ • CPU (32ίΞͩͱͯ͠ 0.00032 core/user ͔͠࢖͑ͳ͍) •

    Memory (1MB * 10ສ = 100GB) • ଳҬ (100Kbps * 10ສ= 10 Gbps) • IP source port (16bit = 65535 Ͳ͏ؤுͬͯ΋ແཧ) ෳ਺୆ʹ෼ࢄ͢Δඞཁ͕͋Δ
  19. ΧελϜϝτϦΫεͷσʔλߏ଄ Namespace: benchmark # ໊લۭؒ MetricName: Concurrency # ϝτϦοΫ໊ Value:

    1000 # ஋ (float) Timestamp: 1528075230 # ࣌ࠁ(UNIX time) Dimensions: - Name: Scenario Value: GvG