0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHP DotEnvのスレッドセーフ対応

Posted at
apache php

EC2のマイクロなインスタンスタイプでホストしているWEBサーバーに同時並列リクエストでワークロード負荷を与えると、DBやセッションストアのmemcachedへのTCP接続が稀に失敗する事象に遭遇し、手間取った

  • MySQL / No such file or directory
    TCP/IP接続なんだが、UNIXドメインソケットが見つからない系のエラー?
  • memcached / can not to connect memcached

切り分け調査

  • ワークロード
    • EC2インスタンスのロードアベレージは余裕で1未満
    • EC2のネットワーク帯域は余裕
    • コネクション数、パケットロストなどRDS, Elasticacheのメトリクスに異常が見られない
  • どこかで蹴られている
    • 一応Route53のプライベートホストゾーンから、エンドポイント直に変更してみるが状況変わらず
    • VPCのDNSスロットリング制限で蹴られている?いやそこまでいじめてない

Amazon が提供する DNS サーバーは、Elastic Network Interface ごとに 1 秒あたり 1024 パケットの制限を適用します。Amazon が提供する DNS サーバーは、この制限を超えたトラフィックをすべて拒否します。
VPC DNS スロットリングが原因で、Amazon が提供する DNS サーバーへの DNS クエリが失敗しているかどうかを確認するにはどうすればよいですか?

ここまで遠回りして、フレームワークのセッションアダプタからphpネイティブに変更するも失敗するが、きれいに{ホスト}:{ポート}が歯抜けのエラーログが出た

PHP Warning:  session_start(): Failed to parse session.save_path (error at offset 0, url was 'tcp://:')

DotEnv

apache mpm_event_module×スレッドセーフmod_phpな環境で接続コンフィグにDotEnvにImmutableで.envファイルをローディングさせて$_ENVスーパーグローバルで参照していた

php
$dotenv = Dotenv::createImmutable(__DIR__);
$dotenv->load();

DotEnvをcreateImmutableで起動するとputenv/getenvがスレッドセーフではないため、次の順序で並列リクエストの環境変数がタイミングによってクリーンアップされたようだ。

1 番目のリクエスト: 変数が存在しない -> ロード
2 番目のリクエスト: 変数が存在する -> ロードしない
1 番目のリクエスト: 終了、変数をクリーンアップする
2 番目のリクエスト: 変数を使用する -> 変数はもう存在しない、によってクリーンアップされる1回目のリクエスト
https://github.com/vlucas/phpdotenv/issues/248
When you have two or more sites on one server, the sites's .env will affect each other · Issue #219 · vlucas/phpdotenv

Using getenv() and putenv() is strongly discouraged due to the fact that these functions are not thread safe, however it is still possible to instruct PHP dotenv to use these functions. Instead of calling Dotenv::createImmutable, one can call Dotenv::createUnsafeImmutable, which will add the PutenvAdapter behind the scenes. Your environment variables will now be available using the getenv method, as well as the super-globals:
公式にもスレッドセーフでない旨ため注意書きがあった

Immutableモードは定義済みの環境変数のローディングは無視され(2)、リクエストの終了とともに破棄される(4)
一方でMutableモードはリクエストごとに独立したストアに確保するとみえて、スレッド競合の問題は起きなくなった
createUnsafeImmutableでv5系の実装で、v4系には存在しなかったのでMutableで検証

$dotenv = Dotenv::createMutable(__DIR__);
$dotenv->load();
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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?