$30 off During Our Annual Pro Sale. View Details »

新メール配信基盤への移行 /ikyu-mail-platform

新メール配信基盤への移行 /ikyu-mail-platform

一休✕bitFlyer C#をつかったサービス開発の裏側
https://ikyu.connpass.com/event/35161/

minato128

June 28, 2017
Tweet

More Decks by minato128

Other Decks in Technology

Transcript

  1. 新メール配信基盤への移行
    株式会社一休
    宿泊事業本部 開発部
    飯迫 正貴
    2017/06/28 【一休 × bitFlyer】C#を使ったサービス開発の裏側

    View Slide

  2. 今日お話すること

    View Slide

  3. 今日お話すること
    • 背景
    • 新メール配信基盤の概要
    • どう移行したか
    • 運用開始後にわかったこと
    • (全体を通して)意識したこと

    View Slide

  4. 背景

    View Slide

  5. 背景
    • すべてのサービスをオンプレからクラウドへ移行中
    • トランザクションメールが対象
    • 既存の各サービスからのメール
    • SMTPでオンプレの共通メールサーバーから送信していた
    • マーケティングメールは対象外
    • メルマガ

    View Slide

  6. 要件整理・課題
    • サービス側がクラウドに移行するまでにメールもクラウドに
    • もちろんそうですね
    • ユーザーからの問い合わせに対応するためのログが必要
    • CSチームで送達確認や本文の確認をしている
    • 既存の仕組みだと検索が面倒で時間がかかっている
    • メール送信処理が同期処理になっていて遅い
    • 非同期にしたい
    • 今となってはメールである必要のないものがある
    • システムチーム宛のものなど
    • SaaS になると送信量で課金額が決まる

    View Slide

  7. どうしたか
    • 新メール配信基盤は最初から全部クラウドで構築
    • Mail SaaS は SendGrid に
    • SMTPをとりあえず生き残らせるとかはやらない
    • 暫定対応なしで一気に最終形へ
    • メールの送信ログは DynamoDB へ
    • 権限がある人には簡単に参照できる検索画面を用意
    • メール送信リクエストは Message Queue で非同期に
    • 送る側は SQS に Queue を入れるだけ
    • メールでなくていいものは新基盤には移行しない
    • 代替として Log SaaS へ流す
    • 必要に応じて Log SaaS から Slack へ通知する

    View Slide

  8. 新メール配信基盤の概要

    View Slide

  9. アーキテクチャ
    • メール送信

    View Slide

  10. アーキテクチャ
    • Webhook 受信

    View Slide

  11. 使い方

    View Slide

  12. メール送信履歴検索
    • CSチームでユーザーから問い合わせがきたときに利用
    • 送達確認
    • 内容(本文)確認
    • バウンスリストからの削除

    View Slide

  13. メール送信履歴検索(Before)
    面倒…

    View Slide

  14. メール送信履歴検索(After)
    権限のある人は即検索可能に!

    View Slide

  15. アーキテクチャ
    • メール送信履歴検索

    View Slide

  16. 実装 / インフラ
    • メール送信
    • ASP.NET Core / .NET Core /C#
    • AWS Elastic Beanstalk
    • 64bit Amazon Linux running Docker
    • Webhook 受信
    • .NET Core / C#
    • AWS Lambda
    • メール送信履歴検索
    • ASP.NET Core / .NET Core / C#
    • Windows Server
    • 諸事情あってまだオンプレ

    View Slide

  17. CI / CD
    • Staging
    • GitHub master merge => Circle CI => AWS EB or Lambda
    • Production
    • GitHub release merge => Circle CI => AWS EB or Lambda

    View Slide

  18. CI / CD

    View Slide

  19. どう移行したか

    View Slide

  20. 移行方針
    • 送信量の少ないサービスから移行
    • AWS 側のリソース調整
    • IP ウォームアップ
    • 詳しくはこちら => https://sendgrid.kke.co.jp/blog/?p=326
    • 送信量の少ないサービスは一括移行
    • 送信量の多いサービスは徐々に移行
    • メールを送る必要がないものやめる
    • 代替を用意
    • 添付ファイルをやめる
    • もちろん SendGrid API は対応している
    • が、DynamoDB には JSON を保存するだけにしたい

    View Slide

  21. 移行順序 / 送信量 / 言語
    • 一休.com海外
    • 送信量 小
    • ASP.NET MVC / C#
    • 一休.comギフト
    • 送信量 小
    • Classic ASP
    • 会員基盤や内部向けAPI
    • 送信量 中
    • ASP.NET MVC / C#
    • 一休.com(宿泊予約)
    • 送信量 大
    • ASP.NET Web Forms /
    VB + C#
    • 一休.comスパ
    • 送信量 小
    • PHP
    • 一休.comレストラン
    • 送信量 大
    • Classic ASP
    スパまで完了

    View Slide

  22. 移行方法 (C# or VB)
    • 共通メール送信用ライブラリ
    • 現行と同様のインターフェースで別の namespace に新 API を追加
    • 旧 API は Obsolete
    • 部分的な移行もできるように
    • AppVeyor NuGet で管理
    • ライブラリを利用しているサービス
    • namespace 変更のみで移行完了
    • プルリクのレビューが楽
    • ライブラリを利用していないサービス
    • 同じ方針で実装

    View Slide

  23. 移行方法 (C# or VB)

    View Slide

  24. 移行方法 (C# or VB)

    View Slide

  25. 移行方法 (Classic ASP)
    • namespace 戦法が使えない
    • 共通の送信ロジックを変更して一括移行(ギフト・スパ)
    • もしくは、地道に新APIに移行(レストラン)
    • AWS SDK ない問題
    • AWS API Gateway + Lambda で対応(ギフト・スパ)
    • Lambda から SQS に Enqueue
    • COMで対応?(レストラン)
    • レストランはこれから

    View Slide

  26. 部分移行
    • 特に予約完了メールは送信量が多い
    • かつ重要度が高い
    • 1%, 10%, 50%, 100% と徐々に新APIへ移行
    • テストはしているが、完璧ではない可能性がある
    • もし失敗しても 1% リカバリーするほうが比較的楽

    View Slide

  27. 部分移行

    View Slide

  28. メールの代替を用意(Before)
    • バッチ処理結果や特定の例外をメールで送っていた
    • システムチーム宛
    • サービス開始当時はそれしかなかった
    • メールを GAS で振り分けて Slack にアラートを上げていた
    • アラートの条件変更がメンテしづらい

    View Slide

  29. メールの代替を用意(Before)
    • 例外メールによる全体の配信遅延
    • たまにアプリのバグで例外メールが飛び続けていた

    View Slide

  30. メールの代替を用意(After)
    • Log SaaS (Logentries) へ流すようにした
    • 同時に構造化ログに
    • フィルターや集計がしやすく
    • Logentries 側からアラートを設定
    • 条件変更は誰でも簡単にできる
    • ただデフォルトの Slack 通知機能は微妙
    • Raw log が出るだけでカスタマイズもできない
    • Azure Functions で Webhook を受け取って Slack に通知
    • 最初は csx で作ったが、あとで Precompiled Function に変更
    • チームで管理するのでちゃんと CI/CD をやりたかった
    • csx は CD 設定簡単だけどコンパイルエラーだと死ぬ
    • CI/CD
    • GitHub => AppVeyor => MS Azure

    View Slide

  31. メールの代替を用意(After)
    バッチ処理結果ログ / Slack アラート

    View Slide

  32. 添付ファイルをやめる
    • バッチ処理でメールにファイルを添付していた
    • 提携企業や経理あて
    • S3 への保存に変更
    • ダウンロード用の Pre-signed URL を本文に記載

    View Slide

  33. 添付ファイルをやめる(Before)
    経理あてのメール

    View Slide

  34. 添付ファイルをやめる(After)
    経理あてのメール

    View Slide

  35. ドメインホワイトリスト
    • 移行前
    • 開発環境からメールは送れなかった
    • 確認方法はあった
    • 移行後
    • 開発環境からもStagingの新メール配信基盤を使うようにした
    • 開発用実装を持ちたくなかった
    • 環境依存バグの温床
    • とはいえ、誤送信は困る
    • Config に宛先ドメインのホワイトリストを追加
    • Staging はこの設定により特定のドメインにしか実際に送信されない

    View Slide

  36. ドメインホワイトリスト

    View Slide

  37. 運用開始後にわかったこと

    View Slide

  38. docomo/au のバウンス率が高い
    • docomo/au 限定で5回までは自動的にバウンスリストから削
    除する仕組みを追加
    詳しくはこちらで!
    https://docs.com/shibayan/6046/sendgrid-c-v3-api

    View Slide

  39. yahoo.co.jp のバウンス率が高い
    • Yahoo!ログインに対応したためYahoo!ユーザーが増えた
    • Yahoo!メールは一定期間が使わないとメールボックスが
    Suspendされる仕様
    • 使ってないけど通知先に設定されたままのユーザーが多い?

    View Slide

  40. 速い
    • アプリ側は Enqueue するだけなので
    • あるバッチの例
    • ユーザーに一括でメール送信している系のバッチ

    View Slide

  41. DynamoDB
    • Write / Read Capacity の調整がちょっと面倒
    • provisioned throughput 課金
    • 読み書きの性能を予約しておくスタイル
    • 超過すると例外が発生
    • ProvisionedThroughputExceededException
    • 札束で殴ることもできるが…
    • 特にバッチ処理で一気に Enqueue されると厳しい
    • Elastic Beanstalk の設定で同時実行数(並列度)を微調整
    • Worker Configuration => HTTP connections

    View Slide

  42. Before

    View Slide

  43. After

    View Slide

  44. DynamoDB
    • Auto Scaling 機能が今月リリースされた
    • まだ試してない
    • 使用量に応じて自動的に Capacity を変更してくれる
    • ただし反映に時間がかかる
    • Write スパイクに有効な機能ではない

    View Slide

  45. その他
    • 一部の IP が Office 365 の Blacklist 入りしていた
    • いきなりたくさん送るとなりやすいらしい
    • 気をつけていたのに
    • https://sender.office.com/ から解除
    • CS側でバウンスリストからの削除ができないと運用が回らない
    • メール送信履歴検索画面に削除機能を追加

    View Slide

  46. SendGrid / KKE がよい

    View Slide

  47. SendGrid / KKE がよい
    • SendGrid の採用が決まってからエヴァンジェリストの方にす
    ぐ来てもらえた
    • その後も何度もアドバイスをもらった
    • KKEさんはノウハウや事例をたくさん持っている
    • 安心・感謝
    • しっかりしたドキュメントがある
    • 公式ライブラリが使いやすくなった

    View Slide

  48. 今後の対応
    • ブロック検知
    • メールの HTML 化と開封率の取得
    • まだ一部のメールしか HTML 対応していない
    • プレーンテキストの見た目のまま無理やり HTML にすることは可能だ
    が、怪しまれて逆に開封率が下がるらしい
    • ちゃんと文面を HTML 対応する必要がある

    View Slide

  49. 意識したこと

    View Slide

  50. 意識したこと
    • 要件 / 課題整理
    • どんな課題を解決するのか明確にする
    • オンプレからクラウドにしてスケールしやすく
    • 同期処理から非同期処理にして高速化
    • メールログを参照を簡単にしてCSチームの手間を削減
    • やらないことを明確にする
    • 暫定アーキテクチャは作らない
    • 要らなくなったメールは移行しない
    • 設計 / 構築
    • とにかくシンプルにして、本当に必要なものだけ作る
    • C# で統一して生産性と安定性をとる
    • SaaS特性、クラウド特性を理解する
    • なるべくSaaSに委譲してエンジニアの関心事や手間を減らす
    • 移行作業
    • 移行は必要最低限の変更だけやる
    • 改善の方にリソースを割く

    View Slide