Upgrade to Pro — share decks privately, control downloads, hide ads and more …

net/httpからnet.Connを掘り起こす

Hiroya Onoe
November 29, 2023

 net/httpからnet.Connを掘り起こす

Go Conference mini 2023 Winter IN KYOTO

HTTP 通信を提供する標準ライブラリ net/http は トランスポート層(L4)以下のプロトコルを意識する必要がないように設計されています。これにより、コネクションの再利用やプールのような複雑な処理を深く考えることなく Go で HTTP 通信を利用することができます。
しかし一方で、 TCP コネクションを表す net.Conn を http.Client, Server 構造体から取り出して直接操作することが難しくなっています。例えば、リバースプロキシなどで利用される PROXY Protocol というプロトコルは、 トランスポート層(L4)プロトコルのペイロードの先頭、つまりアプリケーション層(L7)プロトコルのデータの直前で追加のデータを読み書きします。そのためこのプロトコルを Go で実装する際には、 http.Client, Server 構造体の持つ net.Conn に直接読み書きする必要があります。
こういった方法の解説はウェブ上に乏しく、 net/http や net のコードをかなり詳しく読まないと分からないのが現状です。
今回のLTでは、 net/http や net.Conn について簡単に解説しながら、HTTP の Client, Server それぞれにおいて net.Conn を取得する方法とその実用例を紹介します。

Hiroya Onoe

November 29, 2023
Tweet

More Decks by Hiroya Onoe

Other Decks in Programming

Transcript

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  5. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  11. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  15. 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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  22. 実⽤例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

    View full-size slide

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

    View full-size slide

  24. まとめ
    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

    View full-size slide