【開発コラム】第1回「メール通知の遅延を解消したお話」
開発コラム

【開発コラム】第1回「メール通知の遅延を解消したお話」

はじめに

いつもFantiaをご利用いただきありがとうございます。

Fantia開発のメインメンバーのJUNE-JUNEと申します。

Fantiaの開発に加わってちょうど1年あまりが経過しました。

 

※社員紹介のページは以下になります

https://yumenosora.co.jp/tora-lab/character

Fantiaを日頃ご利用いただいている皆さんにとって、

『Fantiaの開発が一体何をやっているのか』、『どのようにして問題解決を行なっているのか』、

と疑問に思うことも少なくないでしょう。

 

そこで、今後私の方からこれまでFantiaで行なった新規機能の開発や問題解消における詳細を伝えていく技術コラムを書いていく予定です。

そして、当サービスに興味を持った方、また現在抱えている問題などを直そうと思ったエンジニアの方は是非弊社の採用にエントリーしていただければと思います。

また、エンジニアでない方も周りで「この人にFantiaをもっと良くしてもらいたい!」というエンジニアの方がいらっしゃいましたら、ぜひご紹介ください。

 

※Fantiaエンジニアの採用情報はこちら
Fantiaエンジニア採用情報

まずは第1回として、大規模サービスならお馴染みの問題である「通知処理」にまつわる問題と、その解決法をお話します。

メール遅延問題の原因と解決法

Fantiaにおけるメール通知の発火タイミングは数多くあります。

例えば『新しい投稿』をしたときが1つのタイミングです。

ご存知の『●●に新しい投稿「■■■」が投稿されました』という通知は、加入しているファン全員に送られています。

これに加え、メール受信を「ON」にしている方にはメールも送信されます。

 

クリエイターの投稿の処理とは非同期で実施しなくてはなりません。そうでないと、投稿処理の時間が増え続けてしまい、ユーザビリティが大きく損なわれてしまいます。

そこで、Fantiaはサービス開始当初からdelayed_jobというRailsの遅延処理を実行するGemライブラリを使っていました。

 

●delayed_jobのGithub

https://github.com/collectiveidea/delayed_job

使い方はとても簡単で、私が入った当初は問題なく動いていたのですが、今年の3月ごろから明らかな問題が現れ始めました。

 

それは、delayed_jobが即座に通知を処理しきれず、通知が届くのが全体的に遅れてしまうという事態です。

特に4月ごろはその障害が顕著で、当時ご利用されたお客様には大変ご迷惑をおかけしました。

 

他の開発を行なっていてなかなか着手できなかったのですが、流石に看過できないと判断し、今年の4月ごろに本格的な問題解決にあたりました。

 

調査の結果、この遅延における原因の仕組みはいたって単純でした。

以下の図の様に、delayed_jobを用いた通知処理は、タスクをキューに追加しておいて後から実行する「遅延実行」で実施されています。

それ自体は問題ないのですが、通知処理から発生するメール送信も、メール一件を1タスクとする「遅延実行」で行われていたのです。

これにより、ファンの人数が多いと一回の投稿で大量のタスクが一気に積まれてしまいます。

サービスの規模が大きくなる度に、この積まれるタスクの数は乗算的に増えてゆき、delayed_jobの処理を行うサーバーの処理の限界を簡単に突破してしまうのです。

 

これに対する解決方法はいくつか考えられます。

1つ目は「delayed_job」の処理を行うサーバーを増やすこと。

2つ目は「sidekiq」などの別の類似ライブラリを使い、改善を測ること。

3つ目は処理のサーバーレス化を行い、処理の増減に対応させること。

4つ目は「delayed_job」で積まれるタスクの数を減らすことです。

 

私は4つ目のタスクの数を減らす方針にしようと決めました。

なぜかというと、このタスクの量というのは無限に増え続けていくからです。

これは根本的な解決を計らない限り、代替ライブラリでも同様の問題が発生する可能性が高く、サーバーを増やしても維持費が増え続けてしまうことになります。

 

そして、以下の図の様な仕組みに変更しました。

こうすることで、従来は積まれるタスクが「1投稿にあたり1+メール送信分」でしたが、新方式では「1投稿あたり1つ」となります。

加えて、メールの送信処理も1件1件実行していたものを、一括処理に置き換えて速度向上を図りました。

 

Fantiaではメールの送信を「Sendgrid」で行なっています。

 

●Sendgrid

https://sendgrid.kke.co.jp/

Sendgridは海外の高速メール配信を可能にするクラウドメール配信サービスです。

それまではSMTP型という方法でメールを一通ずつ送っていたのですが、一括送信を行うためにAPIでの送信を実装しました。

この一括送信APIの実装が一癖ありまして、実装例のサンプルが公式のページを見てもなかなか見つかりませんでした。

 

一回のAPIで個別のメールアドレスを設定する必要があるため、personalizationというオブジェクトを設定しなければいけないのですが、この設定方法がなかなか出てきません。

ようやく見つけた実例はGithubにある公式のサンプルプログラムです。

公式サイトのマニュアルではなく、Githubの中に適切な実例が書かれていました。

https://github.com/sendgrid/sendgrid-ruby/blob/master/examples/helpers/mail/example.rb

これを参考にメール送信も一括送信することができ、通知処理の全体的な速度向上を実現しました。

そしてリリース後、お客様に遅延なく通知を届けることができるようになったのです。

 

商品紹介

このようなFantiaの内部における問題に関して、

2019年春に発行した虎の穴ラボの薄い本。vol.2でも記載しておりますので、

興味のある方は是非ご購入ください。

https://fantia.jp/products/36739

素材紹介

図で度々使われている女の子の素材は弊社の公式サイト「とらラボ」で無料配布されています。

スライド等のプレゼン資料や技術書の作成など、商用問わず全て無料で使えるので、ご覧ください。

https://yumenosora.co.jp/tora-lab/special

 

あとがき

サービス規模が大きくなるとこの様な問題が発生してゆくのは避けられず、

我々エンジニアは「新規機能の開発」と「品質向上開発」を同時に行なっていかなければいけません。

 

現在Fantiaはサービスに規模に対しての開発エンジニアは人手が不足しており、積極的にエンジニアを募集しています。

繰り返しとなりますが、「Fantiaを一緒に改善したい!」と思うエンジニアの方はぜひご応募ください。

※Fantiaエンジニアの採用情報はこちら
Fantiaエンジニア採用情報