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

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

n1215
February 16, 2019

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

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

n1215

February 16, 2019
Tweet

More Decks by n1215

Other Decks in Programming

Transcript

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

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

    5. PHPでgRPCサーバを実現する試み 6. gRPCサーバに見るPHPの未来 Nextat Inc. 5
  3. 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
  4. Protocol Buffers (Protobuf) gRPCが利用するIDL 兼 メッセージ交換用のバイナリフォーマット IDL = Interface Definition

    Language インタフェース記述言語 プログラミング言語に依存しない .protoファイルから言語実装を自動生成できる gRPCとは独立して使うこともできる 例)REST API + リクエストボディやレスポンスボディに Protocol Buffers Nextat Inc. 16
  5. 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
  6. 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
  7. 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
  8. ワーカーのエントリポイントの実装例 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
  9. せっかくなのでクライアントも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
  10. サーバ 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