当社の API は、100 万人のユーザーをサポートするために開発されました。4 か月以内に 50 万人に達したため、現在、1 年以内に到達する予定の 1,000 万人のユーザーをサポートできるように拡張中です。現在、コア データ処理/集計ロジックを SDK として他のアプリに出荷しているため、目標は現実的です。
現在の API は、ボディが JSON である HTTP ポストです。新しいユーザーが登録すると、デバイスから約 200KB のデータがアップロードされます。以前はデータ サーバー側で処理していましたが、現在はデバイス自体で処理しています。
その後、アプリは 1 日あたり約 2KB のデータをアップロードし、ほぼ同じ量をダウンロードします。複数のモバイル デバイスを使用するユーザーの場合、この数はもう少し多くなりますが、これはユーザー ベース全体の 1% にすぎません。
現在、API サーバーは Jetty+Jersey を使用しており、平均で約 200 の同時接続があります。約 500 ~ 1000 の同時接続を処理できます (要求の種類によって異なります)。
各 API サーバー (合計 4) には 120 のデータベース接続があります。ワークロードは書き込み 80%、読み取り 20% で、更新はほとんどありません。
現在、API は同期的です。つまり、リクエストごとにデータを保存/取得し、ack/data をクライアントに送り返します。
スケーリングする 1 つの方法は、API サーバーを (垂直方向および/または水平方向に) スケーリングし、userId でデータベースを分割することです。データベースのシャーディングが行われるのは、100 万ユーザーごとに 1 TB のデータ ストレージが必要であることを見積もったためです。SSDへの移行も予定していますが、自社のデータセンターがあり、移行が進行中であるため、しばらく時間がかかります。
私が予見する主な課題は、SDK が人気のあるアプリに展開される際の新規ユーザーの急増を処理することです。私が検討しているいくつかのアプローチがあります:
1) 書き込みリクエスト中にエンティティを抽出し、KAFKA にプッシュしてクライアントに ACK を送信します。コンシューマーはエンティティを抽出してキューから保持し、それらをバッチに挿入します。
2) 読み取りと書き込みの異なるサーバーを使用します。読み取りには、既存の同期アーキテクチャを使用します。書き込みリクエストの場合、エンティティを抽出して保持し、それらをメモリ内キューにプッシュする Netty によってサポートされる別の URL を公開し、クライアントに ACK を送信します。kafka キューに非同期で転送し、最終的にデータベースに転送します。
3) 要求ごとに非同期サーバーの Quasar+Comsat および軽量スレッドを使用し、クライアントに ack を待機させます (永続化されたエンティティの自動インクリメント ID も取得します)。問題は、DB 接続の数がボトルネックであることです。多数の同時軽量スレッドを生成しても、実際には役に立たない可能性があります。
これらのアプローチの長所/短所/改善点を指摘したり、新しいアプローチを提案したりすることは、非常に役立ちます。10M から 100M にスケーリングしたとしても、これらのアプローチのどれが当てはまるかという観点も役立ちます。私たちはウェブインターフェースを持っていないので、すべてのデータ転送は純粋にjsonです.発展途上国では、2Gのデバイスと多くのネットワーク切断をサポートする必要があるため、これも考慮する必要があります.