Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

n1215
PRO
February 16, 2019

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

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

n1215
PRO

February 16, 2019
Tweet

More Decks by n1215

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

  4. 自己紹介
    京都から来ました
    ‒ 中榮健二 (なかえけんじ)
    ‒ twitter: @n̲1215 
    ‒ 株式会社Nextat 取締役
    ‒ baserCMS コアコミッター
    ‒ 普段は Laravel + Unity でソシャゲ開発など
    ‒ 好きなIlluminateコンポーネントはilluminate/container
    Nextat Inc. 4

    View Slide

  5. 発表概要
    1. gRPCとは
    2. Protocol Buffers
    3. gRPCの使いどころ
    4. PHPとgRPC
    5. PHPでgRPCサーバを実現する試み
    6. gRPCサーバに見るPHPの未来
    Nextat Inc. 5

    View Slide

  6. 今日のお題はLaravelにほぼ関係ない話ですが
    ぼくはLaravelにつよいエンジニアなので
    Laravelの話も申し訳程度に挟んでいきます
    Nextat Inc. 6

    View Slide

  7. 1. gRPCとは
    Nextat Inc. 7

    View Slide

  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

    View Slide

  9. gRPCの通信プロトコル
    over HTTP/2を前提に策定されている
    メッセージのボディがバイナリ
    TCPコネクションの使い回し
    ネットワークリソース利用効率
    最近gRPC‒Webという追加の仕様/ライブラリがGAに
    gRPCのための機能が足りないWebブラウザにも対応
    Nextat Inc. 9

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  15. 2. Protocol Buffers
    Nextat Inc. 15

    View Slide

  16. Protocol Buffers (Protobuf)
    gRPCが利用するIDL 兼 メッセージ交換用のバイナリフォーマット
    IDL = Interface Definition Language インタフェース記述言語
    プログラミング言語に依存しない
    .protoファイルから言語実装を自動生成できる
    gRPCとは独立して使うこともできる
    例)REST API + リクエストボディやレスポンスボディに
    Protocol Buffers
    Nextat Inc. 16

    View Slide

  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

    View Slide

  18. protoc (Protocol Compiler)
    .protoファイルをprotocでビルドして各言語の実装を生成する
    拡張が容易
    $ protoc -I=. --php_output=. service.proto
    Nextat Inc. 18

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  24. 4. PHPとgRPC
    Nextat Inc. 24

    View Slide

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

    View Slide

  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

    View Slide

  27. PHPerのぼく涙目
    言語に依存しないって言ったじゃない!!!!!
    Google様謹製の某langに宗旨替えするしかないのか?
    Nextat Inc. 27

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  35. 5‒1. PHP‒FPM 前段にProxy
    gRPC → FastCGI
    通常の構成から大きくは外れない
    GitHubでもいくつか見つかるがほとんど更新が止まっている
    bakins/grpc‒fastcgi‒proxy
    LTD‒Beget/grpc‒to‒fpm
    基本的にUnary RPCのみ。stream対応は辛そう
    Nextat Inc. 35

    View Slide

  36. Nextat Inc. 36

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  40. php‒grpcを試した
    調べた中で一番コード生成などが整っていそうだった
    前述の定義ファイルを
    // service.proto
    syntax = "proto3";
    package service;
    service Echo {
    rpc Ping (Message) returns (Message) {
    }
    }
    message Message {
    string msg = 1;
    }
    Nextat Inc. 40

    View Slide

  41. Serviceの実装例
    コンパイルするとインターフェースが自動生成されるので実装する
    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

    View Slide

  42. ワーカーのエントリポイントの実装例
    RoadRunnerがワーカーを起動するエントリポイントのファイルを作成
    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

    View Slide

  43. せっかくなのでクライアントも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

    View Slide

  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

    View Slide

  45. サーバを起動
    $ rr-grpc serve -v -d
    Nextat Inc. 45

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  61. まとめ
    gRPCとProtocol Buffersはいいぞ
    PHPのgRPCサーバは公式サポートがない
    が、PHP界隈でもgRPCサーバに対応する動きがある
    Swoole、RoadRunnerなど脱PHP‒FPMの流れ
    PHPの今後に期待
    Nextat Inc. 61

    View Slide

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

    View Slide

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

    View Slide