Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Goとコンテナで作るWebアプリケーションベンチマーカー / Benchmarker buil...
Search
FUJIWARA Shunichiro
June 30, 2018
Technology
5.5k
9
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Goとコンテナで作るWebアプリケーションベンチマーカー / Benchmarker built with Go and Container
FUJIWARA Shunichiro
June 30, 2018
More Decks by FUJIWARA Shunichiro
See All by FUJIWARA Shunichiro
多摩川(.dev)ランニング入門 / Tamagawa.dev#3
fujiwara3
3
520
クラウドを使う側から、作る側へ / 大吉祥寺.pm 2026前夜祭
fujiwara3
8
2.1k
作るべきものと向き合う - ecspresso 8年間の開発史から学ぶ技術選定 / 技術選定con findy 2026
fujiwara3
9
6.1k
さくらのクラウドでのシークレット管理を考える/tamachi.sre#2
fujiwara3
2
400
Amazon ECS デプロイツール ecspresso の開発を支える「正しい抽象化」の探求 / YAPC::Fukuoka 2025
fujiwara3
13
14k
パフォーマンスチューニングのために普段からできること/Performance Tuning: Daily Practices
fujiwara3
9
6.9k
alecthomas/kong はいいぞ
fujiwara3
7
2.6k
ecspressoの設計思想に至る道 / sekkeinight2025
fujiwara3
12
3.8k
さくらのIaaS基盤のモニタリングとOpenTelemetry/OSC Hokkaido 2025
fujiwara3
4
5.5k
Other Decks in Technology
See All in Technology
AI に書かせたその API、 “信頼” できますか?
nagix
0
110
Railsのように考える: See through the Master
snoozer05
PRO
3
890
生成AIエージェントを用いた、 手動テスト手順書から自動テストへの 変換手法の検討
magicpod
0
160
Claude Code本って、 読む必要あるの?
oikon48
2
460
MCPをつなげて作る組織横断のAIエージェント基盤(の開発工程)
tsubakimoto_s
0
130
現場で役立つ技術負債の効果的な返済方法
masuda220
PRO
8
4.2k
絵ではじめるKubernetesセキュリティ
aoi1
3
590
AIネイティブプロダクトで顧客価値を最大化するプロダクトエンジニアとFDEの協働
righttouch
PRO
0
310
10分で知る最近のOmarchy
komagata
0
340
GoにおけるFFIのこれまでとこれから
goccy
5
3.5k
山手線を徒歩で一周してわかった、 位置情報アプリは「足」が最強のデバッガー
hinakko
0
160
30座EKS, 180次升級淬煉的EKS Upgrade Skill 的歷程
eric8230
0
160
Featured
See All Featured
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
410
Rebuilding a faster, lazier Slack
samanthasiow
85
9.6k
Exploring anti-patterns in Rails
aemeredith
4
510
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
240
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
Typedesign – Prime Four
hannesfritz
42
3.2k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
420
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
720
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
990
Transcript
Hackers Champloo 2018 GoͱίϯςφͰ࡞Δ WebΞϓϦέʔγϣϯ ϕϯνϚʔΧʔ 2018.06.30 @fujiwara
@fujiwara ٕज़෦ github.com/fujiwara sfujiwara.hatenablog.com ISUCON 8 ग़νʔϜ
Game & Community
None
Γ͍ͨ͜ͱ Perl / Go + WebSocket Ͱߏ͞Εͨ ήʔϜαʔόʹରͯ͠ ϕϯνϚʔΫΛֻ͚͍ͨ
ͳͥΔͷ͔ - ੑೳධՁ / ݶքଌఆ • XXXϢʔβ·ͰͷΞΫηεʹ͑ΒΕΔ͔ • ඪϢʔβʹ͑ΒΕͳ͍ =
͓ۚʹͳΒͳ͍ • ΠϯελϯεαΠζɺ = ͓͍ۚ͘Β͔͔Δͷ͔ • ίετֻ͕͔Γ͍͚͗ͯ͢ͳ͍ • ϨεϙϯελΠϜ • ϢʔβʹշదͳମݧΛͯ͠Β͑Δ͔
ͳͥΔͷ͔ - ຊ൪ϦϦʔεͷ४උ ΞϓϦέʔγϣϯ / ϛυϧΣΞͷෆඋΛચ͍ग़͢ • ϘτϧωοΫݕग़ • DB
ͷ index ͕ͳ͍ͱ͔ • ֤छઃఆ͕ద͔ • failover ਖ਼ৗʹಈ࡞͢Δ͔
ͳͥΔͷ͔ - ຊ൪ϦϦʔεͷ४උ ϞχλϦϯά͕ద͔Λચ͍ग़͢ • ΄͍͠ϝτϦΫε͕ऩूͰ͖͍ͯΔ͔ • ݟ͍ͨάϥϑ͕͙͢ݟΒΕΔ͔ • ϘτϧωοΫ͕దʹݕͰ͖Δ͔
• ΞϥʔτͷᮢΛܾΊΔ
۩ମతʹΓ͍ͨ͜ͱ REST API Λୟ͍ͯͦͷ݁ՌΛͬͯ࣍ͷϦΫΤετ • ྫ / → /signup →
/login → /mypage → /infomation ೝূ͕ಠࣗ • CookieͰͳ͍ HTTP ϦΫΤετϔομʹ token • ຖճ unique ͳΛૹ৴ɺ࠶ૹʹΑΔଟॏϦΫΤετݕ • Challenge & Response • ϦϓϨΠ߈ܸͳͲΛ͙
۩ମతʹΓ͍ͨ͜ͱ ήʔϜͷਐߦʹ WebSocket ͕ΘΕ͍ͯΔ • ଞͷϢʔβ͕ൃੜͤͨ͞Πϕϯτ͕ WebSocket Ͱ߱ͬͯ͘ Δ •
Payload MessagePack • ͦͷΠϕϯτʹΑͬͯϦΫΤετΛม͑Δඞཁ͕͋Δ
ͳʹͰΔͷ͔ طʹੈʹ͋Δෛՙࢼݧπʔϧ ApacheBench (ab) • Apache HTTPd ʹଐ • 1
URL ʹͻͨ͢ΒϦΫΤετ͢Δ $ ab -c 10 -n 1000 http://example.com/
ͳʹͰΔͷ͔ wrk github.com/wg/wrk • ApachBench ΑΓߴػೳ $ wrk -c 10
-d 3 http://example.com/
wrk - ϦΫΤετΛ Lua ͰΧελϚΠζ wrk.method = "POST" wrk.body =
"foo=bar&baz=quux" wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
ͬͱߴػೳͳπʔϧ Apache JMeter - jmeter.apache.org • Java • GUI ͕͋Δ
• γφϦΦ GUI or XML (jmx)
Gatling - gatling.io • Scalar • γφϦΦ Scala Ͱهड़
JMeter or Gatling ? ͲͪΒ • WebSocket ͕ѻ͑Δ • JMeterϓϥάΠϯ
• γφϦΦϨίʔμʔ͕͋Δ • HTTP Proxy ͱͯ͠ಈ࡞ͯ͠ϒϥβૢ࡞Λ capture ͢Δ
Go Ͱࣗ࡞͢Δ ձࣾͷڞ௨ݴޠ͕ Go / Perl / Ruby (ಛʹαʔό͕ Go
ͷ߹) • JSON API / WebSocket Payload ͷߏମ͕ڞ௨ʹͰ͖Δ Ϩϙʔτ͕͖Ε͍Ͱ͋Δඞཁͳ͍ • αʔόଆͷϞχλϦϯάͰ࣮ݱ͞Ε͍ͯΔඞཁ͕͋Δ • req/sec, εςʔλείʔυͷׂ߹ ϨεϙϯελΠϜ
ͲͷΑ͏ʹ࡞Δ͔
ΞʔΩςΫνϟ
ϕϯνϚʔΫΫϥΠΞϯτ net/http.Client, gorilla/websocket.Dialer Λ࣋ͭ type Client struct { client *http.Client
wsDialer *websocket.Dialer // ... }
γφϦΦΛ͋ΒΘ͢ struct Client Λ࣋ͭ type Scenario struct { client *bench.Client
// ... }
࣮ࡍͷϕϯνϚʔΫࢼߦ 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: // ...
γφϦΦΛ࠷େ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) // ࣍ͷγφϦΦੜͪΐͬͱͭ } }
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)
࣮Ͱҙ͢Δ͜ͱ
Ұؾʹىಈ͠ͳ͍ 1msֻ͔͔͠Βͳ͍ϦΫΤετΛ1ඵ͝ͱʹ࣮ߦ͢ΔγφϦΦΛ × 1000ฒྻͰ࣮ߦ͠ଓ͚Δ߹ Ұؾʹىಈ͢Δͱຖඵ࠷ॳͷmsʹෛՙ͕ूத͢Δ ࣮ࡍͷϢʔβͷϦΫΤετঢ়گͱҟͳΔ (…ͱݶΒͳ͍͚Ͳ)
దʹ(ࢄͯ͠) Sleep ͢Δ ͖ͬͪΓ 100ms ͣͭͣΒͯ͠͠·͏ͱ ຖඵ 0, 100, 200,
... 900 ms ͷλΠϛϯάʹෛՙ͕ूத͢Δ దʹฏۉ100msͰࢄ͢ΔΛٻΊΔʹ…?
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
rand.NormFloat64()*4 + 10 0 ########## 1 ############## 2 ############# 3
############################ 4 ######################################## 5 ######################################################## 6 ############################################################## 7 ################################################################################### 8 ############################################################################################### 9 ############################################################################################## 10 ############################################################################################################ 11 ############################################################################################## 12 ################################################################################## 13 ###################################################################### 14 ############################################## 15 ######################################## 16 ##################### 17 #################### 18 ######### 19 #####
net/http.Get() ΛΘͳ͍ resp, err := http.Get("http://example.com/") ҉ʹ http.DefaultClient ͕ΘΕΔ •
ಉҰϗετͷϦΫΤετΛ KeepAlive ͍ͯ͠ΔίωΫγϣ ϯʹ·ͱΊͯ͠·͏ͷͰίωΫγϣϯ͕ݮΔ • ࣮ࡍʹϢʔβͷ͕ͦΕͧΕଓΛுΔঢ়گͷγϛϡϨʔ γϣϯʹͳΒͳ͍
͏͔ͬΓ HTTP/2 ʹҙ AWS ALB σϑΥϧτͰ HTTP/2 ରԠ͍ͯ͠Δ net/http.Client σϑΥϧτͰ
HTTP/2 Ͱܨ͛ΔͳΒܨ͙ ࣮ࡍͷΫϥΠΞϯτ͕ HTTP/1 ͷ߹ͷ γϛϡϨʔγϣϯʹͳΒͳ͍ ࣮ߦ࣌ʹڥม GODEBUG=http2client=0 ͰແޮԽͰ͖Δ ৄ͘͠ godoc.org/net/http
ଓΛͪΌΜͱෳுΔ http.Client Λผʹ༻ҙͨ͠߹ c := &http.Client{} req, _ := http.NewRequest("GET",
"https://example.com/", nil) resp, err := c.Do(req) //... • http1 ͳΒͦΕͧΕͷΫϥΠΞϯτ͕ผͷTCPଓΛ࣋ͭ • http2 ͩͱͻͱͭͷίωΫγϣϯΛ͍ճ͢(!!)
http.Transport Λผʑʹ࡞Ε h2 Ͱผଓ c := &http.Client{ Transport: &http.Transport{}, }
req, _ := http.NewRequest("GET", "https://example.com/", nil) resp, err := c.Do(req) //...
ϢʔβͷΞΫηεΛͨ͠ϕϯνϚʔΫʹ͢Δ ؾͮͨ͘Ίʹ • αʔόଆͷίωΫγϣϯΛϞχλϦϯά͢Δ • ΞΫηεϩάʹΫϥΠΞϯτͷ IP ΞυϨε͚ͩͰͳ͘ɺ port ग़ྗ͢Δ
• ಉҰ port ͕͍ճ͞Ε͍ͯΔ༷ࢠ͕͔Δ ϕϯνϚʔΫΛਖ਼֬ʹ͢Δ = ϞχλϦϯάେࣄ
࣮ࡍͷϢʔβϕϯνϚʔΫΛ࣮ߦ͢Δ 1ϓϩηε/ϗετ͔ΒଓͰ͖Δྔʹ੍͕͋Δ ͨͱ͑10ສಉ࣌Ϣʔβͷ݁Ռ͕΄͍͠ͱͯ͠ • CPU (32ίΞͩͱͯ͠ 0.00032 core/user ͔͑͠ͳ͍) •
Memory (1MB * 10ສ = 100GB) • ଳҬ (100Kbps * 10ສ= 10 Gbps) • IP source port (16bit = 65535 Ͳ͏ؤுͬͯແཧ) ෳʹࢄ͢Δඞཁ͕͋Δ
Amazon ECS Ͱ ϕϯνϚʔΫΛେྔ࣮ߦ
ϕϯνϚʔΫ༻ͷ ECS Ϋϥελ(EC2 Πϯελϯεͷଋ) Λ༻ҙ ͦ͜ʹλεΫ(ίϯςφ্Ͱಈ͘ϓϩηε)Λෳ࣮ߦ
ϕϯνΫϥΠΞϯτଆͷϝτϦΫεΛͲ͏औΔ͔ 1ϓϩηεͰ͋Ε 1000ฒྻͰ࣮ߦ = 1000ฒྻ࣌ͷෛՙ ෳϓϩηεΛঃʑʹىಈͯ͠ɺঃʑʹෛՙΛ্͍͛ͯ͘߹ ݱࡏԿฒྻͰಈ͍ͯΔ? ͔ΛՄࢹԽ͢Δඞཁ͕͋Δ e.g. 1,000
→ 10,000ฒྻ·Ͱͳ͠ɺ12,000ʹͨ͠Β XXX ͕ աෛՙʹͳͬͯΤϥʔൃੜɺͳͲΛه͍ͨ͠
None
Amazon CloudWatch ͰΧελϜϝτϦΫεΛه͢Δ ϦιʔεͷϞχλϦϯάͷͨΊͷϚωʔδυαʔϏε AWS Ͱಈ࡞͍ͯ͠ΔαʔϏεɺίϯϙʔωϯτͷϝτϦΫε͕ େ͜͜ʹه͞Ε͍ͯΔ EC2 CPU, ELB
Request, RDS... ଞ͋ΒΏΔͷ
ΧελϜϝτϦΫεͷσʔλߏ Namespace: benchmark # ໊લۭؒ MetricName: Concurrency # ϝτϦοΫ໊ Value:
1000 # (float) Timestamp: 1528075230 # ࣌ࠁ(UNIX time) Dimensions: - Name: Scenario Value: GvG
Dimensions? σʔλͷूܭͷͨΊͷϝλσʔλ ಉ࣌ؒ͡(ଳ)ʹొ͞Εͨෳͷʹରͯ͠ Dimension ͝ͱʹ ߹ܭ, ࠷େ, ࠷খ, Percentile, σʔλݸ
Λूܭͨ݁͠ՌΛऔಘͰ͖Δ
ͳͥ CloudWatch ͕ίϯςφڥͷϝτϦΫε ूܭʹ͍͍ͯΔ͔ ίϯςφಉ࣌ʹ͍࣮ͭ͘ߦ͞ΕΔ͔͔Βͳ͍ ͦΕͧΕͷίϯςφ͓ޓ͍ͷ͜ͱΒͳ͍ ࣗࣗͷϝτϦΫεΛ CloudWatch ʹ͛Δ CloudWatch
ಉҰ࣌ࠁ ಉҰ Dimension ͷΛूܭͰ͖Δ ϝτϦΫε͕͍ͭ͋ͬͯؔ͘ͳ͍
ҙຯͷ͋ΔूܭΛ͢Δ ͲͷΑ͏ʹूܭ͢ΔͱΞϓϦέʔγϣϯతʹ ҙຯͷ͋Δ͕ಘΒΕΔ͔ਓ͕ؒߟ͑Δඞཁ͕͋Δ • ϦΫΤετɺಉ࣌ଓ = ߹ܭ • ϨΠςϯγ =
ฏۉɺPercentile
https://2018.cedec.cesa.or.jp/session/108 2018.08.22 (ਫ) - 08.24 (ۚ) ύγϑΟίԣ
ΦϯϥΠϯ༧બ 9݄15(),16() ຊબ 10݄20() ༏উۚ100ສԁ ֶੜɺ͓Ұਓ༷ࢀՃ͋Γ
None