Slide 1

Slide 1 text

net/httpからnet.Connを 掘り起こす Go Conference mini 2023 Winter IN KYOTO 尾上 寛弥 / Onoe Hiroya X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 1

Slide 2

Slide 2 text

⾃⼰紹介 尾上 寛弥 / Onoe Hiroya 京⼤情報学研究科M1 クラウド技術とかネットワークの研究してます Go歴は3年 X: @hiroyanoe GitHub: hiroyaonoe Website: https://onoe.dev X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 2 ↓京都なアイコン

Slide 3

Slide 3 text

net/httpとは? HTTP通信に使えるパッケージ http.Client X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 3 http.Server 標準パッケージだけでもHTTPサーバーが簡単に書ける

Slide 4

Slide 4 text

net.Connとは? ストリーム志向のコネクションを表すInterface (パケット志向→PacketConn) 実装例 • TCPConn • UDPConn • IPConn • UNIXConn X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 4

Slide 5

Slide 5 text

net/httpとnet.Conn HTTPの持続的接続:コネクションを使いまわせる Client:良い感じにnet.Connをプールして使い回す Server:切断するまでnet.Connを保持する コネクション確⽴のオーバーヘッドを減らせる Client, Serverの構造体は複数のnet.Connを保持 →net.Connは隠蔽されていてアクセスできない X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 5

Slide 6

Slide 6 text

net/httpからnet.Connを掘り起こす http.Client,Serverが持つnet.Connにアクセスしたい net.ConnをRead, Writeしたい X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 6

Slide 7

Slide 7 text

net/httpからnet.Connを掘り起こす http.Client/Serverが持つnet.Connにアクセスしたい net.ConnをRead, Writeしたい そんなこと必要? X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 7

Slide 8

Slide 8 text

net/httpからnet.Connを掘り起こす http.Client/Serverが持つnet.Connにアクセスしたい net.ConnをRead, Writeしたい そんなこと必要? →普通は必要ない・するべきではない X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 8

Slide 9

Slide 9 text

net/httpからnet.Connを掘り起こす http.Client/Serverが持つnet.Connにアクセスしたい net.ConnをRead, Writeしたい そんなこと必要? →普通は必要ない・するべきではない →プロトコルに破壊的変更を加えるために必要 X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 9

Slide 10

Slide 10 text

net/httpからnet.Connを掘り起こす ⽅法 DialContext, ConnContextを使う context.Contextで値をやり取りする X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 10

Slide 11

Slide 11 text

http.Client DialContextを使う func(ctx context.Context, network, addr string) (net.Conn, error) net.Connの作成⽅法を指定できるメソッド デフォルトではnet.Dialer{}.DialContext() X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 11 コード例: https://onoe.dev/gokyoto2023-example

Slide 12

Slide 12 text

http.Client X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 12 コード例: https://onoe.dev/gokyoto2023-example

Slide 13

Slide 13 text

http.Client X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 13 コード例: https://onoe.dev/gokyoto2023-example

Slide 14

Slide 14 text

http.Client X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 14 コード例: https://onoe.dev/gokyoto2023-example

Slide 15

Slide 15 text

http.Server ConnContextを使う func(ctx context.Context, c net.Conn) context.Context net.Connが使⽤するContextを指定できるメソッド デフォルトでは何もしない X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 15 コード例: https://onoe.dev/gokyoto2023-example

Slide 16

Slide 16 text

http.Server X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 16 コード例: https://onoe.dev/gokyoto2023-example

Slide 17

Slide 17 text

http.Server X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 17 コード例: https://onoe.dev/gokyoto2023-example

Slide 18

Slide 18 text

http.Server X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 18 コード例: https://onoe.dev/gokyoto2023-example

Slide 19

Slide 19 text

http.Server X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 19 コード例: https://onoe.dev/gokyoto2023-example

Slide 20

Slide 20 text

net/httpからnet.Connを掘り起こす ⽅法 DialContext, ConnContextを使う context.Contextで値をやり取りする X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 20

Slide 21

Slide 21 text

実⽤例1: HTTP通信の解析 io.MultiWriterを使って net.Connへの書き込み内容を os.Stdoutに出⼒ 通常処理しながら ⽣のHTTPリクエストを⾒る gzipで圧縮されてたり HTTPSだと暗号化されてたり X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 21 コード例: https://onoe.dev/gokyoto2023-example

Slide 22

Slide 22 text

実⽤例2: PROXY Protocol オリジンアドレスの情報をTCPペイロードの先頭に付与して伝播 HTTP以外でX-Forwarded-For相当の機能を使える IPアドレス・ポートを取得するだけなら⾃作net.Listenerで対応可能 参考: https://github.com/pires/go-proxyproto Version2でカスタム情報を取得するならConnContextが必要 参考: https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 22

Slide 23

Slide 23 text

プロトコル⾮依存なマイクロサービス間のコンテクスト伝播 複数環境でマイクロサービスを共⽤ TCPペイロードの先頭にコンテクストを付与 実⽤例3: PiCoP (宣伝) X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 23 レポジトリ: https://github.com/picop-rd

Slide 24

Slide 24 text

まとめ http.Client, Serverが持つnet.Connにアクセスする⽅法 →DialContext, ConnContextを使う context.Contextで値をやり取りする 実⽤例: HTTP通信の解析, PROXY Protocol, PiCoP (ちなみに)HTTP以外でもContextに詰める⽅法が使える gRPC, MySQL, MongoDB, Memcachedなど https://onoe.dev/blog/go-net-conn でHTTP, MySQLを紹介 https://github.com/picop-rd/picop-go に実装例あり X: @hiroyanoe Slide: https://onoe.dev/gokyoto2023 24