SendGridのWebhookを受けるのにFluentdが重宝した話

SendGridのWebhookについて

SendGrid の Event Webhook は、SendGrid経由でメールを送信する際に発生するイベントを、指定したURLにPOSTすることができます。 このデータの用途は、配信停止アドレスの削除、迷惑メール報告への対応、エンゲージできなかった受信アドレスの判定、バウンスされたメールアドレスの特定、メールプログラムの高度な分析などです。ユニーク引数やカテゴリパラメータを使用して、動的なデータを挿入することができるため、あなたのメールのシャープでクリアなイメージを構築するのに役立ちます。

ということなんだけど、 1度に送信件数が5000件以上だったりするとそれなりにOpenや送信したというイベントが飛んで来るので、 このWebhookをどうさばくかというのがちょっとした課題になる。 多分BigQueryに送信するだけであればGCPのLambda相当のサービスを利用すればOKな気がする。 というかGCPがサンプル乗っけてるので、コレはコレで便利なのでぜひ見て欲しい。

SendGrid Tutorial  |  Cloud Functions Documentation  |  Google Cloud

Webhookを受けて、レスポンス内容をMongoに格納する例

今回はFluentdのデフォルトに同梱されているHTTP Input Pluginを利用して、Webhookを受けて、Mongoに送信する方式を取った。 Webhookを受けるだけのなにかアプリケーションを作る必要あったのかと思ったけど、Fluentdでシンプルに解決できる方法があってよかった。

Fluentdのプラグインとして追加が必要なのは、fluent-plugin-mongo くらい。

そのためのfluentd.confをココにおいておく。

<source>
  @type forward
</source>

<source>
  @type http
  port 8080
</source>

<filter **>
  @type stdout
</filter>

<match sendgrid.**>
  @type mongo

   database "#{ENV['DB_NAME']}"
   host "#{ENV['DB_HOST']}"
   port "#{ENV['DB_PORT']}"

   collection "#{ENV['DB_COLLECTION']}"

   user "#{ENV['DB_USER']}"
   password "#{ENV['DB_PASSWORD']}"

   capped
   capped_size 100m

   ssl true
</match>

これでFluentdを再起動し、SendGrid上でport:8080を接続先に設定すればOK。

そもそもBigQueryやTresureDataではなく、 Mongoに送っている理由としては、短い保持期間であればMongoの方が短い時間で結果が返ってくるのかなということでそうしている。 この場合たくさんデータがあふれてくると結局処理時間が長くなるのでは??? という懸念があるので、格納するデータの保持期間については別途検討する必要がありそう。

保持期間を設定してそれまでは保存しておき、古いドキュメントを自動で削除するみたいなのが、 少し簡単にできるかも。今後はコレを参考にして検証する予定である。 qiita.com

サンプルはMongoに送信しているだけだけど、TresureDataやBigQuery、はたまたフォーマッティングして、 S3にもOutputするようにすれば良いんじゃないですかねという感じ。

余談だけど、どこでも動かせるようにということでDockerイメージに固めている。 Azureを利用しているのでWeb App for Containersで動かしている感じ。 多分AWSではECSでも良いだろうし、きっともっと面倒ならElasticBeanstalkでも良いと思う。

Webhookを受けるのにも便利なFluentd

Fluentdはバッファリングしてくれる機構を持っているし、こういったものを自前で実装するよりも信頼性は高い。 Webhook受けて何処かに書き込むような簡単な処理だけなら、わざわざRailsアプリケーションを立てる必要はなくFluentdで十分だと思っている。*1

*1:ロスト確率と、対応時間のコストの兼ね合い考えると、少し重複する分に問題ないなら良い選択と思っている。