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
connect-go で面倒くささと戦う / 2024-08-27 #newmo_layerx_go
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
izumin5210
August 27, 2024
Programming
2.4k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
connect-go で面倒くささと戦う / 2024-08-27 #newmo_layerx_go
newmo × LayerX "Go"同 勉強会
https://layerx.connpass.com/event/323385/
izumin5210
August 27, 2024
More Decks by izumin5210
See All by izumin5210
開発体験を左右するライブラリの API 設計 - GraphQL スキーマ構築ライブラリから考える #tskaigi
izumin5210
2
1.8k
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
2
870
AI Agent の開発と運用を支える Durable Execution #AgentsInProd
izumin5210
8
2.9k
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
2.2k
Building AI Agents with TypeScript #TSKaigiHokuriku
izumin5210
6
1.8k
Web エンジニアが JavaScript で AI Agent を作る / JSConf JP 2025 sponsor session
izumin5210
4
3.4k
AI Coding Meetup #3 - 導入セッション / ai-coding-meetup-3
izumin5210
0
3.7k
Web フロントエンドエンジニアに開かれる AI Agent プロダクト開発 - Vercel AI SDK を観察して AI Agent と仲良くなろう! #FEC余熱NIGHT
izumin5210
3
1.3k
TypeScript を活かしてデザインシステム MCP を作る / #tskaigi_after_night
izumin5210
5
940
Other Decks in Programming
See All in Programming
鹿野さんに聞く!『TypeScriptコードレシピ集』で磨く実践力
tonkotsuboy_com
2
670
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
280
TSKaigi Night Talks 2026_TypeScriptでサプライチェーンの整合性を型に閉じ込める
geekplus_tech
0
400
The NotImplementedError Problem in Ruby
koic
1
920
決定論的オーケストレーションの設計と実装 / Design and Implementation of Deterministic Orchestration
nrslib
4
1.5k
Inside Stream API
skrb
1
770
AIを活用したE2Eテスト実装効率化のあゆみ / ebisu-mobile-14-kotetu
kotetuco
0
130
Oxlintのカスタムルールの現況
syumai
6
1.1k
ふつうのFeature Flag実践入門
irof
8
4.2k
技術的負債解消で開発者の未来を開く- AIの力でコード刷新
kmd2kmd
0
120
キャリア迷子上等 ─ "ない道"は自分で作ればいい
16bitidol
3
2.2k
Go1.27で導入されるジェネリクスメソッドでできること
mackee
0
170
Featured
See All Featured
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
400
How to Think Like a Performance Engineer
csswizardry
28
2.7k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.8k
Optimising Largest Contentful Paint
csswizardry
37
3.7k
Statistics for Hackers
jakevdp
799
230k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
170
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
1
260
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.3k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
1.8k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Why Our Code Smells
bkeepers
PRO
340
58k
Heart Work Chapter 1 - Part 1
lfama
PRO
7
36k
Transcript
© LayerX Inc. connect-go で面倒くささと戦う 2024-08-27 newmo × LayerX "Go"同
勉強会 @izumin5210
© LayerX Inc. 2 ▸ Wantedly, Inc. (2018-04 - 2022-08)
▸ LayerX (2022-09-) ‐ バクラク事業部 Platform Engineering 部 Enabling Team ‐ Backend と Web Frontend 中心にやってます ▸ 最近気になっているパッケージは github.com/pingcap/tidb/parser 画像を入れてね whoami @izumin5210
はじめに 前提になるプロダクト「バクラク」とアーキテクチャ概要
4 © LayerX Inc. 今日の話の前提: バクラクについて LayerX Company Deck https://speakerdeck.com/layerx/company-deck?slide=23
© LayerX Inc. 5 ▸ プロダクト: お客様に1つのパッケージとして価値を提供するソフトウェア製品 ‐ (「バクラク申請」など、右下の図における ◦
を指すイメージ) ▸ サービス: 論理的あるいは物理的に分けられた1つのサーバアプリケーション ‐ マイクロサービス・アーキテクチャにおける 「サービス」という単語と概ね同等 発表内での用語の定義 今日の話の前提: 用語の定義
6 © LayerX Inc. 今日の話の前提: バクラクのバックエンド API の移り変わり Product1 Webapp
Product2 Webapp Product1 Service Product2 Service OpenAPI GraphQL ▸ 初期のプロダクトは go-swagger, gqlgen などでバックエンドサーバを作っていた
7 © LayerX Inc. 今日の話の前提: バクラクのバックエンド API の移り変わり Product1 Webapp
Product2 Webapp Product1 Service Product2 Service Product3 Webapp Product3 Service OpenAPI GraphQL
8 © LayerX Inc. 今日の話の前提: バクラクのバックエンド API の移り変わり Product1 Webapp
Product2 Webapp Product1 Service Product2 Service Product3 Webapp Product3 Service こっちの情報も見せたい… こっちの情報を使いたい… OpenAPI GraphQL
9 © LayerX Inc. 今日の話の前提: バクラクのバックエンド API の移り変わり Product1 Webapp
Product2 Webapp Product1 Service Product2 Service Product3 Webapp Product3 Service OpenAPI GraphQL GraphQL Gateway GraphQL Connect ▸ 初期のプロダクトは go-swagger, gqlgen などでバックエンドサーバを作っていた ▸ プロダクトやプロダクト間連携が増えてきたことに対応するため、 GraphQL Gateway (!= BFF, Node.js 製)を構築し、バックエンドに connect-go を使い始めた
Connect #とは
© LayerX Inc. 11 ▸ gRPCと互換性をもつ、 HTTP APIを実装するためのフレームワーク ▸ gRPC
Protocolとの完全な互換性に加え、 human-readable and debuggableなConnect Protocolをサポート ‐ JSONやProtobufをHTTP/1.1の上でやりとりできる(片方向通信の場合) 💡豆知識 “Connect” がプロジェクト名だが、文脈からわかりづらいときなどは “Connect RPC” と表記してもいいらしい* Connect #とは Connect #とは * https://connectrpc.com/docs/faq
© LayerX Inc. 12 protobuf-go のコード生成 Connect #とは message GreetRequest
{ string name = 1; } こういうmessage定義から… type GreetRequest struct { // private fields Name string `::.` } こういう構造体定義が生成される
© LayerX Inc. 13 connect-go のコード生成 Connect #とは service GreetService
{ rpc Greet(GreetRequest) returns (GreetResponse) {} } こういうサービス定義から…
© LayerX Inc. 14 connect-go のコード生成 Connect #とは type GreetServiceClient
interface { // クライアントがリクエストするときの interface Greet(context.Context, *connect.Request[v1.GreetRequest]) (*connect.Response[v1.GreetResponse], error) } type GreetServiceHandler interface { // サーバが実装することになる interface Greet(context.Context, *connect.Request[v1.GreetRequest]) (*connect.Response[v1.GreetResponse], error) } こういうのを生成してくれる (un)marshal など「いつもの」な処理はConnectがやってくれる
© LayerX Inc. 15 (いろんなところで話しまくってるので圧縮してお届け 📦) ▸ Why APIスキーマ ‐
自然言語によらず、機械同士・人間同士いずれのコミュニケーションにも使えるプロトコルになる ‐ サーバ・クライアントいずれもコード生成できる場合が多く、スキーマと実装の乖離を防ぐことができる ▸ Why Protobuf ‐ スキーマ記述が簡素で可読性が高い(e.g. OpenAPI と比較し情報密度が高くなりやすい, 一般的なプログラミング言語っぽい, etc.) ‐ 互換性を保ちやすい, 互換性が壊れたことを機械的に検知できる ‐ 拡張性の高さ ‐ message(データ, リソース, モデル)を考える方向に思考が働きやすい(cf. OpenAPI だと operation にベタ書きしちゃう) ▸ Why gRPC ‐ Protobuf で記述した interface の実装に集中できる(json.Unmarshal のような「いつもの」コードは不要) などなど Why APIスキーマ, Why Protobuf, Why gRPC Connect #とは 今さらProtocol Buffersと、手に馴染む道具の話 https://qiita.com/yugui/items/160737021d25d761b353 Protocol Buffers によるプロダクト開発のススメ - API 開発の今昔 https://www.wantedly.com/companies/wantedly/post_articles/309513
© LayerX Inc. 16 ▸ Go 実装の出来がいい ‐ サーバは net/http.Handler,
クライアントは net/http.Client であり 利用可能な 3rd party パッケージの幅が広い ▸ HTTP/1.1 かつ application/json なリクエストを投げられる ‐ ローカル開発で雑にデバッグできて便利! ‐ 特別なクライアント実装がなくても使えるので、応用が効きやすい(後述) 👉 いずれも gRPC(grpc-go) の抱える複雑性を低減してくれそう Why Connect(connect-go) Connect #とは
© LayerX Inc. 17 ▸ スキーマ駆動自体は gRPC でもできる ▸ 一方で、プロトコルからくる仕様・実装により別の複雑性が発生していた
▸ Connect(connect-go) を使うことで、その gRPC の複雑さを回避するぞ! …というのが今日の内容です Why Connect(connect-go) Connect #とは
バクラクでの Connect 応用例 1 非同期API・非同期ジョブ
© LayerX Inc. 19 非同期API・非同期ジョブ バクラクでの Connect 応用例: 非同期API・非同期ジョブ ▸
スキーマがないことが多い ‐ そのジョブのペイロードの struct を定義してても、安易に変えるとデプロイの間で壊れたり ‐ caller と callee が同じサービスならまだマシだが、別だったらスキーマないと地獄 ▸ ローカル等での雑デバッグ面倒になりがち ‐ (テストを書こうという話もありつつ…)手元でシュッと動かしたいときに面倒になりがち ‐ REPL がある言語ならやりやすいんだけど…
© LayerX Inc. 20 非同期API・非同期ジョブにもConnectを バクラクでの Connect 応用例: 非同期API・非同期ジョブ Publisher
Connect server service GreetService { rpc Greet(GreetRequest) returns (GreetResponse) {} } 行き先(GreetService/Greet)と ペイロード(GreetRequest)を キューに詰める Subscriber Worker
© LayerX Inc. 21 非同期API・非同期ジョブにもConnectを バクラクでの Connect 応用例: 非同期API・非同期ジョブ Publisher
Connect server Subscriber Worker キューから取り出した内容を見て Subscriber が適切な Connect Server を呼ぶ Connect Protocol でリクエストすればいいだけ ここがConnectによる通信になる
© LayerX Inc. 22 この仕組みがなぜ嬉しいか バクラクでの Connect 応用例: 非同期API・非同期ジョブ Publisher
Connect server Subscriber Worker ▸ 非同期でもちゃんとスキーマ定義できる ‐ 雑に json.Marshal するのではなく、 同期APIと同じメンタルモデルで型定義を。 非同期ジョブ・非同期APIもAPI! ▸ 雑デバッグが楽! ‐ Publisher がまだなくてもおもむろに cURL で動かせる!
バクラクでの Connect 応用例 2 ローカルでの起動を楽にする
© LayerX Inc. 24 ローカルでの起動がどんどん大変になる問題 バクラクでの Connect 応用例: ローカルでの起動を楽にする TenantService
CardTransactionService WorkflowService NotificationService ▸ プロダクトが発展する、あるいは増えると サービスも増える ▸ いまの開発に必要なのはこれとこれと… と 起動していくのは面倒 ▸ ポート番号を予約してくのも面倒
© LayerX Inc. 25 ローカルでは1つのHTTP serverに 全Connect serverを乗せる バクラクでの Connect
応用例: ローカルでの起動を楽にする TenantService NotificationService CardTransactionService 論理的には別のサービス ローカルでは物理的には1つのサービス TenantService NotificationService CardTransactionService 社内ではgo-allと呼ばれています
© LayerX Inc. 26 ローカルでは1つのHTTP serverに 全Connect serverを乗せる バクラクでの Connect
応用例: ローカルでの起動を楽にする TenantService NotificationService CardTransactionService ▸ ローカルでは全サービスを1つに まとめることで、起動を楽にしている ▸ cURLで雑デバッグしたいときも ポート番号を1つだけ覚えておけばいい ▸ デプロイ時は 論理的なサービス = 物理的なサービス
© LayerX Inc. 27 バクラクでの Connect 応用例: ローカルでの起動を楽にする func HandlerOptions(ctx
context.Context) ([]connect.Option, error) { svc, err := NewServiceHandler(ctx) if err := nil { return nil, err } path, handler := tenantv1connect.NewTenantServiceHandler(svc, /* common options //) return []connect.Option{ connect.WithHandler(path, handler), connect.WithCloseHandler(svc), }, nil } http.Handler と path を生成する関数を各サービスに生成して、
© LayerX Inc. 28 バクラクでの Connect 応用例: ローカルでの起動を楽にする var ServiceHandlerOptions
= map[string]func() ([]connect.Option, error){ tenantv1connect.TenantServiceName: tenant_v1_tenant.HandlerOptions, // 全サービスの HandlerOptions 関数を突っ込んでおく } 全サービスの HandlerOptions 関数を突っ込んだ map をコード生成する あとはこれを使って Connect server を作るだけ
© LayerX Inc. 29 ローカルでは1つのHTTP serverに 全Connect serverを乗せて、ログは頑張って探しやすくする バクラクでの Connect
応用例: ローカルでの起動を楽にする ▸ 「複数サービスのログが1つの stdout で流れてしまう」というデメリット ‐ 読めねえ ▸ バクラクでは Grafana 上でログ・トレースを探せるようにしている ‐ プロセスマネージャ* でログを OpenTelemetry に変換し、Loki, Tempo に投入 ‐ ログだけでいいならシンプルに Promtail + Loki でも可 * エンジニアオンボーディングを改善するツールの紹介 https://tech.layerx.co.jp/entry/2022/12/12/131507
バクラクでの Connect 応用例 2.5 ローカルでの起動を楽に・かつ速くする
© LayerX Inc. 31 全サービスを1つにまとめると、ビルドはどんどん重くなる バクラクでの Connect 応用例: ローカルでの起動を速くする ▸
あらゆるサービスをひとまとめにビルドしようとすると、当然ながら重くなる ▸ ローカルでは、いま開発中のサービス以外の要因で待たされたくない ‐ いま開発中 is … リクエストが来たサービス? 👉 リクエストが来たサービスだけビルドする!
© LayerX Inc. 32 ビルドはどんどん重くなっていくので、 部分的にビルドできるようにする バクラクでの Connect 応用例: ローカルでの起動を速くする
▸ メインの port を listen してるプロセスがリクエストを受けたら、 ‐ 対象のサービスをビルドし ‐ Unix domain socket を listen する形で起動して ‐ そこにリクエストを流す! ▸ 最小限しかビルドしないので速い! ▸ これも go-all と似たような感じで実装を生成する
バクラクでの Connect 活用術 3 デプロイもちょっと楽にする
© LayerX Inc. 34 ローカルでは1つのHTTP serverに 全Connect serverを乗せる バクラクでの Connect
応用例: デプロイもちょっと楽にする TenantService NotificationService CardTransactionService ▸ ローカルでは全サービスを1つに まとめることで、起動を楽にしている 👉 全サービスを1バイナリにまとめてるなら AWS 上でも1バイナリだけでいいのでは?
© LayerX Inc. 35 1つのバイナリに全Connect serverを乗せて、 起動時に出し分ける バクラクでの Connect 応用例:
デプロイもちょっと楽にする ▸ 全てのサービスをまとめたバイナリをAWS 上でも動かせば、 1度ビルドしたバイナリは使い回せる! ‐ ビルド時間, ストレージなどの節約になる! ▸ 実際は振る舞いがちょっと違うので、モードを2つに分けている* ‐ 全サービスが起動するモードと、特定のサービスのみ起動するモード * connect\-go による複数サービスの開発とユニバーサルバイナリによる改善 https://tech.layerx.co.jp/entry/2023/07/18/173901
バクラクでの Connect 活用術 3 デプロイをさらに楽にする
© LayerX Inc. 37 ローカルでは1つのHTTP serverに 全Connect serverを乗せる バクラクでの Connect
応用例: デプロイをさらに楽にする TenantService NotificationService CardTransactionService ▸ デプロイ時は 論理的なサービス == 物理的なサービス 👉 …じゃなくてもいいのでは?
© LayerX Inc. 38 複数の論理的なサービスを1つのデプロイメントにまとめる バクラクでの Connect 応用例: デプロイをさらに楽にする TenantService
CardTransactionService NotificationService ▸ 非機能要件面で分ける理由がない場合は、 1つのデプロイメントに 複数の論理的なサービスを乗せることも可 WorkflowService
バクラクでの Protobuf 活用術 もはや Connect あんまり関係ないが、 Protobuf 自体も便利!
© LayerX Inc. 40 ▸ データを定義してそこから必要な実装を生やすシリーズ ‐ e.g. FeatureFlag, 権限・ロール
▸ Protobuf の message, enum から GraphQL の型を生成 ▸ Protobuf Message に sql.Scanner & driver.Valuer を実装し、 JSON 表現で DB に格納してくれるコードを生成する ▸ サービス間通信の認証情報は Protobuf で payload 定義し、署名を付けている ‐ JWT 的な感じだが、Protobuf なのでサイズを抑えることができる ▸ Connect のサービス定義から Go のサービス実装の scaffolding バクラクでの Protobuf 活用例
まとめ
© LayerX Inc. 42 まとめ もともとのモチベーション ▸ スキーマ駆動自体は gRPC でもできる
‐ 一方で、プロトコルからくる仕様・実装により別の複雑性が発生していた ▸ Connect(connect-go) を使うことで、その gRPC の複雑さを回避するぞ! Connect によって… ▸ 非同期ジョブ・非同期 API にも Connect を使い、通常の API と同じ開発体験に ▸ ローカルでは全サービスのプロセスを1つにまとめて、起動を楽に ‐ さらにそのうち必要なサービスのみビルドすることで、起動を高速に ▸ 本番でも複数の論理サービスを1つの物理サービスにまとめることでインフラも楽に ▸ その他 Protobuf にいろいろやってもらって、いろいろ便利に