一休✕bitFlyer C#をつかったサービス開発の裏側 https://ikyu.connpass.com/event/35161/
新メール配信基盤への移行株式会社一休宿泊事業本部 開発部飯迫 正貴2017/06/28 【一休 × bitFlyer】C#を使ったサービス開発の裏側
View Slide
今日お話すること
今日お話すること• 背景• 新メール配信基盤の概要• どう移行したか• 運用開始後にわかったこと• (全体を通して)意識したこと
背景
背景• すべてのサービスをオンプレからクラウドへ移行中• トランザクションメールが対象• 既存の各サービスからのメール• SMTPでオンプレの共通メールサーバーから送信していた• マーケティングメールは対象外• メルマガ
要件整理・課題• サービス側がクラウドに移行するまでにメールもクラウドに• もちろんそうですね• ユーザーからの問い合わせに対応するためのログが必要• CSチームで送達確認や本文の確認をしている• 既存の仕組みだと検索が面倒で時間がかかっている• メール送信処理が同期処理になっていて遅い• 非同期にしたい• 今となってはメールである必要のないものがある• システムチーム宛のものなど• SaaS になると送信量で課金額が決まる
どうしたか• 新メール配信基盤は最初から全部クラウドで構築• Mail SaaS は SendGrid に• SMTPをとりあえず生き残らせるとかはやらない• 暫定対応なしで一気に最終形へ• メールの送信ログは DynamoDB へ• 権限がある人には簡単に参照できる検索画面を用意• メール送信リクエストは Message Queue で非同期に• 送る側は SQS に Queue を入れるだけ• メールでなくていいものは新基盤には移行しない• 代替として Log SaaS へ流す• 必要に応じて Log SaaS から Slack へ通知する
新メール配信基盤の概要
アーキテクチャ• メール送信
アーキテクチャ• Webhook 受信
使い方
メール送信履歴検索• CSチームでユーザーから問い合わせがきたときに利用• 送達確認• 内容(本文)確認• バウンスリストからの削除
メール送信履歴検索(Before)面倒…
メール送信履歴検索(After)権限のある人は即検索可能に!
アーキテクチャ• メール送信履歴検索
実装 / インフラ• メール送信• 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• 諸事情あってまだオンプレ
CI / CD• Staging• GitHub master merge => Circle CI => AWS EB or Lambda• Production• GitHub release merge => Circle CI => AWS EB or Lambda
CI / CD
どう移行したか
移行方針• 送信量の少ないサービスから移行• AWS 側のリソース調整• IP ウォームアップ• 詳しくはこちら => https://sendgrid.kke.co.jp/blog/?p=326• 送信量の少ないサービスは一括移行• 送信量の多いサービスは徐々に移行• メールを送る必要がないものやめる• 代替を用意• 添付ファイルをやめる• もちろん SendGrid API は対応している• が、DynamoDB には JSON を保存するだけにしたい
移行順序 / 送信量 / 言語• 一休.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スパまで完了
移行方法 (C# or VB)• 共通メール送信用ライブラリ• 現行と同様のインターフェースで別の namespace に新 API を追加• 旧 API は Obsolete• 部分的な移行もできるように• AppVeyor NuGet で管理• ライブラリを利用しているサービス• namespace 変更のみで移行完了• プルリクのレビューが楽• ライブラリを利用していないサービス• 同じ方針で実装
移行方法 (C# or VB)
移行方法 (Classic ASP)• namespace 戦法が使えない• 共通の送信ロジックを変更して一括移行(ギフト・スパ)• もしくは、地道に新APIに移行(レストラン)• AWS SDK ない問題• AWS API Gateway + Lambda で対応(ギフト・スパ)• Lambda から SQS に Enqueue• COMで対応?(レストラン)• レストランはこれから
部分移行• 特に予約完了メールは送信量が多い• かつ重要度が高い• 1%, 10%, 50%, 100% と徐々に新APIへ移行• テストはしているが、完璧ではない可能性がある• もし失敗しても 1% リカバリーするほうが比較的楽
部分移行
メールの代替を用意(Before)• バッチ処理結果や特定の例外をメールで送っていた• システムチーム宛• サービス開始当時はそれしかなかった• メールを GAS で振り分けて Slack にアラートを上げていた• アラートの条件変更がメンテしづらい
メールの代替を用意(Before)• 例外メールによる全体の配信遅延• たまにアプリのバグで例外メールが飛び続けていた
メールの代替を用意(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
メールの代替を用意(After)バッチ処理結果ログ / Slack アラート
添付ファイルをやめる• バッチ処理でメールにファイルを添付していた• 提携企業や経理あて• S3 への保存に変更• ダウンロード用の Pre-signed URL を本文に記載
添付ファイルをやめる(Before)経理あてのメール
添付ファイルをやめる(After)経理あてのメール
ドメインホワイトリスト• 移行前• 開発環境からメールは送れなかった• 確認方法はあった• 移行後• 開発環境からもStagingの新メール配信基盤を使うようにした• 開発用実装を持ちたくなかった• 環境依存バグの温床• とはいえ、誤送信は困る• Config に宛先ドメインのホワイトリストを追加• Staging はこの設定により特定のドメインにしか実際に送信されない
ドメインホワイトリスト
運用開始後にわかったこと
docomo/au のバウンス率が高い• docomo/au 限定で5回までは自動的にバウンスリストから削除する仕組みを追加詳しくはこちらで!https://docs.com/shibayan/6046/sendgrid-c-v3-api
yahoo.co.jp のバウンス率が高い• Yahoo!ログインに対応したためYahoo!ユーザーが増えた• Yahoo!メールは一定期間が使わないとメールボックスがSuspendされる仕様• 使ってないけど通知先に設定されたままのユーザーが多い?
速い• アプリ側は Enqueue するだけなので• あるバッチの例• ユーザーに一括でメール送信している系のバッチ
DynamoDB• Write / Read Capacity の調整がちょっと面倒• provisioned throughput 課金• 読み書きの性能を予約しておくスタイル• 超過すると例外が発生• ProvisionedThroughputExceededException• 札束で殴ることもできるが…• 特にバッチ処理で一気に Enqueue されると厳しい• Elastic Beanstalk の設定で同時実行数(並列度)を微調整• Worker Configuration => HTTP connections
Before
After
DynamoDB• Auto Scaling 機能が今月リリースされた• まだ試してない• 使用量に応じて自動的に Capacity を変更してくれる• ただし反映に時間がかかる• Write スパイクに有効な機能ではない
その他• 一部の IP が Office 365 の Blacklist 入りしていた• いきなりたくさん送るとなりやすいらしい• 気をつけていたのに• https://sender.office.com/ から解除• CS側でバウンスリストからの削除ができないと運用が回らない• メール送信履歴検索画面に削除機能を追加
SendGrid / KKE がよい
SendGrid / KKE がよい• SendGrid の採用が決まってからエヴァンジェリストの方にすぐ来てもらえた• その後も何度もアドバイスをもらった• KKEさんはノウハウや事例をたくさん持っている• 安心・感謝• しっかりしたドキュメントがある• 公式ライブラリが使いやすくなった
今後の対応• ブロック検知• メールの HTML 化と開封率の取得• まだ一部のメールしか HTML 対応していない• プレーンテキストの見た目のまま無理やり HTML にすることは可能だが、怪しまれて逆に開封率が下がるらしい• ちゃんと文面を HTML 対応する必要がある
意識したこと
意識したこと• 要件 / 課題整理• どんな課題を解決するのか明確にする• オンプレからクラウドにしてスケールしやすく• 同期処理から非同期処理にして高速化• メールログを参照を簡単にしてCSチームの手間を削減• やらないことを明確にする• 暫定アーキテクチャは作らない• 要らなくなったメールは移行しない• 設計 / 構築• とにかくシンプルにして、本当に必要なものだけ作る• C# で統一して生産性と安定性をとる• SaaS特性、クラウド特性を理解する• なるべくSaaSに委譲してエンジニアの関心事や手間を減らす• 移行作業• 移行は必要最低限の変更だけやる• 改善の方にリソースを割く