Laravel-Swooleでunix domain socketを使う方法

最近PHPで新しくサーバーを立てる機会があったのですが、出来るだけパフォーマンスのオーバーヘッドを意識したくない && シンプルな処理しかしない小規模なサーバーということもありポピュラーなnginx + fpmの構成ではなく、Laravel-Swooleを採用しました。

Laravel-Swooleは、swooleというPHPでイベント駆動な非同期サーバーを実現するextensionをLaravel/Lumenで簡単に利用可能にするライブラリです。

ドキュメントをひと通りチェックしたところ、The support of swoole_http_server for Http is not complete. So, you should configure your swoole server with nginx proxy in your production environment.と記載があり、単体での利用は推奨されていないようでした。

9. Nginx Configuration · swooletw/laravel-swoole Wiki · GitHub

ただ、サンプルで用意されているnginxの設定はリバースプロキシをTCP/IPで行っており、Laravel-Swooleのドキュメントにはunix domain socketに関する具体的な設定例は見当たりませんでした。 一応、swoole自体もunix socketに対応していますし、Laravel-Swooleの設定項目にもunix socketが存在します。


swoole_http.php

<?php

return [
    'server' => [
        'host' => env('SWOOLE_HTTP_HOST', '/var/run/swoole.sock'),  // socketを置くパスを指定する
        'port' => env('SWOOLE_HTTP_PORT', '0'), // unix socketを使う場合0にする
        'socket_type' => SWOOLE_UNIX_STREAM, // unix socktを使う場合 SWOOLE_UNIX_STREAM / SWOOLE_UNIX_DGRAM を指定する
        // ....
    ],
    // ...
];

以上でswoole自体の設定は出来たのです、Laravel-Swooleとnginxを別ユーザーで実行する場合socketのパーミッションをいじってやる必要があります。

取り急ぎpermissionを変更したいのですが、php-fpmでいうところのlisten.modeに相当する設定項目がLaravel-Swooleにはないようです。

dockerで利用するので、swoole起動時にフックしたいのですが、どうしようかと思ったところswooleのexampleに参考になりそうな記述がありました。
どうやら、swooleサーバーの起動時に発行されるイベントにフックしてchmodを叩いてやれば良いようです。

swoole-src/stream_server.php at 15404958c76edfe745e18a9219439f4bd9993b71 · swoole/swoole-src · GitHub

Laravel-Swooleでは、swoole.startというイベントが発行されるので、それにフックしてsocketのパーミッションを変更します。

laravel-swoole/Manager.php at master · swooletw/laravel-swoole · GitHub


EventServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
use SwooleTW\Http\Server\Facades\Server;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        Registered::class => [
            SendEmailVerificationNotification::class,
        ],
    ];

    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();

        // swoole 起動時にsocketのpermissionを変更する
        Event::listen('swoole.start', function () {
            $server = $this->app->make(Server::class);
            chmod($server->host, 0666);
        });
    }
}

ただ、unix domain socketを使う場合のpermissionは666でベストなのか、dockerで複数コンテナ使う場合のユーザーの取り回しなどは未解決、、

FPM opcache + preload / swoole / PHPP-PMあたりの比較してみたい。