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
マイクロサービス時代 のHTTPクライアントの作り方 / how we build our ...
Search
LINE Developers
July 13, 2019
Technology
2k
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
マイクロサービス時代 のHTTPクライアントの作り方 / how we build our http client for microservice
Go Conference'19 Summer in Fukuokaでの登壇資料です
https://fukuoka.gocon.jp/ja/
LINE Developers
July 13, 2019
More Decks by LINE Developers
See All by LINE Developers
LINEスタンプのSREing事例集:大きなスパイクアクセスを捌くためのSREing
line_developers
3
2.5k
Java 21 Overview
line_developers
6
1.3k
Code Review Challenge: An example of a solution
line_developers
1
1.6k
KARTEのAPIサーバ化
line_developers
1
630
著作権とは何か?〜初歩的概念から権利利用法、侵害要件まで
line_developers
5
2.3k
生成AIと著作権 〜生成AIによって生じる著作権関連の課題と対処
line_developers
3
2.5k
マイクロサービスにおけるBFFアーキテクチャでのモジュラモノリスの導入
line_developers
9
3.9k
A/B Testing at LINE NEWS
line_developers
3
1.1k
LINEのサポートバージョンの考え方
line_developers
2
1.5k
Other Decks in Technology
See All in Technology
データ基盤をDataformで整えた話 〜 開発環境を添えて 〜
takapy
0
120
探して_入れて_作って_使う_Agent_Skills___LT.pdf
peintangos
2
180
Socrates × Looker 〜セマンティックレイヤーで進化するデータ分析エージェント〜
hanon52_
0
310
もりもり新機能を一挙紹介! AgentCoreに入門して、AWS上にAIエージェントを構築しよう
minorun365
PRO
6
850
いまさら聞けない人のためのAIコーディング入門
devops_vtj
0
120
AI-DLCを活用した高品質・安全なAI駆動開発実践 / AI Driven Development with AI-DLC
yoshidashingo
0
140
美味しいスイスチーズを作ろう🧀🐭
taigamikami
1
260
LLMと共に進化するプロセスを目指して
ymatsuwitter
12
3.5k
Diagnosing performance problems without the guesswork
elenatanasoiu
0
170
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/3 - 2026/5
oracle4engineer
PRO
1
210
Agentic ERPをどう設計するか ー 受発注エージェントを動かす、現場の知見と設計思想ー
recerqainc
1
1.8k
ポケモンの型をTypeScriptの型システムで表現してみた
subroh0508
0
350
Featured
See All Featured
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.3k
Art, The Web, and Tiny UX
lynnandtonic
304
22k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
200
Everyday Curiosity
cassininazir
0
220
Optimizing for Happiness
mojombo
378
71k
The Invisible Side of Design
smashingmag
302
52k
Paper Plane (Part 1)
katiecoart
PRO
0
8.6k
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Documentation Writing (for coders)
carmenintech
77
5.4k
[SF Ruby Conf 2025] Rails X
palkan
2
1.1k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Transcript
ϚΠΫϩαʔϏε࣌ ͷHTTPΫϥΠΞϯτͷ࡞Γํ @dxhuy Observability Team / LINE Corp
@dxhuy https://github.com/huydx
None
Developer
• LINEͷObservabilityνʔϜʹ͍ͭͯ • ϚΠΫϩαʔϏεͷམͱ݀͠ • ෦ͰΧελϜͨ͠HTTPΫϥΠΞϯτ ͷઃܭͱհ ࠓͷ
Engineering LINE’S OBSERVABILITY TEAM
Engineering OBSERVABILITY IS NEW WAVE
Πϝʔδతʹ ࣾDATADOGΛ࡞͍ͬͯΔ
Engineering Log ج൫ Metric ج൫ ࢄ τϨʔγ ϯάج൫ ZipkinͷOSS ίϯτϦϏϡʔτ
Engineering GO͍ͬͯΔͷʁ Metric Agent Time Series Storage Metric API Server
͜Ε͔Β࡞Δͷ ͲΜͲΜGO࠾༻ʂ CLI tool Metric Alert Engine
> 1.000.000 metrics per sec εέʔϧνϟϨϯδ
> 2.000 read per sec εέʔϧνϟϨϯδ
Engineering Metrics૿Ճ Ϗδωεεέʔϧ
Engineering GOPHERੵۃ࠾༻தʂ ιϑτΣΞΤϯδχΞ (Software EngineerɺEngineering Efficiency)ʲLINEϓϥοτϑΥʔϜʳ
Engineering ࠓͷຊ
Engineering ϚΠΫϩαʔϏε ͍ͬͯ·͔͢
Engineering ίϛϡχέʔγϣϯ(RPC) ͕େࣄ
Engineering twitch/Twirp GRPC Thrift REST Http RPCख๏͕༷ʑ ࠓޙ૿͑ͦ͏
Engineering GRPC, THRIFTͳͲશͯͷ γεςϜΛม͑ͳ͍ͱߦ͚ͳ͍
Engineering ͢Ͱʹଘࡏ͍ͯ͠Δ APIαʔϏε͕ࠞࡏ net/http͕ఆ൪
Engineering NET/HTTPͪΐͬͱ Γͳ͍
Engineering ϚΠΫϩαʔϏε௨৴ͷ ΫϥΠΞϯτඞཁͳੑ࣭
Engineering αʔϏεͷελοΫ ωοτϫʔΫԆ ϦΫΤετࣦഊ αʔϏεಥવؾઈ https://www.flickr.com/photos/chrish_99/8526019374/
Engineering https://www.flickr.com/photos/chrish_99/8526019374/
Engineering ϦϞʔτίʔϧ͕ࣦഊ͠ ͯճ෮Ͱ͖ΔΑ͏ʹͳ Δ ࣮ύλʔϯ - Retry - CircuitBreaker ճ෮ੑ
ίʔϧઌ͕ࢄͰ͖ΔΑ ͏ʹͳΔ ࣮ύλʔϯ - Load Balancing - Service Discovery ߴՄ༻ੑ ࢲ͕ཉ͍͠ HTTPΫϥΠΞϯτ
Engineering • CircuitBreaker, RetryͳͲ͕ἧ͏ύοέʔδͳͲଘࡏ͢Δ͕ • Ұͭͷػೳ͔͍࣋ͬͯ͠ͳ͍ͷ͕ଟ͍ • ඪ४ͷnet/httpͷΠϯλʔϑΣʔεʹ૬ੑѱ͍ɺίʔυϕʔεͷม ߋ͕ଟ͘ͳΔ •
BoilerPlate͕ଟ͍ • ύϑΥʔϚϯεྑ͘ͳ͍ • ֎෦dependencies͕ଟ͍ • ྫɿgojek/heimdall, go-kitܥͷϥΠϒϥΠͳͲ ͭ·ΓΧελϜNET/HTTP ΫϥΠΞϯτཉ͍͠
Engineering ࣾͰΧελϜNET/HTTP ࡞Γ·ͨ͠
Engineering XHTTPύοέʔδ ઃܭͱ͍ํͷհ
Engineering • ඪ४ͷnet/httpͷΠϯλʔϑΣʔεͰ͖Δ͚ͩै͏ • ͏ଆʢϢʔβʣͷมߋΛ࠷খݶʹ͢Δ • net/httpͷϥούϥΠϒϥϦͱͯ͠ • ඞཁͳͷશ෦ἧ͏ •
ճ෮ੑɺߴՄ༻ੑͷػೳΛἧ͏ • ϝτϦΫεɺTracingͷػೳΛἧ͏ • ଥͳσϑΥϧτʢλΠϜΞτͳͲʣ ઃܭࢥߟ
Engineering package xhttp type ClientConfig struct {…} func NewClient(config *ClientConfig)
*Client {} func NewRequestX(method string, addr *AddressGroup, path string, body io.Reader) (*Request, error) func (c *Client) DoX(req *Request, option ...CallOption) (*Response, error) func (c *Client) PostX(addr *AddressGroup, path string, contentType string, body io.Reader, options ...CallOption) (resp *Response, err error) { func (c *Client) PostFormX(addr *AddressGroup, path string, data url.Values, options ...CallOption) (resp *Response, err error) func (c *Client) GetX(addr *AddressGroup, path string, options ...CallOption) (resp *Response, err error) { NET/HTTPͱಉ͡ΠϯλʔϑΣΠε
Engineering addrGroup := xhttp.MustNewAddressGroup( //AddressGroup͋ͱ΄Ͳհ͠·͢ “dns: //txt:your-domain.com:8080”, xhttp.WithLoadBalancer(xhttp.RoundRobin), ) reqP,
_ := xhttp.NewRequestX("POST", addrGroup, "/", nil) res, err = client.DoX(reqG) res, err = client.PostFormX(addrGroup, "/", url.Values{}) res, err = client.GetX(addrGroup, "/") ͍ํͷΠϝʔδ
Engineering ߴՄ༻ੑͷ
Upstream 2 die xhttp client Upstream 1 αʔό͍ͭͰࢮ͵Մೳੑ Upstream 3
Engineering • ීஈ Reverse Proxy (VIP)ͳͲར༻͕ଟ͍ • ৽͍͠αʔϏεՃΛ͢Δͨͼʹ৽͍͠ Reverse Proxyಋೖ͢Δ
ͷ͕໘ • Solution • Client Side Load Balancing • ΫϥΠΞϯτίʔϧઌͷαʔόάϧʔϓΛࣗͰίϯτϩʔ ϧ͢Δ͜ͱ • ΫϥΠΞϯτίʔϧઌͷαʔόάϧʔϓɺͲΕΛݺͼग़͢ͷ ͔ͷϩʔυόϥϯγϯάϩδοΫΛ࣮͢Δ͜ͱ αʔόάϧʔϓ͕ඞཁ
Engineering type Address struct { Port string Host string }
type AddressGroup struct { scheme Scheme name string resolver Resolver loadBalancer LoadBalancer cacheAddress []Address closeCh chan interface{} } AddressGroup ʢαʔόάϧʔϓͷநԽʣ
Engineering type Resolver interface { Scheme() Scheme Init(address string) error
UpdateCh(context.Context) <-chan []Address Close() } type LoadBalancer interface { Pick() (Address, error) HandleStateChange(list []Address) error } Resolver + LoadBalancer
Engineering type DnsResolver struct { domain string updateCh chan []Address
doneCh chan interface{} } func (d *DnsResolver) Scheme() Scheme { return Scheme("dns") } func (d *DnsResolver) Init(name string) error { d.resolve() } func (d *DnsResolver) resolve() { go func() { // resolve d.domain d.updateCh <- addresses time.Sleep(TTL) } } Example: DnsResolve
Engineering type roundRobinLB struct { list []Address next uint32 mu
sync.RWMutex } func (rr *roundRobinLB) Pick() (Address, error) { l := len(rr.list) if l == 0 { return Address{}, fmt.Errorf("empty list of address") } v := atomic.AddUint32(&rr.next, 1) return rr.list[int(v)%len(rr.list)], nil } func (rr *roundRobinLB) HandleStateChange(list []Address) error { rr.mu.Lock() defer rr.mu.Unlock() rr.list = list return nil } Example: Round Robin LB
Engineering ͏ଆBOILER PLATE͕΄ͱΜͲͳ͍ addrGroup := xhttp.MustNewAddressGroup( //AddressGroup͋ͱ΄Ͳհ͠·͢ “dns: //txt:your-domain.com:8080”, xhttp.WithLoadBalancer(xhttp.RoundRobin),
) reqP, _ := xhttp.NewRequestX("POST", addrGroup, "/", nil) ϥΠϒϥϦଆͰ schemeύʔεͯ͠Resolver ΛΞαΠϯ͢Δ
Engineering • Load Balancing is impossible • https://www.youtube.com/watch?v=kpvbOzHUakA • Round
Robin Upstreamϗετͷঢ়ଶʢLatency, Φʔόϩʔυঢ় گʣͳͲΛҙࣝͰ͖ͣɺͣͬͱಉ͡ѱ͍ঢ়ଶͷϗετʹಉ͡ϦΫΤε τΛ͛Δɹ • P2C ΞϧΰϦζϜ • Power of 2 Random Choice • Upstreamͷঢ়ଶΛୡඞཁ͋Δ • https://www.eecs.harvard.edu/~michaelm/postscripts/mythesis.pdf ༨ஊ ϩʔυόϥγϯάΞϧΰϦζϜ͍͠
Engineering ճ෮ੑͷ
Engineering Upstream 2 die xhttp client Upstream 1 αʔό͍ͭͰࢮ͵Մೳੑ Upstream
3
Engineering Upstream 2 die xhttp client Upstream 1 die (શʣαʔό͍ͭͰࢮ͵Մೳੑ
Upstream 3 die
Engineering • શʹࢮ͵͡Όͳͯ͘ɺ(GCͳͲͷཧ༝ͰʣLatency͕Ͷ্͕Δ • దͳσϑΥϧτλΠϜΞτ͕ඞཁ • ଈ࣌తͳϦΫΤετࣦഊ (500ΤϥʔͳͲʣ • దͳϦτϥΠ
• ܧଓతͳϦΫΤετࣦഊ (ωοτϫʔΫࣦഊͳͲʣ • Ͱ͖Δ͚ͩૣ͍ஈ֊ͰϦΫΤετΛυϩοϓ͢Δ • CircuitBreakerύʔλϯɿFail Fast Error αʔό͕ࢮ͵ͱ͖Ͳ͏͠·͢ʁ
Engineering • net/httpσϑΥϧτλΠϜΞτ͋Γ·ͤΜʂ • ແݶʹϦΫΤετͭ • xhttpͰσϑΥϧτͰ30sઃఆՄೳɺ֎͔Β͢ͷՄೳ λΠϜΞτʹ͍ͭͯ func NewClient(config
*ClientConfig) *Client { client.client = &http.Client{ Timeout: config.RequestTimeout, Transport: newRoundTripper(config.RoundTripper, config.MetricRegistry), }… }
Engineering Dial TLS Handshake Request Resp Headers Resp Body Idle
Client.Do http.Client.Timeout net.Dialer.Timeout http.Transport.TLSHandshake.Timeout http.Transport.ResponseHeader.Timeout http.Transport.IdleConn.Timeout https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/ ߹ʹΑΓࡉ͔͘ίϯτϩʔϧՄೳ
Engineering • Լखʹretry͢Δ͜ͱʹࣾαʔϏεΛDDOS͢Δ͜ͱ • ඞͣ Backoff ( Exponential )͢Δ͜ͱ •
RetryϦΫΤετείʔϓͷOption (ClientείʔϓͰ͋Γ·ͤΜʣ RETRYʹ͍ͭͯ res, err = client.DoX(reqG, xhttp.WithRetry(&xhttp.RetryOptions{ MaxAttempts: 2, RetryOn: func(response *http.Response) bool { return response.StatusCode != 200 }, TimeoutPerAttempt: time.Second, }))
Engineering • ૣ͍ஈ֊Ͱυϩοϓ͢Δख๏ͷҰͭͱͯ͠ CircuitBreakerύλʔϯɹ • https://engineering.linecorp.com/ja/blog/circuit-breakers-for- distributed-services/ • ϗετͷঢ়ଶΛʮࣦഊ͢ΔϦΫΤετͷʯͰஅ •
ʮࣦഊʯఆٛࣗମϢʔβʹͤΔ • ঢ়ଶʹΑΓʮϦΫΤετՄೳʯͱʮϦΫΤετෆՄೳʯͰ͚Δ • ϦΫΤετෆՄೳͷ߹୯७ʹ FailFastErr ฦ͢ FAIL FASTରࡦʹ͍ͭͯ
Engineering • ׂͱύϥϝʔλ͕ଟ͍ͷͰɺΞϧΰϦζϜࣗମΛཧղ͢Δ্ઃఆ͢Δ ඞཁ͕͋Δ CIRCUIT BREAKER type CircuitBreakerConfig struct {
noop bool FailureRateThreshold float64 MinimumRequestThreshold int64 TrialRequestInterval time.Duration CircuitOpenWindow time.Duration CounterSlidingWindow time.Duration CounterUpdateInterval time.Duration IsFailed FailedJudger KeyBuilder KeyBuilder } client := xhttp.NewClient(&xhttp.ClientConfig{ CircuitBreakerConfig: &xhttp.CircuitBreakerConfig{}, })
Engineering • > ϗετͷঢ়ଶΛʮࣦഊ͢ΔϦΫΤετͷʯͰஅ • Ͳ͏ͬͯૣ͑͘Δʁ ༨ஊɹHIGH PERFORMANCE CIRCUITBREAKERͷͨΊʹ var
c int64 c ++ var c atomic.Int64 c.Add(1) • AtomicͬͯcontentionมΘΒͳ͍ʢಉ͡มʹࢀর͢Δ͜ͱʣ • https://github.com/linxGnu/go-adder • Java LongAdderͷΞΠσΟΞʢatomicΛsharding) • ϚϧνϧʔνϯڥͰatomic.Int64ΑΓ2~4ഒૣ͍
Engineering METRICS/TRACINGͷ
Engineering • ObservabilityνʔϜͳͷͰͦͷॏཁੑΛ͘͢͝ཧղ͍ͯ͠Δ • ͑ͳ͍ͱ͍͚ͳ͍ͷ • ϦΫΤετLatencyߴ͍Ͱ͔͢ʁ • Latencyߴ͍࣌ͳͥʁ OBSERVABILITYͷॏཁੑ
• Latencyߴ͍͔Ͳ͏͔MetricsͰ͑Δ • Metrics Instrumentation prometheus client ͏ • ͳͥʁΛ͑Δͷ Metrics + TracingͰ͑Δ • Tracing Instrumentation zipkin-go
Engineering ROUNDTRIPPERར༻ͯ͠INSTRUMENT type ClientConfig struct { MetricRegistry *prometheus.Registry Tracer *zipkin.Tracer
…… } func newRoundTripper(originRt http.RoundTripper, mr *prometheus.Registry, tc *zipkin.Tracer) *roundtripper { … .. } client.client = &http.Client{ Timeout: config.RequestTimeout, Transport: newRoundTripper(config.RoundTripper, config.MetricRegistry, config.Tracer), }
Engineering • ΧελϚΠζ͢ΔͨΊͷϑοΫ • ϦΫΤετૹΔॲཧΛΧελϚΠζɿ RoundTripperΛ͢ • ίωΫγϣϯΛ࡞ΔॲཧΛΧελϚΠζɿDialContextΛ͢ ༨ஊɹNET/HTTPࢁ ϑοΫఏڙͯ͘͠ΕͯΔ
• ϝτϦΫεΛऔಘ͢ΔͨΊͷϑοΫ • http/ClientTraceेɹ • https://blog.golang.org/http-tracing
Engineering ࠷ޙ
Engineering • Ͱ͖Εࣾɺ͋Δ͍νʔϜڞ௨ͷϥΠϒϥϦἧͬͨ΄͏͕ྑ͍ • http client, log package, metrics instrument…
• ϚΠΫϩαʔϏε͍͠ɺͰ͖Εආ͚ͨ΄͏͕ྑ͍ • ͍ۙ͏ͪʹxhttpΛOSS͢Δ • go͖ͰɺେنγεςϜΛ࡞Γ͍ͨਓ͝࿈བྷ͓ͪͯ͠Γ·͢
Engineering ͝੩ௌ͋Γ͕ͱ͏͍͟͝·͢