Slide 1

Slide 1 text

GolangでHTTP Routerをつくった @bmf_san

Slide 2

Slide 2 text

https://speakerdeck.com/bmf_san/urlruteinguwotukuruepisodo1

Slide 3

Slide 3 text

続編にして完結編

Slide 4

Slide 4 text

⽬次 ・HTTP Routerの仕組み ・データ構造 ・Golangでの実装

Slide 5

Slide 5 text

Github https://github.com/bmf-san/goblin

Slide 6

Slide 6 text

1 HTTP Routerの仕組み

Slide 7

Slide 7 text

HTTP Router is 何? ・リクエストされたURLやHTTP Methodに応じて、 処理の実⾏を制御するアプリケーション ・URLとアプリケーションの処理を結びつける

Slide 8

Slide 8 text

処理のイメージ

Slide 9

Slide 9 text

パターン Routerが解釈するルーティングのパターン ・静的なルーティング →/foo/barが/foo/barに⼀致 ・動的なルーティング →/foo/bar/123が/foo/bar/:idに⼀致

Slide 10

Slide 10 text

2 データ構造

Slide 11

Slide 11 text

データ構造を考える ・Router≒⽂字列マッチング ・URLの階層構造と相性が良いデータ構造 →⽊構造

Slide 12

Slide 12 text

⽊構造

Slide 13

Slide 13 text

トライ⽊(プレフィックス⽊) ・⽂字列の集合を扱う⽊構造の⼀種 ・ざっくりいうと、⽂字列を探索しやすいように⽊に 格納したやつ ・ex. サジェスト、IPアドレス探索、形態素解析とか に応⽤が⾒られる

Slide 14

Slide 14 text

トライ⽊を知る ・https://www.cs.usfca.edu/~galles/visualization/ Trie.html →アルゴリズムのビジュアライズ ・https://github.com/bmf-san/road-to-algorithm- master/tree/master/data_structures/tree/trie →参照実装かいた

Slide 15

Slide 15 text

オレオレトライ⽊ ・ルーティングの定義を元にオレオレトライ⽊をつく る(これが結構試⾏錯誤した..) ・トライ⽊の定義に当てはまるのかちょっと⾃信ない けど多分トライ⽊、いやギリトライ⽊だと思う

Slide 16

Slide 16 text

オレオレトライ⽊ • /foo/ • /baz/ • /foo/bar/ • /foo/:name[string]/ • /foo/bar/:id[int] ˞ύϥϝʔλͷఆٛͷ࢓ํ͸%4-ͳͷͰࣗ༝

Slide 17

Slide 17 text

ͦΜͳ໦Ͱେৎ෉͔ʁ

Slide 18

Slide 18 text

⼤丈夫だ、問題ない。でも・・ ・時間的計算量(処理時間)、空間的計算量(メモ リ)をより最適化するなら、当然選択肢はある ・Radix Tree https://www.cs.usfca.edu/~galles/ visualization/RadixTree.html

Slide 19

Slide 19 text

3 Golangでの実装

Slide 20

Slide 20 text

GolangでのURLパターンマッチの 仕組み、お作法

Slide 21

Slide 21 text

net/http ・net/httpのインターフェースついて、HTTPServer を⽴てるコードの実装から内部処理を読んでおく →net/httpのmuxを拡張する ・cf. https://bmf-tech.com/posts/GolangのHTTP サーバーのコードリーディング

Slide 22

Slide 22 text

muxとは ・マルチプレクサ。多重器、多重装置、多重化装置、合波器。 ・2つの⼊⼒から1つの出⼒を得るもの ・雑にいうとURLのパターンマッチするやつ ・net/httpではServeMux構造体(URLパターンマッチやる 君) cf. https://golang.org/pkg/net/http/#ServeMux

Slide 23

Slide 23 text

net/httpのmuxの拡張 ・http.ListenAndServeから処理をたどる  →addressとHandlerインターフェースを満たしたhandlerを引数に 取る。内部的には、handlerの呼び出し=ServeHTTPの呼び出しとな る cf. https://golang.org/src/net/http/server.go?s=96538:96593#L3074 ・ServeMuxはServeHTTPを実装しており、Handlerインターフェー スを満たしている cf. https://golang.org/pkg/net/http/#ServeMux.ServeHTTP

Slide 24

Slide 24 text

)BOEMFS*OUFSGBDF 何を拡張すればいい? IUUQ-JTUFO"OE4FSWF "EESFTT )BOEMFS 4FSWF)551 ཁ͢Δʹ͜Εʂ

Slide 25

Slide 25 text

こんな感じ ・https://github.com/bmf-san/goblin/blob/master/ router.go#L60 ࣗલͷ63-ύλʔϯϚον

Slide 26

Slide 26 text

⾃前のURLパターンマッチの実装

Slide 27

Slide 27 text

オレオレトライ⽊の実装 ・オレオレトライ⽊を実装に落とし込む →トライ⽊の応⽤。パラメータ部分の実装がちょっ と⾯倒 ・コアの実装 https://github.com/bmf-san/goblin/blob/master/trie.go

Slide 28

Slide 28 text

再帰処理との闘い ・つらい ・テストとデバッガで頑張れば 乗り越えられる

Slide 29

Slide 29 text

Example ・参照実装 https://github.com/bmf-san/goblin/blob/master/_examples/main.go ・トレイリングスラッシュは気にしないで⼤丈夫なは ず ・静的ファイルはhttp.ServeFile使って問題なく返せ るはず

Slide 30

Slide 30 text

ベンチマーク ɾࢀর https://github.com/bmf-san/goblin#benchmark →ͪΌΜͱ෼ੳͰ͖͍ͯͳ͍͚Ͳɺ΅ͪ΅ͪͳײ͢͡Δ ɾgo੡RouterͷϕϯνϚʔΫ෼ੳ https://github.com/julienschmidt/go-http-routing-benchmark

Slide 31

Slide 31 text

Issue・PR・Star

Slide 32

Slide 32 text

参考 ・雑まとめ GolangͰgoblinͱ͍͏URLϧʔλʔΛࣗ࡞ͨ͠ URLϧʔςΟϯάࣗ࡞ೖ໳ɹΤϐιʔυ̍ URLϧʔςΟϯάࣗ࡞ೖ໳ɹΤϐιʔυ̎ GolangͷHTTPαʔόʔͷίʔυϦʔσΟϯά A Trie implementation in Golang