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
gRPCミドルウェアを作ってみよう
Search
Shintaro Kanno
August 03, 2022
Programming
630
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
gRPCミドルウェアを作ってみよう
Shintaro Kanno
August 03, 2022
More Decks by Shintaro Kanno
See All by Shintaro Kanno
アトミックデザイン入門
shintaro8
0
310
Goの並行処理に入門しよう
shintaro8
0
160
Azure Functionsを使ってSlackに通知をしてみよう
shintaro8
0
580
Other Decks in Programming
See All in Programming
気圧・高度・GPSを記録&可視化するアプリ「Koudo」を作った話
hjmkth
1
310
The NotImplementedError Problem in Ruby
koic
1
880
生成AI時代にこそ効くGo | Why Go Works in the Age of Generative AI
mom0tomo
8
3.3k
jQueryをバージョンアップする前に使いたいjQuery Migrate
matsuo_atsushi
0
570
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
170
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
260
並列実装の現場、2ヶ月間実務でAIを使い倒したAIもPCも私も限界が近い
ming_ayami
0
130
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
7
1.4k
Agentic UI
manfredsteyer
PRO
0
180
正しくソフトウェアを作る、前提を疑うための認知の視点 / doubt-premise
minodriven
21
6.9k
Strategic Design in the Frontend: Moduliths & Micro Frontends @DDDEurope
manfredsteyer
PRO
0
120
ユニットテストの先へ:テスト技法で要求・仕様を整理するJava開発実践 / Beyond_Unit_Testing_Practical_Java_Development_Techniques_for_Organizing_Requirements_and_Specifications
shimashima35
0
410
Featured
See All Featured
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4k
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
260
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
2.8k
Marketing to machines
jonoalderson
1
5.5k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
330
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
950
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.3k
We Analyzed 250 Million AI Search Results: Here's What I Found
joshbly
1
1.4k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
200
Believing is Seeing
oripsolob
1
150
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Transcript
gRPCミドルウェアを作ってみよう
名前 : 官野 慎太朗 業務 : 都内のIT事業会社にて勤務 技術経験: - JavaScript/TypeScript,
Go - MySQL, PostgreSQL - Docker, Kubernetes - Azure, Aws - Git, RestfulAPI, gRPC, etc… @shinshin8 @doctorkanno572
gRPCのミドルウェアを使ったこ とはありますか? ?
go-grpc-middleware(github.com/grpc-ecosystem/go-grpc-middleware) • gRPC開発に必要なインターセプ ター、ヘルパー、ユーティリティなどを 提供 • 認証、ロギング、リカバリ、リトライなど の機能を実現
提供されている以外の機能が欲しい・・・
! 自前でgRPCミドルウェアを 作ってみよう
1. 4つのRPCについて 2. Unary Server Interceptorの基本構造 3. Google Maps APIを使ったgRPCミドルウェアの実装
Agenda
1. 4つのRPCについて
• Unary RPC ◦ クライアントからの1つのリクエストに対し、サーバーが1つのレスポンスをクライアントに返す。 • Server streaming RPC ◦
クライアントからの1つのリクエストに対し、サーバーが複数のレスポンスをクライアントに返す。 • Client streaming RPC ◦ クライアントからの複数のリクエストに対し、サーバーが1つのレスポンスをクライアントに返す。 • Bidirectional RPC ◦ 通信が確立後、クライアントとサーバー間で任意のタイミングでのやりとりを行う。
1. 2. Unary Server Interceptor の基本構造
Unary Server Interceptorの基本的な構成 func UnaryInterceptor() grpc.UnaryServerInterceptor { return func (
ctx context.Context, req interface {}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler ) ( resp interface {}, err error ) { // ~~~ implementation ~~~~ return handler(ctx, req) } }
Unary Server Interceptorの基本的な構成 func UnaryInterceptor() grpc.UnaryServerInterceptor { return func (
ctx context.Context, req interface {}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler ) ( resp interface {}, err error ) { // ~~~ implementation ~~~~ return handler(ctx, req) } } • grpc.UnaryServerInterceptor ◦ ミドルウェアの戻り値 ◦ 戻り値で関数を返す
4つのパラメータ func UnaryInterceptor() grpc.UnaryServerInterceptor { return func ( ctx context.Context,
← ★ req interface {}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler ) ( resp interface {}, err error ) { // ~~~ implementation ~~~~ return handler(ctx, req) } } • ctx : コンテキスト
4つのパラメータ func UnaryInterceptor() grpc.UnaryServerInterceptor { return func ( ctx context.Context,
req interface {}, ← ★ info *grpc.UnaryServerInfo, handler grpc.UnaryHandler ) ( resp interface {}, err error ) { // ~~~ implementation ~~~~ return handler(ctx, req) } } • ctx : コンテキスト • req : クライアントから受け取 るリクエスト
4つのパラメータ func UnaryInterceptor() grpc.UnaryServerInterceptor { return func ( ctx context.Context,
req interface {}, info *grpc.UnaryServerInfo, ← ★ handler grpc.UnaryHandler ) ( resp interface {}, err error ) { // ~~~ implementation ~~~~ return handler(ctx, req) } } • ctx : コンテキスト • req : クライアントから受け取 るリクエスト • info : サーバー情報
4つのパラメータ func UnaryInterceptor() grpc.UnaryServerInterceptor { return func ( ctx context.Context,
req interface {}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler ← ★ ) ( resp interface {}, err error ) { // ~~~ implementation ~~~~ return handler(ctx, req) } } • ctx : コンテキスト • req : クライアントから受け取 るリクエスト • info : サーバー情報 • handler : 後続の処理
意識したい処理の流れ func ( ~~~~~~~~~ ) ( ~~~~~~~~~ ) { //
ミドルウェアで行いたい処理を実装 return handler(ctx, req) } 処理結果を後続の処理に受け渡す 後続の処理結果を扱う func ( ~~~~~~~~~ ) ( ~~~~~~~~~ ) { resp, err := handler(ctx, req) if err != nil { // エラーハンドリング } // 後続の処理結果をもとに実装 }
3. Google Maps APIを使った gRPCミドルウェアの実装
今回作ったもの • Google Maps APIを使ってcontextに緯度経度を追加するミドルウェア • Google Maps Geocode及びGeolocation APIの操作を可能にするパッケージを使用
◦ https://github.com/martinlindhe/google-geolocate • クライアントからのリクエストcontextに位置情報が追加されている前提 • 実際に作ったもの ◦ https://github.com/shinshin8/golang-grpc-middleware
func GeocodeUnaryServerInterceptor(apiKey string) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { client := geo.NewGoogleGeo(apiKey) geocode := geoctx.GetGeoInfo(ctx) res, _ := client.Geocode(geocode) if err != nil { geoctx.SetGeoLocate(ctx, 0, 0) } else { geoctx.SetGeoLocate(ctx, res.Lng, res.Lat) } return handler(ctx, err) } } 実際に作ったミドルウェア
func GeocodeUnaryServerInterceptor(apiKey string) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { client := geo.NewGoogleGeo(apiKey) ←★ 引数で受け取った Google Maps API Keyかクライアントを作成 geocode := geoctx.GetGeoInfo(ctx) res, _ := client.Geocode(geocode) if err != nil { geoctx.SetGeoLocate(ctx, 0, 0) } else { geoctx.SetGeoLocate(ctx, res.Lng, res.Lat) } return handler(ctx, err) } } 実際に作ったミドルウェア
func GeocodeUnaryServerInterceptor(apiKey string) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { client := geo.NewGoogleGeo(apiKey) geocode := geoctx.GetGeoInfo(ctx) ←★ contextから位置情報を取得 ※geoctx.GetGeoInfoは今回作った機能 res, _ := client.Geocode(geocode) if err != nil { geoctx.SetGeoLocate(ctx, 0, 0) } else { geoctx.SetGeoLocate(ctx, res.Lng, res.Lat) } return handler(ctx, err) } } 実際に作ったミドルウェア
func GeocodeUnaryServerInterceptor(apiKey string) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { client := geo.NewGoogleGeo(apiKey) geocode := geoctx.GetGeoInfo(ctx) res, _ := client.Geocode(geocode) ← ★ 取得した位置情報から Geocodeし、緯度経度を取得 if err != nil { geoctx.SetGeoLocate(ctx, 0, 0) } else { geoctx.SetGeoLocate(ctx, res.Lng, res.Lat) } return handler(ctx, err) } } 実際に作ったミドルウェア
func GeocodeUnaryServerInterceptor(apiKey string) grpc.UnaryServerInterceptor { return func(ctx context.Context, req interface{},
info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) { client := geo.NewGoogleGeo(apiKey) geocode := geoctx.GetGeoInfo(ctx) res, _ := client.Geocode(geocode) if err != nil { geoctx.SetGeoLocate(ctx, 0, 0) } else { geoctx.SetGeoLocate(ctx, res.Lng, res.Lat) ← ★ 緯度経度をcontextに付与 ※geoctx.SetGeoLocateは今回作った機能 } return handler(ctx, err) } } 実際に作ったミドルウェア
Thank you!