Contenu connexe Similaire à 【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜 (20) 【とらのあなラボ Tech Day #3】新規システムにおける技術選定〜GoとgRPCを採用した話〜 1. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新規システムにおける技術選定
〜GoとgRPCを採用した話〜
虎の穴ラボ 藤原 佳顕
1
2. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
アジェンダ
● 概要
● 新しいシステムを作った話
● 実際に採用した技術〜GoとgRPC〜
○ 実際の構成
○ 良かった点/失敗した点
● まとめ
2
3. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
自己紹介
3
● 名前
○ 藤原佳顕(@nuhera, @zonuko)
● 仕事
○ FantiaとかCreatiaとか社内アプリとか
● 好み
○ Clojure、Rust
● 趣味
○ 格闘ゲーム
■ Melty Blood、Guilty Gear
○ STG(ダライアスとか)も好き
○ 最近は女神転生Vずっとやってました
5. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
5
Fantiaにアフィリエイト機能作らない?
6. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● 技術選定の前提
○ 自分のタスクに対する裁量はかなり大きい範囲で認められている
■ 何でもOKではない
■ 作るものに最適か、会社の方針にあっているかを踏まえた上で自分の使
いたいものを選択できる
■ プログラミング言語、インフラなど基本的にすべて裁量がある
作ろうとしているモノに対して最適なものを採用するのが腕の見せ所!
6
7. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● 今回作る機能の要件
○ ある種の履歴管理機能
■ =>DB上のレコードは膨大になる可能性がある
○ 機能の使用に利用者申請が必要
■ =>利用者管理機能が必要
○ 連携箇所を考えるとなるべく高速に
■ =>レスポンスに1sとかはNG
7
8. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● 検討候補
○ 言語、フレームワーク
■ Ruby on Rails
● 虎の穴ラボで一番良く使われる
■ Go
● マイクロサービスとする場合ユースケースに合致
● 会社の方針としても推したい技術
■ Rust
● 社内システムで採用したことあり
● 他個人的に使っていた
8
9. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● 検討候補
○ アーキテクチャ
■ モノリシック
● 予想されるデータの量的には採用しづらいが検討余地はあり
■ REST API
● 定番。慣れてはいるがきれいに作るのが難しい
■ GraphQL
● Rustと共に個人的に利用実績あり(社内システム)
■ gRPC
● 基本的にサーバー間通信の想定だったので候補に
● また、Goを選んだ場合に相性が良さそう
9
10. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● 検討候補
○ DB関連
■ MySQL(8)
● 社内の知見的に一択だった
● あくまで社内のものな点に注意。自分の経験からは選ばない
■ RDBにまつわるツール
● 言語が決まってから
■ Redis
● 速度要件的に使える場所でキャッシュとして使いたい
10
11. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● 検討候補
○ クラウド関連
■ GCP
● 組み込み先のシステムはGCP上で稼働
■ AWS
● 社内的には最も使われている
11
12. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● その他ライブラリなど
○ Goを使う場合はある程度ライブラリの選定が必要
■ ORM or クエリビルダー
● GORM
○ スターが一番多い
● SQLBoiler
○ マイグレーションしたDBからORMのコードを起こせるのが良さそう
■ DBマイグレーション
● ORMとくっついていないので何でも良い
● golang-migrate/migrate
○ Go言語製でシンプルなDBマイグレーションツール
12
13. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
13
ちゃんとメンテできるように!
リリースは簡単に!
技術方針としてはGoとgRPCがい
いな・・・
速度重視でクラウドは同じ+
リージョン近いほうがいいので
は?
14. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● 提案した技術をベースに社内で相談
○ はじめに組み込み先サービスの主担当+アーキテクチャの担当
■ 自分が推したいものを持っておくのが大事
● 今回はGo、gRPC、AWS
■ この時点で一旦決定
○ 決定したものをCTOに共有
■ 今回はここでAWS⇨GCPに変わった
● 前述の通りなるべく同じクラウド、同じリージョンにするため
14
16. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● 最終的に選んだ技術
○ サービスは分割
■ データ量がやはり懸念。データが膨大になって障害になったことがあるた
め
○ Go
■ 会社の方針と自分が上げた候補で合致したもの
■ ライブラリ:GORM、golang-migrate
● できるだけシンプルかつ、今後の発展も期待できそうなもの
16
17. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
新しいシステムを作った話
● 最終的に選んだ技術
○ gRPC
■ 今回はサーバー間通信が主だったのでRESTやGraphQLより向いているだ
ろうと判断
■ 速度も期待できる
○ GCP(CloudRun)
■ FantiaはGCP
■ CloudRun自体は別件で利用実績があったかつ、gRPCに対応していた
■ AWSとの速度比較などしていないが、安全のためこちらを選択
17
19. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
実際の構成
● システム全体像
19
Fantia(クライアント:Rails)
アフィリエイト(APIサーバー: Go)
20. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
実際の構成
● ディレクトリ構成
20
● api
○ gRPCの定義ファイル(*.proto)とそこから生成されるファイルの置き場
● cmd
○ エントリポイントのソース置き場(main.goとそれにまつわるもの)
● db
○ migrations: go-migrateで作ったDBマイグレーションファイル置き場
○ model: GORMで定義されたORM用ソース置き場。ビジネスロジックはこちら
○ seed: 初期データ投入用ソース置き場
● handler
○ APIのエンドポイント
○ gRPCで自動生成されたソースを具体的な実装に落とし込んだもの
21. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
実際の構成
● apiディレクトリ配下の例
21
syntax = "proto3";
package samplepb;
// コード生成時のGoとRubyのパッケージ名
option go_package = "api/grpc-gen/samplepb";
option ruby_package = "Grpcs::Samplepb";
// 名前の通り一つのサービスを表す(service)
service Sample {
// rpcで定義されるのが実質的なインターフェース
// 言語から見るとinterfaceやメソッドといった形
rpc PingPong (Ping) returns (Pong) {}
}
// messageではinterface等でやり取りされるデータが定義される
// 要は構造体のようなもの これがシリアライズされてバイナリで送られる
message Ping {
string msg = 1;
}
message Pong {
string msg = 1;
}
(sample.proto)
22. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
実際の構成
● apiディレクトリ配下の例
22
// For semantics around ctx use and closing/ending streaming RPCs, please refer to
https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type SampleClient interface {
PingPong(ctx context.Context, in *Ping, opts ...grpc.CallOption) (*Pong, error)
}
type Ping struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"`
}
(sample_grpc.pb.go)SampleClientインターフェースをhandler配下で実装すればAPIが出来上がる
(sample.pb.go)Pongも同様な形で構造体が生成される
23. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
実際の構成
● Ruby側もprotoファイルからソース生成できる
23
# Generated by the protocol buffer compiler. DO NOT EDIT!
# Source: sample.proto for package 'Grpcs.SamplePb'
require 'grpc'
require 'sample_pb'
module Grpcs
module SamplePb
module Sample
class Service
# 略
rpc :PingPong, ::Grpcs::SamplePb::Ping, ::Grpcs::SamplePb::Pong
end
Stub = Service.rpc_stub_class
end
end
end
require 'google/protobuf'
Google::Protobuf::DescriptorPool.generated_pool.build do
add_file("sample.proto", :syntax => :proto3) do
add_message "samplepb.Ping" do
optional :msg, :string, 1
end
add_message "samplepb.Pong" do
optional :msg, :string, 1
end
end
end
(sample_pb.rb)
(sample__services_pb.rb)
24. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
良かった点
24
● 速度を目的に導入したgRPCの開発体験が良かった
○ 当然速度も満足できるレベル
○ protoファイルから自動生成されるコードをサービス間のインターフェースとして使える
○ API側は多少実装が必要だが、クライアント側は自動生成コードを実行するだけでAPI実行が
できてしまう
■ エンドポイントの指定とかは必要
■ 先の例だとDSLで定義されていた`rpc :PingPong`
● 実際の呼び出しサンプルは以下
@service = Grpcs::SamplePb::Sample::Stub.new('localhost:50051')
@grpc_res = @service.ping_pong(@request, metadata)
25. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
良かった点
25
● gRPCがRubyであっても型チェックしてくれる
○ もともと静的型付けなGo側は当然チェックされる(コンパイル時)
○ Rubyで生成したコードに間違った型の値を入れるとエラーになる
■ ただし、実行時な点は注意
○ テストコードやユーザーテストでエラーを発見しやすかった
@request = Grpcs::SamplePb::Ping.new(msg: msg)
↑msgがstring以外だとエラーにしてくれる
26. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
良かった点
26
● CloudRunの運用が楽
○ コンテナをサーバーレスに動かす仕組み
○ スケールは受け入れ可能同時リクエスト数と最低台数で決まる
■ その上でCPUを調整
○ CloudBuildを使ったリリースがかなり楽
■ リリース用コンテナのビルドまで、CloudRunへの展開までなど設定ファイルを書くこ
とで柔軟に選べる
■ GitHubなどと連携していなくても画面上からボタン押すだけでリリースできる
27. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
失敗した点
27
● protoファイルの管理方法
○ Go側のプロジェクトにいれてしまった
■ Ruby側のプロジェクトとGo側のプロジェクトのフォルダの配置に依存してしまう
○ より広範にgRPCが使われるようなら専用リポジトリに分離しようと考えていたが、最初か
ら分離してもよかった
28. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
失敗した点
28
● ライブラリの選定
○ GORMを採用したがsqlcのほうが、好みや実際の実装を見ると良かった
■ https://github.com/kyleconroy/sqlc
○ GORMを使ってはいるものの実際の使い方がクエリビルダーっぽい
■ SQLの結果を構造体にマッピングしているだけのような使い方
○ SQLを中心に考えるならsqlcのほうが良かったのでは?
var conv *HogeHoge
query := db.GetDB().Table("hogehoge").Where("fuga_id = ?", af.ID)
query = query.Where("type IN (?) ", []int{int(TYPE)})
query = query.Order("id desc")
query.Find(&conv)
29. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
失敗した点
29
● gRPCの中身を直接は確認できない
○ RESTの場合は直接APIをブラウザで実行してみたりして返ってくるJSONを確認したりし
ていた
○ gRPCはHTTP/2上かつ、バイナリでデータのやり取りが行われるのでRESTのように直
接見える形で実行することが難しい
○ 開発時は専用クライアントを使った
■ BloomRPC
● https://github.com/bloomrpc/bloomrpc
30. Copyright (C) 2022 Toranoana Inc. All Rights Reserved.
まとめ
30
● 虎の穴ラボでの新規サービスを作るときの技術選定の流れを紹介しました
● 実際に作ったものを例にソースや選定の結果できあがった構成を紹介しました
● 選んだ技術を使ってみて良かったところ、悪かったところを紹介しました