たった一つかどうかは知らんけど、「まあとりあえずこれでいいや」みたいな方法。
「CベースのgRPCサーバ」とは何ぞやっていうと、gRPCの実装はC言語ベースの実装・golang実装・Java実装に分かれているっぽくて、いわゆるRubyとかPythonとかのLLにおけるgRPC Serverは「各言語のライブラリ => 各言語のC言語バインディング => Cで書かれたコア」という構成になっているっぽい。早い話が、goとJava以外ではCベースの実装を使っていることになる。
で、ある程度真面目にRuby / gRPCで書かれたAPIサーバを運用しようとするにあたって「これどうやってgraceful restartしようかな」と思ったわけですね。
今まで僕がgraceful restartをやる方法といえば、
- UnicornとかNginxとか、サーバアプリケーション自体がgraceful restartを実装しているのでそれに乗っかる
- H2OとかRhebokとか、server-starter経由でgraceful restartできるサーバアプリケーションを使う
のどっちかしかやってこなかったわけですが、gRPC Serverは少なくとも1ではなさそうであり、2のためにコードに手を入れるのもなんだかな、という感じだったので「どうしたもんかな〜」と思いながらgRPCのCのソースを眺めいていたわけです。
そしたら、アレですよアレ。なんとCベースのgRPCサーバはデフォルトでSO_REUSEPORTが有効になってるんですね。やった!これや!ということで超手抜きなgraceful restartの実現方法がこちら
- 新サーバを立ち上げる (同じportをlistenしても死なない、なぜならREUSEPORTが効いてるからな!)
- 暫し待つ
- 旧サーバを殺す
Great.
ただしこの方法には明らかな問題があって、もし新サーバを立ち上げるのに失敗した場合は爆死してしまう。そこは新サーバの立ち上がりをちゃんと確認してから旧サーバを殺すようにすればいいだろう。
イマドキはgraceful restartなんてやらずにBlue / Greenなdeployを行うのが主流だったりするのかもだけど、まあやりたい人はいるだろうということで。