Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
0
Help us understand the problem. What is going on with this article?
@s_satoh

PHP7対応プロファイラを試す(XHProfを入れたら502エラーが頻発した件)

More than 1 year has passed since last update.

はじめに

株式会社オークファンの佐藤です。
Truly Ergonomic社が新しいキーボードのファンディングを始めたことに動揺している今日このごろです。
https://www.trulyergonomic.com/store/index.php

本記事では、私が半年前にハマった、PHP7環境対応のプロファイラ選びの話をお届けします。

前提

高いユーザビリティを保つためには、レスポンス速度は重要です。サイトが遅ければ遅いほど離脱率が上がるのは、もはや周知の事実です。
しかし、それを定量的に測定するのはなかなか大変なこと。そして、原因を追求するのも大変なことです。そこで、弊社のメインサービスである オークファン の開発環境にプロファイラを入れることにしました。
これにより、エンジニア側で(だいたい、プログラムを遅くするのはエンジニアの仕業です)問題を早期把握できるようにしています。

オークファンはPHP7 + Nginx環境で稼働しています。プロファイラもPHP7対応版を入れなければいけません。
今回はFacebookが作成したことで有名なXHProfの、PHP7非公式版を利用しました。

非公式とはいえ、手順通りにインストールして終わりかと思ったら……

502エラーが頻発

ここで大きな問題が発生しました。
プロファイラを入れた途端、リクエストが不定期に、しかし高頻度で502エラーを返すのです。

有料プロファイラとして有名なTidewaysのバージョンならもうちょっと信頼できるかと思ったら、今度は100%の確率で502エラーを返すようになりました。

ぐぐっても似たような現象は出てこないため、PHP7環境一般というより、オークファン固有の問題と考えざるを得ません。
そのあたりを想像しながら、ライブラリを入れ替えたり、コアダンプを取ったりして調査しました。

解決

特定のプロファイラを入れたら解決しました。
https://github.com/longxinH/xhprof

(´-`).。oO(なんか納得行かない……)
なので、もうちょっと調べてみました。

なぜ?

異常終了したコアダンプを見ると、メモリ解放系の処理のところで落ちています。

example.dmp
Core was generated by `php-fpm: pool www            '.
Program terminated with signal 11, Segmentation fault.
#0  hp_fast_alloc_hprof_entry () at /phpng-xhprof/phpng_xhprof.c:1163
1163            XHG(entry_free_list) = p->prev_hprof;
Missing separate debuginfos, use: debuginfo-install php-fpm-7.1.11-1.el6.remi.x86_64

この段階でマルチプロセス系の問題かな、と予想しました。

実質マルチプロセス

実は、オークファンのサイト上では、内部で自分にcurlを送っているコードがいくつかあるのです。

自分にcurlするということは、最低2つのプロセスが同時に存在しているということです。
そのときに、

  1. プログラムAが起動し、同時にプロファイラA'が起動する
  2. プログラムAが同一サーバーの別プログラムBにCurlする
  3. プログラムBが起動し、同時にプロファイラB'が起動する
  4. プログラムBが終了し、同時にプロファイラB'が終了する
  5. プログラムBの終了時点で、プロファイラB'の終了処理が呼び出される
  6. プロファイラB'の終了処理が、プロファイラ共有のメモリ領域を破壊する
  7. プログラムAが再開するが、プロファイラA'のメモリ領域は破壊されているので異常終了する

といった現象が発生しているのでは?
つまり、うまくいくプロファイラは、関連するリクエストが終了するまでメモリ領域を保管できているのでは?

実際、うまくいくソースコードとうまくいかないソースコードを見ると、うまくいく方はメモリの解放位置が違いました。
PHP_MSHUTDOWN_FUNCTION()とPHP_RSHUTDOWN_FUNCTION()を使い分けることで、マルチプロセスに対応できたのかなと思いました。

↑現時点でソースコードを見る限り、原因はこれじゃないかもしれません……

結論

(´-`).。oO(ライブラリを使う際は幅広く検討しましょう……)

最後に

株式会社オークファンでは、予想外の要求数百億件のデータと戦う、PHPエンジニア・Javaエンジニアを募集中です。
データは使ってこそ価値を持ちます。価値を生むのはあなたのコードです!

0
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
s_satoh
自称"Freedom Dreamer"。以前にはライブレポートを書いたり、プロレスを取材したり、エンジニア以外のこともやってきました。現在はマトモなエンジニアとして修行中です。メタルが大好き。
aucfan
あらゆる商品に関する正確でフェアな情報を提供する企業として、世界における唯一無二の存在となるというビジョンの元、基盤となる技術を作り続けるマザーズベンチャー

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
0
Help us understand the problem. What is going on with this article?