Slide 1

Slide 1 text

通信の不安定さに悩んでいたら シュッとプロキシを書けて 改善できちゃった話 鈴⽊ 善晴 / 株式会社HRBrain 2024.06.08 Go Conference 2024

Slide 2

Slide 2 text

2 ⾃⼰紹介 ■名前 鈴⽊ 善晴 / Yoshiharu Suzuki ■所属 株式会社 HRBrain テックリード 兼 バックエンドエンジニア ■Go歴 4年

Slide 3

Slide 3 text

3 本LTのアウトカム🎁 「HTTP通信を制御するプロキシ」のGoの実装例 を知ることができる

Slide 4

Slide 4 text

4 アジェンダ 01 背景とアプローチ 02 プロキシの説明 03 まとめ

Slide 5

Slide 5 text

5 アジェンダ 01 背景とアプローチ 02 プロキシの説明 03 まとめ 0:50

Slide 6

Slide 6 text

6 弊社は、⼈事領域のSaaSを開発しています!

Slide 7

Slide 7 text

リクエストが集中すると、SSHトンネルで通信が失敗する…。 7 開発環境が不安定問題😢

Slide 8

Slide 8 text

プロキシを挟んで制御を試みる 8 同時通信を抑えれば改善できるのでは?🤔

Slide 9

Slide 9 text

9 アジェンダ 01 背景とアプローチ 02 プロキシの説明 03 まとめ 1:50

Slide 10

Slide 10 text

10 構成技術 標準(または準標準)の技術だけで、2⽇程度でプロキシを実現! ● http.RoundTripper インターフェース … 「⼀回のHTTP通信」を表すインターフェース ● golang.org/x/sync/semaphore パッケージ … セマフォの提供 💡セマフォとは? ● コンピュータの並行処理において、共有リソースのアクセスを制御し、 競合を防ぐための機構 ● カウンターを用いて、特定のリソースの利用可能数を管理する

Slide 11

Slide 11 text

11 ⼟台となるリバースプロキシを⽤意する func main() { target, _ := url.Parse("http://localhost:8080") // リバースプロキシの作成 proxy := httputil.NewSingleHostReverseProxy(target) // サーバ起動 srv := &http.Server{ Addr: ":9999", Handler: proxy, } _ = srv.ListenAndServe() }

Slide 12

Slide 12 text

12 通信に⼿を⼊れる余地を作る http.RoundTripperを加える // カスタマイズするための構造体 type c struct{} func (c *c) RoundTrip(r *http.Request) (*http.Response, error) { // 標準で用意されているデフォルト実装へ移譲するだけ return http.DefaultTransport.RoundTrip(r) } func main() { ... proxy := httputil.NewSingleHostReverseProxy(target) // プロキシの動きをカスタマイズ proxy.Transport = &c{} ... } 2:50

Slide 13

Slide 13 text

13 同時通信に上限を設定して完成🙌 semaphoreも加える type c struct { sem *semaphore.Weighted // 同時通信を制御するセマフォ } func (c *c) RoundTrip(r *http.Request) (*http.Response, error) { _ = c.sem.Acquire(r.Context(), 1) // 1通信につき1つ使う defer c.sem.Release(1) // 最後に解放 return http.DefaultTransport.RoundTrip(r) } func main() { ... proxy := httputil.NewSingleHostReverseProxy(target) proxy.Transport = &c{ sem: semaphore.NewWeighted(1), // 同時通信の上限が1の例 } ... } 󰢃 󰢃 󰢏 3:35

Slide 14

Slide 14 text

14 同時通信に上限を設定して完成🙌 semaphoreも加える type c struct { sem *semaphore.Weighted // 同時通信を制御するセマフォ } func (c *c) RoundTrip(r *http.Request) (*http.Response, error) { _ = c.sem.Acquire(r.Context(), 1) // 1通信につき1つ使う defer c.sem.Release(1) // 最後に解放 return http.DefaultTransport.RoundTrip(r) } func main() { ... proxy := httputil.NewSingleHostReverseProxy(target) proxy.Transport = &c{ sem: semaphore.NewWeighted(1), // 同時通信の上限が1の例 } ... } 󰢃 󰢃 󰢏

Slide 15

Slide 15 text

15 アジェンダ 01 背景とアプローチ 03 まとめ 02 プロキシの説明 4:20

Slide 16

Slide 16 text

16 まとめ 1. プロキシで同時通信を制御する事例を紹介 ○ 実際のソースコードはこちら󰡇 https://github.com/bellwood4486/flow-limit-proxy 2. 標準(+準標準)パッケージで⽤意されていることも多い。 なので公式ドキュメントに⽬を通すのは⼤事! ○ http.RoundTripper ○ golang.org/x/sync/semaphore 3. ⼀つのことをうまくやるツールをシュッと作れるのは ”便利!” “楽しい!”

Slide 17

Slide 17 text

We are hiring! ご清聴ありがとうございました!