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
600
クラウドを使う側から、作る側へ / 大吉祥寺.pm 2026前夜祭
fujiwara3
8
2.2k
作るべきものと向き合う - ecspresso 8年間の開発史から学ぶ技術選定 / 技術選定con findy 2026
fujiwara3
9
6.4k
さくらのクラウドでのシークレット管理を考える/tamachi.sre#2
fujiwara3
2
430
Amazon ECS デプロイツール ecspresso の開発を支える「正しい抽象化」の探求 / YAPC::Fukuoka 2025
fujiwara3
13
14k
パフォーマンスチューニングのために普段からできること/Performance Tuning: Daily Practices
fujiwara3
9
7k
alecthomas/kong はいいぞ
fujiwara3
7
2.7k
ecspressoの設計思想に至る道 / sekkeinight2025
fujiwara3
12
3.9k
さくらのIaaS基盤のモニタリングとOpenTelemetry/OSC Hokkaido 2025
fujiwara3
4
5.8k
Other Decks in Technology
See All in Technology
AIに任せられるFlutterコードベースを作る 〜仕様をコードで表し、ハーネスで守る〜
myohei
1
630
Systems Manager AgentがインストールされたPCを紛失した時の対策を考えてみた
amarelo_n24
1
110
構造で守らせる データ・法務・セキュリティ・開発チームとつくる AI時代のデータガバナンスとデータ基盤のリアル
legalontechnologies
PRO
3
780
新米を「売り越さない」、Aurora DSQLで作る在庫ゼロ死守の限定ドロップEC
yama3133
0
150
コードレビューをなくして見えたもの
henteko
0
130
AI Search (Foundry IQ) におけるRAGデータの準備と配置
ryomaru0825
1
140
Flutter Widget Previewerで始めるUIプレビューとVRTの自動化
sakusaku3939
0
200
【Oracle AI SPOTLIGHT ウェビナー】事例から見る!なぜOCIが選ばれたのか ― AI時代のクラウド戦略を紐解く ―
oracle4engineer
PRO
2
150
"AWSはちょっと苦手"でも大丈夫。AWS Blocks で手軽に作る Flutter のバックエンド #FlutterKaigi
tacck
PRO
0
130
推論基盤と Scale-Up Interconnect の現状と制約から俯瞰する技術動向
markunet
2
780
なぜAI時代に技術記事を書くのか?どう書くのか? 〜bunの場合〜
kworkdev
PRO
0
4.6k
Copilot Coworkで「みのるん式」やってみた
minorun365
PRO
2
1.4k
Featured
See All Featured
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
470
Into the Great Unknown - MozCon
thekraken
41
2.8k
Abbi's Birthday
coloredviolet
4
11k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
2
430
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
RailsConf 2023
tenderlove
30
1.6k
How Software Deployment tools have changed in the past 20 years
geshan
2
35k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
620
The untapped power of vector embeddings
frankvandijk
2
2k
BBQ
matthewcrist
90
10k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
3k
Mobile First: as difficult as doing things right
swwweet
225
10k
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