開発ブログ

株式会社Nextatのスタッフがお送りする技術コラムメインのブログ。

電話でのお問合わせ 075-744-6842 ([月]-[金] 10:00〜17:00)

  1. top >
  2. 開発ブログ >
  3. PHP >
  4. [PHP]Golang製PHPアプリケーションサーバRoadRunnerを試す

[PHP]Golang製PHPアプリケーションサーバRoadRunnerを試す

こんにちは、ナカエです。

本日はGo言語で書かれたPHPアプリケーションサーバ、RoadRunnerについての記事です。

PHPアプリケーションサーバの新潮流

昨今のPHP界隈では、Swooleに代表されるように、よくあるApache+mod_phpやPHP-FPMによる従来の構成と異なる実行方法を持つPHPのためのHTTPサーバまたはアプリケーションサーバが少しずつ注目を集めるようになってきました。

従来のPHPの実行方式における「1つのリクエストごとにアプリケーションの初期化が行われレスポンスを返すと状態がリセットされる」という前提を覆し、アプリケーションの初期化の前倒しによる大幅なパフォーマンスの向上を図れると話題を呼んでいます。

RoadRunner

RoadRunnerもそんな新興のアプリケーションサーバの1つで、Go言語で書かれています。 HTTPのリクエストを前段のGoのHTTPハンドラがさばき、ロードバランサ/プロセスマネージャがPHPのWorkerにリクエストを割り振るという構成になっています。

開発元のSpiral Scoutのブログ記事 PHP was never meant to die によると、彼らは開発スタックにGolangを導入してその力を実感し、Golangの力を借りて既存のPHPのアプリを強化できないだろうかと考えたのが開発のきっかけだったようです。 上記記事は2013年に書かれたPHP is meant to dieという記事へのアンサー記事にもなっており、熱意溢れるとても良い話でした。

通常のHTTPサーバだけでなく、RoadRunnerによるgRPCサーバの実装も公開されており、PHPの新しい可能性を見せてくれます。

RoadRunnerを試す

RoadRunnerを動かすには、ビルド済みのバイナリをDLするか、Golangを使ってビルドする必要があります。 今回はホストマシンの環境を汚したくないため、Docker環境を構築しました。

Dockerfile

FROM php:7.2-cli

RUN apt-get update && apt-get install -y --no-install-recommends \
  wget \
  git \
  vim \
  zlib1g-dev \
  unzip

# Install Go
RUN wget -O - https://dl.google.com/go/go1.11.4.linux-amd64.tar.gz | tar -C /usr/local -xzf -
ENV PATH $PATH:/usr/local/go/bin
ENV GO111MODULE on

# Install RoadRunner
WORKDIR /go/src
RUN git clone --depth 1 https://github.com/spiral/roadrunner \
  && cd /go/src/roadrunner \
  && make \
  && make install
COPY ./.rr.yaml /etc/roadrunner/.rr.yaml

# Install PHP Extensions
RUN docker-php-ext-install zip \
  && docker-php-ext-install opcache \
  && docker-php-ext-enable opcache

# Install Composer
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" \
  && php -r "if (hash_file('SHA384', 'composer-setup.php') === rtrim(file_get_contents('https://composer.github.io/installer.sig'))) { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" \
  && php composer-setup.php \
  && php -r "unlink('composer-setup.php');" \
  && mv composer.phar /usr/local/bin/composer

WORKDIR /var/www

ENTRYPOINT ["/usr/local/bin/rr", "serve", "-c", "/etc/roadrunner/.rr.yaml"]

PHP用のイメージを元にしていますが、RoadRunnerのビルドのためにGo1.11も入れています。

下記Gitリポジトリをクローンすればdocker-composeにより手軽に環境を立ち上げることができます。

n1215/roadrunner-docker-skeleton

PHPの処理の書き方

RoadrRunnerの設定ファイルでPHPのWorkerのエントリポイントとなるファイルが指定されており、

http:
  address: :8080
  workers:
    command: "php /var/www/app/psr-worker.php"
    pool:
      numWorkers: 4

そのファイル内にPSR-7のリクエストを受け取ってPSR-7のレスポンスを返す処理を記述するのが基本となります。

<?php
declare(strict_types=1);

ini_set('display_errors', 'stderr');
include 'vendor/autoload.php';

$relay = new Spiral\Goridge\StreamRelay(STDIN, STDOUT);
$psr7 = new Spiral\RoadRunner\PSR7Client(new Spiral\RoadRunner\Worker($relay));

while ($req = $psr7->acceptRequest()) {
    try {
        $resp = new \Zend\Diactoros\Response();
        $resp->getBody()->write('Hello, world!');
        $psr7->respond($resp);
    } catch (\Throwable $e) {
        $psr7->getWorker()->error((string)$e);
    }
}

既存のフレームワークとの統合

PSR-7のリクエストからレスポンスを返せれば処理の実体は何でも良く、既存のフレームワークを組み合わせることももちろん可能です。

RoadRunnerのWikiにはPSR-7-Bridgeを利用したLaravelSymfonyとの統合例が掲載されています。

Laravelでnginx+PHP-FPMの構成とパフォーマンスを比較した記事 用 RoadRunner 加速 Laravel 应用(注: 中国語)によると、LaravelのHome画面で30倍ものトランザクションを叩き出しています。

まとめ

今回は新進気鋭のアプリケーションサーバ、RoadRunnerを試すためのDocker環境を構築しました。 個人的に、SwooleやRoadRunnerが見せてくれるPHPの新たな可能性に大いに期待しています。今後も調査を継続していく予定です。

TOPに戻る