LoginSignup
5
3

More than 5 years have passed since last update.

Lambda×puppeteerでクロールしようとしたらゾンビプロセスの沼に浸かった記録(解決済)

Posted at

headless chromeを使ってサーバーレスでいい感じにクローリングするプログラムを作ろうとしたら沼に浸かりました。
うまいこと動くテンプレートをgithubで公開しています。
https://github.com/inatomitk/lambda-puppeteer-template

環境

  • puppeteer ※headless chromeのNode.jsのAPI
  • AWS Lambda
  • Node.js

沼りポイント

headless chromeのバイナリがLambdaにアップロードできない

Lambdaには一つのfunctionあたり50MBまでのファイルしかアップロードできないという制限があります。
普通の処理ならその制限を気にする必要もない(まず、そんな大きいファイルにならない)です。が、headless chromeはサイズが大きい(50MB弱くらい)なので、その他諸々のパッケージを含めるとアップロードできない可能性が高いです。

なので、Lambdaのlayerを使用しました。layerを使用することで関連するパッケージを関数とは別でアップロード・使用することが可能です。
serverlessというLambdaにアップロードするための便利なツールがlayerにも対応しています。

ちなみに、serverlessでアップロードする際に、素直にserverless deployをすると毎回layerもアップロードされるのであまりよろしくないです。


$ serverless deploy function -f [関数名]

と実行すると、該当の関数だけアップロードされます。

puppeteerが動かない

様々な記事を参考にさせていただいたのですが、バージョンの相性のせいなのか、うまくheadless chromeが起動せずうまく動きませんでした。

https://github.com/RafalWilinski/serverless-puppeteer-layers
試行錯誤を重ね、遂に、↑を参考に構築したところ、無事クローラーが動きました。

だが、しかし、、、

ゾンビプロセスが溜まりクラッシュする

数回の実行ではまったく問題なかったのですが、短い時間に連続で何度も実行するとクラッシュしてしまう。。
メモリを観察すると、実行毎にメモリが圧迫されていたことがわかりました。そして限度を超えるとクラッシュする。

そこでプロセスを出力してみると、ゾンビプロセス(メモリ0のプロセス)が実行の度に溜まっていることがわかりました。

USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
486 989 0.0 0.0 0 0 ? Z 07:56 0:00 [headless_shell] <defunct>
486 937 0.0 0.0 0 0 ? Z 07:50 0:00 [headless_shell] <defunct>
486 888 0.0 0.0 0 0 ? Z 07:50 0:00 [headless_shell] <defunct>
486 840 0.0 0.0 0 0 ? Z 07:50 0:00 [headless_shell] <defunct>
486 793 0.0 0.0 0 0 ? Z 07:50 0:00 [headless_shell] <defunct>
486 748 0.0 0.0 0 0 ? Z 07:49 0:00 [headless_shell] <defunct>
486 694 0.0 0.0 0 0 ? Z 07:49 0:00 [headless_shell] <defunct>
486 645 0.0 0.0 0 0 ? Z 07:49 0:00 [headless_shell] <defunct>
486 62 0.0 0.0 0 0 ? Z 07:45 0:00 [headless_shell] <defunct>
486 596 0.0 0.0 0 0 ? Z 07:49 0:00 [headless_shell] <defunct>
486 548 0.0 0.0 0 0 ? Z 07:49 0:00 [headless_shell] <defunct>
486 500 0.0 0.0 0 0 ? Z 07:48 0:00 [headless_shell] <defunct>
486 451 0.0 0.0 0 0 ? Z 07:48 0:00 [headless_shell] <defunct>

※「あれ?Lambdaってサーバレスだから毎回プロセスを破棄するんじゃないの?」と思ってましたが、そんなことはないようです。
https://qiita.com/koshigoe/items/afa3368352020660a220

ここからスーパー試行錯誤しました。
一定時間待ったり、クローラ実行用のchild processを作ってchild process毎killしたり、あらゆる手でプロセスの終了を試みました。

が、解決しなかった

※該当のissueも存在します。執筆時点でまだopenになっている。
https://github.com/GoogleChrome/puppeteer/issues/1825

バージョンのせいなのか、人によってkillするだけで上手くいったと報告してる人もいるのが難しいところでした。
私の場合は、puppeteer.launch時点で孤立したゾンビプロセスが生成され、消せなかった。。
ライブラリ依存の問題であろうことはわかってたので、Lambdaを辞めるという選択肢も含めて諦めかけていました。
もういっそこの際レポジトリにコントリビュートしてやろうかなと思っていたところ、意外な形で解決しました。

headless chromeの新バージョンが出た

https://github.com/alixaxel/chrome-aws-lambda
最新のheadless chromeに追従してくれるこのライブラリをベースにlaunch部分を書き直したら動きました。

今回のトラブルを活かして↑のレポジトリをlayerにしてserverlessで使えるようにテンプレート化したレポジトリを公開しています。
https://github.com/inatomitk/lambda-puppeteer-template

結論

バージョンアップは偉大

5
3
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
5
3