Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
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
作るべきものと向き合う - ecspresso 8年間の開発史から学ぶ技術選定 / 技術選定con findy 2026
fujiwara3
9
4.7k
さくらのクラウドでのシークレット管理を考える/tamachi.sre#2
fujiwara3
2
340
Amazon ECS デプロイツール ecspresso の開発を支える「正しい抽象化」の探求 / YAPC::Fukuoka 2025
fujiwara3
13
12k
パフォーマンスチューニングのために普段からできること/Performance Tuning: Daily Practices
fujiwara3
9
6.7k
alecthomas/kong はいいぞ
fujiwara3
7
2.5k
ecspressoの設計思想に至る道 / sekkeinight2025
fujiwara3
12
3.7k
さくらのIaaS基盤のモニタリングとOpenTelemetry/OSC Hokkaido 2025
fujiwara3
3
4.3k
監視のこれまでとこれから/sakura monitoring seminar 2025
fujiwara3
12
5.9k
k6による負荷試験 入門から日常的な実践まで/Re:TechTalk #01
fujiwara3
2
610
Other Decks in Technology
See All in Technology
iAEONの段階的リアーキテクト戦略 / iAEON's_Gradual_Re-architecture_Strategy
aeonpeople
0
230
AI駆動開発を通して感じた、 AI時代のデザイナーの役割変化
whisaiyo
3
2.3k
2026TECHFRESH畢業分享會 - Lightning Talk - 打造精準高效的 MCP 設計模式與測試實務
line_developers_tw
PRO
0
1.2k
気軽に使える"情報のハブ"としてのNotion活用 〜フロー情報の集積点 と、 Claude Code × Notion AI〜
syucream
1
150
小さく始める AI 活用推進 ― 日経電子版 Web チームの事例/nikkei-tech-talk47
nikkei_engineer_recruiting
0
300
データサイエンスを価値につなげるプロジェクト設計 〜 DS一年目が現場で得た気づき 〜
ysd113
1
270
マルチアカウント環境での コーディングエージェントを使った障害調査が大変なので AIエージェントにReadOnly権限を付与してみた / ReadOnly AI Agents for Multi-Account AWS Incident Response
yamaguchitk333
2
110
Bucharest Tech Week 2026 - Guardians of the Cloud-Native Galaxy
edeandrea
PRO
0
110
プロダクト開発から業務改善コンサルまで。事業全体へ「染み出す」ことで広がるエンジニアの可能性
ham0215
0
140
10年間のブログ発信を振り返って見えたWebアプリケーションエンジニアとしての軌跡
stefafafan
0
150
【セミナー資料】Claude Code をセキュアに使うための考え方と設定の勘どころ / Claude Code Webinar 20260616
masahirokawahara
2
410
AIAU_UMEMOGU_ninomiya_slide
ninomiya_ii
0
220
Featured
See All Featured
Documentation Writing (for coders)
carmenintech
77
5.4k
How to make the Groovebox
asonas
2
2.2k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.2k
Accessibility Awareness
sabderemane
1
140
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
840
GraphQLとの向き合い方2022年版
quramy
50
15k
Speed Design
sergeychernyshev
33
1.9k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Become a Pro
speakerdeck
PRO
31
6k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4k
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