事の始まり

最近、趣味でサイトのスクレイピングとか簡単なものを作ったりしている。
もちろん対象サイトに負荷をかけないようにするのはそうなんだけど、単純にBANされないようにする方法を考えた時に、UserAgentをちゃんと定義したりする以外に、やはりIPアドレスの分散は課題である。
そこで、Lambdaでスクレイピングした場合に、接続元のIPアドレスはどの程度固定になり、どの程度分散されるのか調査してみました。

IPアドレスチェック用のLambda

まず、単純にIPアドレスが返ってくる簡単なLambdaを作成した。
これでCloudWatchLogsにログが記録されるため、IPアドレスがわかるようになる。

import json
import requests
from datetime import datetime, timedelta, timezone


def lambda_handler(event, context):
    res = requests.get('https://ifconfig.me')
    JST = timezone(timedelta(hours=+9), 'JST')
    now = datetime.now(JST)
    time = now.strftime("%Y%m%d %H:%M:%S")

    print(time)
    print(res.text)

調査方法

そもそも、LambdaのIPアドレスは固定じゃないというのはどこかで記事を見かけていて、なんならVPCに配置してEIPつけるみたいな記事を見たことあったため、一旦手動で時間を空けて実行してみた。
その結果、Lambdaの実行時間の最大である15分経過すると、どうやらLambdaが破棄されるのか、IPアドレスが変わるタイミングがわかった。
※二分探索により、最初30分、5分、20分、10分、15分といった感覚でゆっくり漫画見ながら調べた。

あとは、15分おきに実行するようにCloudWatchRuleで設定して約1日実行してみた。

CloudWatch Logsのダウンロード

設置した翌日、下記コマンドでログをダウンロード。

awslogs get /aws/lambda/ifconfig -s '24 hours ago' --profile プロファイル名 > ~/Downloads/awslogs.txt

行のカウント

エディタで適当に不要な行を削除して行をカウント。
4(15min) x 24 = 96IPアドレスなので合っていることを確認。

wc -l ~/Downloads/awslogs.txt
      96 /Users/DAREKAUSER/Downloads/awslogs.txt

ユニークチェック

IPアドレスがユニークであるかチェックTOP10。
※事前にエディタ不要な部分を削除してsortかけて,重複数で降順ソートして、TOP10だけを表示している。

$ cat ~/Downloads/awslogs.txt | uniq -c | sort -k'1' -nr | head
   2 52.194.XXX.XXX
   2 18.179.XXX.XXX
   2 18.177.XXX.XXX
   2 13.231.XXX.XXX
   1 54.92.XX.XXX
   1 54.64.XXX.XXX
   1 54.249.XXX.XXX
   1 54.238.XXX.XXX
   1 54.199.XXX.XXX
   1 54.199.XXX.XXX

上記結果が出た。

結論

やはり15分経過すると、LambdaのグローバルIPはほぼ異なるものが使用されることがわかった。
もしかしたら他の条件もあるかもしれないが、当初想定していた以上に再利用されず、またもしかしたら15分という定期実行だったのタイミングでたまたま再実行されただけで16分だったら再利用されていなかったかもしれない。
いずれにせよ、2回再利用されるくらいなら十分使用できると思う。

インフラを見るものとしては、過剰なスクレイピングは大変嫌なものではあるが、適切な頻度でサーバーに負荷をかけずにサービスを利用してくれる分には問題は無いと思っている。

Lambdaでやる場合も、ゆっくりクロールするように適切に設定すれば、効率よく情報が得られると思うので是非活用していきたい。

※もちろんVPC内の話ではありません

カテゴリー: AWSlambda