Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
connect-go で面倒くささと戦う / 2024-08-27 #newmo_layerx_go
Search
izumin5210
August 27, 2024
Programming
2.5k
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
コンパウンドプロダクト開発のためのローカルプロセスマネージャー再発明 #layerxgo
izumin5210
0
660
in-process GraphQL のすすめ #ginzajs
izumin5210
4
1.5k
開発体験を左右するライブラリの API 設計 - GraphQL スキーマ構築ライブラリから考える #tskaigi
izumin5210
2
2.1k
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
2
1.1k
AI Agent の開発と運用を支える Durable Execution #AgentsInProd
izumin5210
8
3.1k
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
2.3k
Building AI Agents with TypeScript #TSKaigiHokuriku
izumin5210
6
1.8k
Web エンジニアが JavaScript で AI Agent を作る / JSConf JP 2025 sponsor session
izumin5210
4
3.6k
AI Coding Meetup #3 - 導入セッション / ai-coding-meetup-3
izumin5210
0
3.8k
Other Decks in Programming
See All in Programming
フロントエンドUIフレームワークのこれまでとこれから
ssssota
2
1.3k
初心者DevRelとして参加者だった私が、DevRel Talks!#2に登壇するまでにしてきたこと
sokohirai
0
360
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
1
470
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
5
2.5k
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
270
{ Android | Kotlin } Gradle Plugin in 2026
ryunen344
1
290
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
130
ハーネス設計入門 〜プロンプト、コンテキストの次〜
kinopeee
55
36k
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
4.4k
スマート反転とウェブアクセシビリティ
camiha
0
170
不幸な GC
chencmd
0
890
思考垂れ流し開発 ~音声入力 × AIエージェント × 開発ハーネスによる試行錯誤~
npostring
0
1k
Featured
See All Featured
Building Applications with DynamoDB
mza
96
7.2k
Optimizing for Happiness
mojombo
378
71k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
520
Mobile First: as difficult as doing things right
swwweet
225
10k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
470
Paper Plane (Part 1)
katiecoart
PRO
1
11k
The Invisible Side of Design
smashingmag
301
52k
Utilizing Notion as your number one productivity tool
mfonobong
4
580
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 にいろいろやってもらって、いろいろ便利に