PHPでもgRPCサーバを立てたいだけの人生だった

Df4978f14401325586e9e286b140ac4c?s=47 n1215
February 16, 2019

 PHPでもgRPCサーバを立てたいだけの人生だった

2019/02/16 Laravel JP Conferenceでの発表スライド

Df4978f14401325586e9e286b140ac4c?s=128

n1215

February 16, 2019
Tweet

Transcript

  1. Laravel JP Conference PHPでもgRPCサーバを立てたいだけの人生だった 2019年2月16日 (土) 株式会社Nextat 中榮健二 Nextat Inc.

    1
  2. 1月某日 カンファレンスのタイムテーブルを見たぼく「???」 Nextat Inc. 2

  3. 実質LT枠だこれ! 紅白の裏番組みたいなセッションへようこそ! Nextat Inc. 3

  4. 自己紹介 京都から来ました ‒ 中榮健二 (なかえけんじ) ‒ twitter: @n̲1215  ‒ 株式会社Nextat

    取締役 ‒ baserCMS コアコミッター ‒ 普段は Laravel + Unity でソシャゲ開発など ‒ 好きなIlluminateコンポーネントはilluminate/container Nextat Inc. 4
  5. 発表概要 1. gRPCとは 2. Protocol Buffers 3. gRPCの使いどころ 4. PHPとgRPC

    5. PHPでgRPCサーバを実現する試み 6. gRPCサーバに見るPHPの未来 Nextat Inc. 5
  6. 今日のお題はLaravelにほぼ関係ない話ですが ぼくはLaravelにつよいエンジニアなので Laravelの話も申し訳程度に挟んでいきます Nextat Inc. 6

  7. 1. gRPCとは Nextat Inc. 7

  8. gRPCとは Google製のRPCフレームワーク → gpc.io RPC = Remote Procedure Call (遠隔手続呼出)

    'g' の意味はリリース毎に違うらしい 1.0 'g' stands for 'gRPC', 1.1 'g' stands for 'good', ... Microservicesの文脈でサービス間通信での利用例が増えている ハイパフォーマンス Nextat Inc. 8
  9. gRPCの通信プロトコル over HTTP/2を前提に策定されている メッセージのボディがバイナリ TCPコネクションの使い回し ネットワークリソース利用効率 最近gRPC‒Webという追加の仕様/ライブラリがGAに gRPCのための機能が足りないWebブラウザにも対応 Nextat Inc.

    9
  10. サーバ・クライアント間の通信の種類 4種類 HTTP/2だから効率よく双方向通信が可能 Nextat Inc. 10

  11. (1) Unary RPCs 1リクエスト / 1レスポンス 多くのWebアプリ開発者が慣れ親しんだもの Nextat Inc. 11

  12. (2) Server streaming RPCs 1リクエストに対しサーバが複数回のレスポンスを返す 送信完了までクライアントがストリームからメッセージを読む サーバープッシュ Nextat Inc. 12

  13. (3) Client streaming RPCs 複数回のリクエストを送信しサーバが1回レスポンスを返す 送信完了までサーバがストリームからメッセージを読む データのアップロードなどに利用可能 Nextat Inc. 13

  14. (4) Bidirectional streaming RPCs リクエストとレスポンスが多対多 双方向ストリーミング 順序に決まりはない チャットなどに利用可能 Nextat Inc.

    14
  15. 2. Protocol Buffers Nextat Inc. 15

  16. Protocol Buffers (Protobuf) gRPCが利用するIDL 兼 メッセージ交換用のバイナリフォーマット IDL = Interface Definition

    Language インタフェース記述言語 プログラミング言語に依存しない .protoファイルから言語実装を自動生成できる gRPCとは独立して使うこともできる 例)REST API + リクエストボディやレスポンスボディに Protocol Buffers Nextat Inc. 16
  17. Protocol Buffers 定義ファイル の書式 Message → リクエストやレスポンスのデータ構造を記述 Service → RPCの定義を記述

    // service.proto syntax = "proto3"; package service; service Echo { rpc Ping (Message) returns (Message) { } } message Message { string msg = 1; } Nextat Inc. 17
  18. protoc (Protocol Compiler) .protoファイルをprotocでビルドして各言語の実装を生成する 拡張が容易 $ protoc -I=. --php_output=. service.proto

    Nextat Inc. 18
  19. 3. gRPCの使いどころ Nextat Inc. 19

  20. gRPCのメリット パフォーマンス、ネットワークリソースの効率的利用 双方向通信 クライアントの実装が言語ごとに自動生成できる スキーマが定まるので型のエラーが起きにくい コンパイル時のエラーないし静的解析で検知しやすい 定義ファイルの内容がそのままAPIの定義となる 実装とAPIドキュメントが剥離しない JSON Schema

    / Open API / Swagger etc. からの解放! Nextat Inc. 20
  21. gRPCのデメリット 開発中に通信の中身を確認しにくい HTTP/2は実質暗号化通信が必須 バイナリフォーマット grpc‒gateway(gRPC to JSON proxy)などの周辺ツール 定義ファイルから各言語の実装をビルドするのが少し手間 サーバとクライアントで定義ファイルのバージョンが違って落ちるこ

    とも v3でクライアントが壊れにくいように改善している Nextat Inc. 21
  22. gRPCの使いどころ マイクロサービスのバックエンドでのサービス間通信 公式クライアントしかないスマホアプリ用のサーバ ゲームのAPIサーバ チャットやバトルシステムの通信方式をまとめられる gRPCの亜種の例もあり 一般向けの公開APIに用いるのは今のところつらそう ブラウザ対応は今後改善されていくはず Nextat Inc.

    22
  23. gRPC良さそうじゃん!使ってみたい! Nextat Inc. 23

  24. 4. PHPとgRPC Nextat Inc. 24

  25. ここでPHPerの皆様には 悲しいお知らせがあります Nextat Inc. 25

  26. PHPでのgRPCサーバは茨の道です PHP界隈ではgRPCの話はほとんど聞かない phpconでクライアントの話: php grpc‒client in phpcon2018 PHPによるgRPCクライアントは公式サポート リクエスト使い捨てのPHPの通常の動作方式ではStreamingが不可能 ドキュメント(PHP用):

    サーバ側はNode.JSを使ってね ❤ Google Groupでのとある発言 : PHPでgRPCサーバ作っても特殊な 構成になるしあまり役に立たないよね(意訳) 参考: なぜPHPはgRPCサーバーがサポートされていないのか? Nextat Inc. 26
  27. PHPerのぼく涙目 言語に依存しないって言ったじゃない!!!!! Google様謹製の某langに宗旨替えするしかないのか? Nextat Inc. 27

  28. PHPは歯ブラシ PHPは◯◯◯である ‒ quipped PHPは歯ブラシくらい興奮に値する。シンプルで、毎日使う便利な道 具。 伝説のPHP作者「Rasmus Lerdorf」名言集を聞くと嫌PHP厨がファ ビョる 歯を磨くための便利な道具

    Nextat Inc. 28
  29. えらい人が用途にあったプログラム言語 を選べとおっしゃる Nextat Inc. 29

  30. あなた達はいつも正しいね…… Nextat Inc. 30

  31. だがここは Laravel JP Con ロマン枠(実質LT枠) Nextat Inc. 31

  32. PHPerには歯ブラシで船舶を磨く 自由が与えられている ってボクが言ってました Nextat Inc. 32

  33. 5. PHPでgRPCサーバを実現する試み Nextat Inc. 33

  34. PHPだけ仲間はずれは寂しい 公式非サポートに反旗を翻すPHPerたちの姿が PHPのみで実現するわけではない 通常のPHPの構成でダメなら通常じゃない構成でやればいいじゃない Unary RPC対応だけでも嬉しい Nextat Inc. 34

  35. 5‒1. PHP‒FPM 前段にProxy gRPC → FastCGI 通常の構成から大きくは外れない GitHubでもいくつか見つかるがほとんど更新が止まっている bakins/grpc‒fastcgi‒proxy LTD‒Beget/grpc‒to‒fpm

    基本的にUnary RPCのみ。stream対応は辛そう Nextat Inc. 35
  36. Nextat Inc. 36

  37. 5‒2. Swoole https://www.swoole.co.uk/ コルーチンベースの非同期並行実行ライブラリ(PHP拡張/C言語) SwooleのHTTPサーバはHTTP/2にも対応し、ハイパフォーマンス Unary RPCが実装可能であることが示されている gRPCフレームワークとしての整備はされていない Swoole自体は中華圏で実績あり。WeChatのテンセントなど Nextat

    Inc. 37
  38. なぜか公式grpc‒clientのリポジトリに gRPCサーバ実装例 Nextat Inc. 38

  39. 5‒3. php‒grpc (RoadRunner)   https://github.com/spiral/php‒grpc RoadRunner (Golang製のPHPアプリケーションサーバ) を利用 前面のGoサーバがgRPCのリクエストを受け、PHPのworkerに振る 開発元は

    Spiral Scout 開発の経緯: PHP was never meant to die 最新のプレゼン資料(ロシア語): RoadRunner Nextat Inc. 39
  40. php‒grpcを試した 調べた中で一番コード生成などが整っていそうだった 前述の定義ファイルを // service.proto syntax = "proto3"; package service;

    service Echo { rpc Ping (Message) returns (Message) { } } message Message { string msg = 1; } Nextat Inc. 40
  41. Serviceの実装例 コンパイルするとインターフェースが自動生成されるので実装する <?php namespace App; class EchoService implements \Service\EchoInterface {

    public function Ping( ContextInterface $ctx, Message $in ): Message { $out = new Message(); return $out->setMsg(strtoupper($in->getMsg())); } } Nextat Inc. 41
  42. ワーカーのエントリポイントの実装例 RoadRunnerがワーカーを起動するエントリポイントのファイルを作成 <?php require 'vendor/autoload.php'; $server = new \Spiral\GRPC\Server(); //

    サービスを登録 $server->registerService( \Service\EchoInterface::class, new \App\EchoService() ); $streamRelay = new \Spiral\Goridge\StreamRelay(STDIN, STDOUT); $worker = new \Spiral\RoadRunner\Worker($streamRelay); $server->serve($worker); Nextat Inc. 42
  43. せっかくなのでクライアントもPHPで <?php require __DIR__ .'/vendor/autoload.php'; $cert = file_get_contents(__DIR__ . '/cert/server.crt');

    $credential = Grpc\ChannelCredentials::createSsl($cert); // クライアント側は定義ファイルからビルドした実装がそのまま使える $client = new Service\EchoClient('localhost:9001', [ 'credentials' => $credential, ]); $message = new Service\Message(); $message->setMsg(!empty($argv[1]) ? $argv[1] : 'Hello'); [$reply, $status] = $client->Ping($message)->wait(); $client->close(); echo 'Server Response: ' . $reply->getMsg() . PHP_EOL; Nextat Inc. 43
  44. サーバ golang製なのでビルドするとワンバイナリになる: rr‒grpc 設定はyamlで手軽に書ける .rr.yaml grpc: listen: "tcp://:9001" proto: "../protos/service.proto"

    定義ファイル tls: key: "../cert/server.key" cert: "../cert/server.crt" workers: command: "php worker.php" エントリポイントのファイルを実行 pool: numWorkers: 4 ワーカーの数 Nextat Inc. 44
  45. サーバを起動 $ rr-grpc serve -v -d Nextat Inc. 45

  46. クライアントを実行 Nextat Inc. 46

  47. サーバ側の様子 Nextat Inc. 47

  48. PHPで実装を書いたサーバとクライアントでgRPC通信ができた! ストリーミングはまだ試してません SwooleとRoadRunnerはイケそうな感触 Nextat Inc. 48

  49. 6. gRPCサーバに見るPHPの未来 Nextat Inc. 49

  50. PHPアプリケーションサーバの新潮流 Swoole、PHP PM、RoadRunner etc. gRPCのためだけに作られたわけではない 非同期・並行処理やハイパフォーマンスのため アプリケーションサーバの柔軟性のため よりPHPに近いところもしくはPHP自体でサーバを制御したい alt PHP‒FPM

    Nextat Inc. 50
  51. 従来のPHPのメリット: リクエストごとに状態がリセットされる 不正な状態が後に残りにくい 状態に無頓着なコードでも比較的安全 Nextat Inc. 51

  52. デメリット リクエストごとに初期化処理 パフォーマンスが犠牲に PHP自体はとても速くなったにも関わらず リクエスト毎に同じ処理をしていては遅い フルスタックなLaravelは顕著に重い 色々なキャッシュで高速化 Nextat Inc. 52

  53. alt PHP‒FPMによるトレードオフの反転 PHPアプリケーションの初期化処理を前倒しできるものが多い サーバorワーカーの立ち上げ時に初期化 リクエストごとの重複処理がなくなる Appサーバ起動時の初期化は他言語では普通にやっていること キャッシュしたらリクエストをまたいで状態が残るのは同じでしょ? Nextat Inc. 53

  54. PHP最大のメリットを捨てて "速さ"を手に入れる Nextat Inc. 54

  55. 参考: Swooleのベンチマーク TechEmpower Framework Benchmarksより PHP7 Laravel Nextat Inc. 55

  56. Swoole 多言語の強豪たちを押しのけ4位 PHPというかC Nextat Inc. 56

  57. 今からできること PHPでgRPCサーバを実戦投入するのは時期尚早 安定して流行すると仮定しても数年はかかる 今からPHPの変化に備えることはできる Nextat Inc. 57

  58. 今からできること ~ HTTP FastCGIよりHTTPの世界に近くなる HTTPやTLSの勉強 HTTP/2全然わからん。え、もうHTTP/3が? HTTPメッセージのライブラリへの習熟 PSR‒7が選ばれることが予想される。実装はいくつかある LaravelはSymfony HTTP Foundationを採用しているが PSR‒7

    Bridgeはある Nextat Inc. 58
  59. 今からできること ~ 疎結合な設計 フレームワークとユーザコードの分離 複数の構成を考慮したフレームワークがどんどん出てきそう いざという時に移し替えられるように プレゼンテーション層の分離 サクッとHTTPメッセージの中身を変更できるように Nextat Inc. 59

  60. 今からできること ~ 初期化処理と状態 イミュータビリティを意識 完全コンストラクタ サービスコンテナによる依存解決に気をつける HTTPリクエスト依存のクラスをコンテナに入れない バグの温床になる LaravelのFormRequestの設計はこの文脈ではアンチパターン HTTPリクエストから導出される値や認証済ユーザなども同様

    個別のHTTPリクエストを受ける前に解決できる処理なのかどうか キャッシュやパフォーマンスを考えることにも繋がる Nextat Inc. 60
  61. まとめ gRPCとProtocol Buffersはいいぞ PHPのgRPCサーバは公式サポートがない が、PHP界隈でもgRPCサーバに対応する動きがある Swoole、RoadRunnerなど脱PHP‒FPMの流れ PHPの今後に期待 Nextat Inc. 61

  62. 追伸 RoadRunnerを触っていたらビルドの都合でgolang不可避 入信した 1.11で入ったModulesが便利 Nextat Inc. 62

  63. ご清聴ありがとうございました この後のAsk The Speakerでも質問受付 お手柔らかに We're hiring!! Nextat Inc. 63