LoginSignup
0
0

More than 3 years have passed since last update.

PHP7.2 × DockerでgRPCクライアントを使うための環境構築

Last updated at Posted at 2020-07-24

Goでクライアントを作るときには、brewgo getでパッケージをいくつか入れるだけで済むのですが、PHPの方ではいくつかハマりどころがあったのでまとめました。

前提

  • protoコマンドがインストールされている
  • 使用するRPC方式はUnaryRPCである
  • コード生成はローカル環境で行う

扱うprotoファイル

下記のprotoに少し変更をかけたものを扱います。
https://grpc.io/docs/languages/php/quickstart/

hello.proto
package hello;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

コード生成

下記ページを参考にしました。
https://grpc.io/docs/languages/php/quickstart/

コード生成用のPHPプラグインを追加

protoファイルからPHP用の各種クラスを生成するために、grpc_php_plugin を入れる必要があります。

$ git clone -b v1.30.0 https://github.com/grpc/grpc
$ cd grpc && git submodule update --init && make grpc_php_plugin

すると、ソースを展開したディレクトリに bins/opt/grpc_php_plugin が生成されます。

コード生成実行

下記コマンドを入力します。

$ protoc --proto_path=proto \
  --php_out=src/gen \
  --grpc_out=src/gen \
  --plugin=protoc-gen-grpc=./grpc/bins/opt/grpc_php_plugin \
  ./proto/hello.proto

この時のオプションとして、

  • --proto_path にはprotoファイルが配置されているディレクトリを指定する
  • --php_out--grpc_out は同じディレクトリを指定する
  • --plugin=protoc-gen-grpc= に、先ほどプラグインをインストールしたディレクトリの bins/opt/grpc_php_plugin を指定する

を行います。
これでコード生成はOKです。

クライアント環境準備

インストールするパッケージは下記ページを参考にしました。
https://cloud.google.com/php/grpc?hl=ja#php-implementation

Dockerの上で動かしたPHPで、gRPCのリクエストを送るための環境を構築します。

php.ini

grpc.so 拡張パッケージの記述がポイントです。

php.ini
[Date]
date.timezone = "Asia/Tokyo"

[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"

extension = grpc.so

Dockerfile

peclでgrpcパッケージを入れることがポイントです。

FROM php:7.2-stretch

RUN apt-get update -y \
    && apt-get install -y zip autoconf zlib1g-dev \
    && apt-get clean

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
COPY php.ini /usr/local/etc/php/php.ini
RUN pecl install grpc

WORKDIR /var/local
COPY . .
RUN composer install

composer.json

ここでは先ほどのコード生成によってファイルが格納された先を src/gen として扱っています。

composer.json
{
    "autoload": {
        "psr-4": {
            "Hello\\": "src/gen/Hello",
            "GPBMetadata\\": "src/gen/GPBMetadata"
        }
    },
    "require": {
        "php": ">=7.2",
        "google/protobuf": ">=3.0",
        "grpc/grpc": ">=v1.27.0"
    },
    "repositories": [
        {
          "type": "vcs",
          "url": "https://github.com/stanley-cheung/Protobuf-PHP"
        }
    ]
}

ポイントは、

  • google/protobuf パッケージのインストール
  • grpc/grpc パッケージのインストール
  • コード生成されたクラスをautoloadで読み込み指定する

ことです。

docker-compose.yaml

先ほどのphp.iniを、ボリュームマウントでコンテナに配置することがポイントです。

docker-compose.yaml
version: "3"
services:
  php:
    build: .
    volumes:
      - ./php.ini:/usr/local/etc/php/php.ini
      - .:/var/local/
    ports:
      - 80:80

クライアント実装

実装例です。

srcipts/RunHello.php
<?php

use Hello\GreeterClient;
use Hello\HelloRequest;

$hostname = 'localhost:8000';
$client = GreeterClient($hostname, [
    'credentials' => \Grpc\ChannelCredentials::createInsecure()
]);

$request = new HelloRequest();
$request->setName("DummyName");
list($reply, $status) = $client->SayHello($request)->wait();
$message = $reply->getMessage();

この時vendor配下に \Grpc\ChannelCredentials クラスが存在せず、エディタでは警告等が出ます。
これはcomposerで入れるものではなく、Dockerfileとphp.iniで指定したgrpc拡張パッケージに含まれています。

この辺↓
https://github.com/grpc/grpc/blob/f3e748f646f482b9de2801c1542094bd5b6fdf3a/src/php/ext/grpc/channel_credentials.c#L133

よって、必要なライブラリ自体はDocker側にインストールされているため、実行時には正常に通ります。
(個人的にはここがハマりポイントでした)

実行

オートローダーを読み込んで、クライアント実装のスクリプトを読み込めば実行されます。

$ docker-compose run --rm php -a
php> require_once('vendor/autoload.php');
php> require_once('scripts/RunHello.php');

あとはこのクライアントをクラスに閉じ込めたり、composerのパッケージ化などを行えばWebサーバー等にも組み込むことができます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0