2022年 9月 の投稿一覧

Laravel Sail のプロジェクトを新規作成する際にDocker is not running. – Docker Desktop 再起動で改善

こんにちは、ウチイダです。

今日は、以前からたびたび発生しては時間を地味に奪っていくエラーについて。

Laravel Sail のプロジェクトを作成する際に、以下のようなエラーが出ます。

$ curl -s "https://laravel.build/laravel_app" | bash
Docker is not running.

そもそも、WSLからdocker コマンドが使えません。ソケットが開いてない?

$ docker ps
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?

WSLの再起動をやってみても、解消したりしなかったり、だったのです。

しかし、最近試してみた方法で、すぐに直せることが分かったのでメモしておきます。

タスクバーからDockerのアイコンを右クリック > Restart する

以上です。

DockerDesktopを再起動するだけ

WSLを止めて起動しなおしたり、WSL側のDocker デーモンの動作を確認したりしてましたが、全然関係なかったみたいです。

発生する原因はわからないままなのですが、すぐに解消できるようになったので、しばらくこの方法で対応したいと思います。

以上、あなたのお役に立てれば幸いです。

住所の文字列から都道府県を抜き出すPHPの実装例

こんばんは、ウチイダです。

住所のテキストしかない状況で、都道府県を抜き出す処理を作ったとき、意外にもちょっとてこずったのでメモしておきます。

    /**
     * 住所から都道府県を切り出す
     * 要素0に都道府県、要素1に市区町村以下の住所を格納した配列を返す
     * @param string $address
     */
    function separateAddressPref(string $address)
    {
        $array = [];
        preg_match('/^(京都府|.*?[都道府県])(.*$)/u', $address, $array);
        $ret = [];
        if (count($array) > 0) {
            $ret[] = $array[1];
            $ret[] = $array[2];
        } else {
            $ret[] = '';
            $ret[] = $address;
        }
        return $ret;
    }

住所がある場合、たいてい郵便番号などもあるので、その場合は郵便番号から都道府県を取ってくる方が楽だと思います。

今回は郵便番号がない状況だったので、住所の文字列から取り出す仕様になりました。

てこずりポイントは、コード見ても明らかなように「京都府」という特殊パターンの存在です。

「都」と「府」が両方含まれているので、京都府だけ一塊の文字列として扱うようにしています。

以上です。

あなたのお役に立てれば幸いです。

Laravelのqueue をcron で動かすときの設定 — レンタルサーバ会社さんにお叱りを受けたので修正した

こんばんは、ウチイダです。

結構前なのですが、しょうもないヤラカシをしたので、自戒を込めて記事にしておきます。

冒頭、まずはお詫びを。エックスサーバーさん、その節は大変失礼いたしました🙇

何があったのか

それは、エックスサーバー上でLaravelのアプリケーションを運用するお仕事でした。

そこそこ本格的なアプリケーションで、外部サービスのAPIへのリクエストなどの重い処理が走るので、ジョブ・キューを使うことにしました。

本来ならドキュメントにもある通り、supervisor などを使ってワーカープロセスをデーモン化したいところです。

しかし、さしものエックスサーバといえども、supervisor は利用できないようでした。

そこで、cron を使ってワーカープロセスを定期的に起動するようにしました。

実際に記述していたcron エントリは以下のような感じです。ディレクトリのパスだけ、ダミーのものに変えています。

* * * * * cd path/to/laravel_project && /opt/php-8.1/bin/php artisan queue:work --max-time=36000 --timeout=36000 --env=production >> /dev/null 2>&1

設定後しばらくしたら、エックスサーバーのサポートからメールで連絡がありました。

要旨としては、契約しているサーバーが高負荷になっており、cron で実行されてるプロセスが原因なので早急に対策せよというものでした。

慌ててエラーログを確認したところ、DBとのコネクションリソースも使い果たしていました…

[2022-07-31 12:40:51] production.ERROR: SQLSTATE[HY000] [1226] User 'my_user' has exceeded the 'max_user_connections' resource (current value: 100) // ...以下略

サポートから指摘があった通り、CPU負荷も高くなっていただろうと思います。

何がいけなかったのか

冷静にcron設定を見直してみたところ、いくつか問題点に気づきました。

  • 重い処理が渡されたときのために –max-time と –timeout を 36000秒(10時間!)というめちゃ大きな値にしている
  • –stop-when-empty オプションをつけていないので、–max-time オプションで指定している秒数、ワーカープロセスが残り続ける
  • cron の起動は最短間隔(1分ごと)にしてあるため、新しいワーカープロセスが頻繁に生成される

つまり、古いプロセスが消えることなく、新しいプロセスを次々に作ってしまう設定だったということです。

ちょっと落ち着いて考えればわかりますね…あほすぎる…

cron エントリの修正

今回の原因は、古いワーカープロセスが終了せず、時間の経過とともに増え続けてしまうことでした。

というわけで、以下のようにcronエントリを修正しました。

*/5 * * * * cd path/to/laravel_project && /opt/php-8.1/bin/php artisan queue:work --max-time=300 --timeout=36000 --env=production >> /dev/null 2>&1

修正したのは以下の点です。

  • cron の実行周期を、1分から5分に変更
  • –max-time=300 に指定して、ワーカープロセスの生存時間を5分に設定
  • –timeout は、日に1回のバッチ処理が数時間かかるものがあるので、36000のままにしておく

5分毎にワーカープロセスがcronによって生成され、次の生成までワーカープロセスが少なくとも1つ存在するようにしました。

処理に5分以上かかるジョブが送られると、一時的に2つ以上のワーカープロセスが存在することになります。

そんなに重い処理が頻繁に発生するアプリケーションではなかったので、問題にはならないはずです。

これでも負荷が上がってしまうようなら、VPSとかクラウド環境に移行することをクライアントに提案するつもりです。

ちなみに、Laravel の日本語ドキュメントにも、queue コマンドの使い方は詳しく書いてあります。RTFM!!

https://readouble.com/laravel/9.x/ja/queues.html#running-the-queue-worker

まとめ

あらためまして、エックスサーバーさん、および同一サーバーを利用していた方、ご迷惑おかけしました。

ドキュメントをちゃんと読むことと、ローカルでの動作テストをきちんと行うことを改めて心に刻みました。

この記事を見ているみなさんはこんなアホなミスはしないと思いますが、ヤラカシ事例としてお知りおきください。

以上、あなたのお役に立てれば幸いです。