匿名迷子札チャットシステムをゼロから設計した話① 〜 WebSocketで直見えてきた課題 〜

Relink投稿

Re:Link迷子札では、飼い主と保護者をつなぐ連絡手段として、独自のチャットシステムを開発することを採用しました。

開発テーマ

メールや電話番号、SNSなど既存の連絡手段を利用する方法も検討しましたが、最終的にはリアルタイムな双方向通信を実現するチャットシステムを自社で設計・開発することを選択しました。

その理由は、迷子札というサービスの性質上と弊社の今後の思いを実現するため、次の要件を特に重要視したためです。

  • 飼い主・保護者双方の匿名性を担保できること
  • リアルタイムにやり取りできること
  • 会員登録やアプリのインストールを必要とせず、すぐに利用できること
  • 将来的な利用者増加にも対応できるスケーラブルな構成であること
  • 飼い主と発見者だけでなく、必要に応じて第三者が介入できること(地域ボランティアや自治体、AIによる支援など)

その背景には、開発において「発見者の心理的ハードルを下げること」を大きなテーマとしているからです。

ここからは技術的な話です。

通信手段の選択

リアルタイム性・匿名性・第三者介入の実現において、WebSocketを使用することにしました。

通信手段比較内容備考
ポーリング定期的にメッセージの受信確認を行う手段。
リアルタイム性を担保しようとすると、通信頻度と通信量が増える懸念がある。
SSE一方通行の通信のため、そもそもチャットには不向き。
Push通知Push通知受信後、メッセージ取得の手段もあるが、安定動作にはアプリ化必要。PWAでの通知は不安定になる
WebSocketリアルタイムな双方向、同時複数通信が可能である。開発コストは他に比べて高いが、要件を満たすためにも必要と判断。

WebSocketによる双方向通信

WebSocketは、アプリケーション層で利用される通信プロトコルの一つです。HTTPと同じくTCP上で動作するプロトコルですが、HTTPとは通信の仕組みが大きく異なります。

HTTPでは、クライアントがリクエストを送信し、サーバーがレスポンスを返すことで1回の通信が完結します。そのため、新しいデータを取得するたびに、新たなHTTPリクエストを送信する必要があります。

一方、WebSocketでは、一度接続を確立すると、その接続を維持したままサーバーとクライアントが双方向にデータを送受信できます。これにより、リアルタイム性が求められるチャットなどのシステムに適した通信を実現できます。

WebSocket接続が確立されるまでの流れは、次のとおりです。

  • クライアントがHTTPリクエストを送信する(Upgrade: websocket ヘッダーを付与)
  • サーバーが 101 Switching Protocols を返し、WebSocketへの切り替えを許可する
  • 以降はHTTP通信を終了し、WebSocketプロトコルによる双方向通信を開始する

WebSocketの課題

強制的な切断

WebSocketは、一度接続するとサーバーとの接続を維持し続けることで、リアルタイムな双方向通信を実現します。

しかし、ブラウザでは常にこの接続が維持されるとは限りません。特にiPhoneやiPadのSafariでは、バックグラウンドへの移行や省電力制御、メモリ管理などにより、WebSocket接続が切断されることがあります。

これはWebSocket自体の問題ではなく、モバイルブラウザがバッテリー消費やリソース使用量を抑えるための仕様です。そのため、WebSocketを利用する場合は、接続が切断されることを前提とした設計が必要になります。

Re:Linkでは、このような環境でも利用者が接続の切断を意識することなく利用できるよう、バックグラウンド・フォアグラウンドの状態遷移を考慮した自動再接続機能や、接続状態の復元処理を実装しています。

これにより、OSやブラウザの制御によって接続が切断された場合でも、可能な限りシームレスに通信を再開し、利用者がストレスなくメッセージをやり取りできるよう設計しています。

メッセージ受信処理の軽量化

WebSocketサーバーには、メッセージの送受信をできるだけ高速かつ安定して処理する役割を担わせています。そのため、受信したメッセージに対して時間のかかる処理を同じプロセス内で実行すると、レスポンスの遅延や同時接続数の低下を招く可能性があります。

そこで、WebSocketサーバーではメッセージの受信・配信に専念し、それ以外の処理は非同期で実行する設計としました。

例えば、以下のような処理はメッセージ配信とは切り離し、キューを介してバックグラウンドで処理します。

  • 新着メッセージの通知メール送信
  • OGP情報の取得
  • 画像データの妥当性確認
  • サムネイル画像の生成
  • その他、時間を要する処理

このように役割を分離することで、WebSocketサーバーは常に軽量な状態を維持でき、リアルタイム性を損なうことなく安定したメッセージ配信を実現しています。

チャットルームの管理

WebSocketは、サーバーとクライアント間でリアルタイムな双方向通信を実現するためのプロトコルです。しかし、「誰と誰が会話するのか」「どのメッセージを誰に届けるのか」といったチャットルームの管理までは行ってくれません。

そのため、チャットシステムを構築するには、WebSocketとは別にチャットルームの管理機能を検討する必要があります。

Re:Linkでは、迷子札ごとにチャットルームを作成し、接続している利用者を適切なチャットルームへ紐付けることで、メッセージが関係者以外へ配信されないよう管理しています。

また、将来的なサーバーの水平スケールも考慮し、チャットルーム情報は複数のWebSocketサーバーから共有できる構成としたい。これにより、どのサーバーへ接続した利用者同士でも、同じチャットルームでリアルタイムにメッセージをやり取りできるよう設計しています。

そこで、サーバ間で情報共有できるキャッシュを使用します。キャッシュの設計に関しては、別途記事にまとめたいと思います。

まとめ

WebSocketは、リアルタイムな双方向通信を実現するための優れた技術です。しかし、実際にサービスとして提供するためには、単にWebSocketを導入するだけでは十分ではありません。

接続の維持や再接続、チャットルームの管理、メッセージ配信、サーバー負荷の分散など、利用者には見えない部分にこそ多くの設計上の工夫が求められます。

Re:Linkでは、「発見者の心理的ハードルを下げること」を開発のテーマとし、利用者が技術を意識することなく、安心して連絡を取れる体験を目指して設計・開発を進めてきました。

私たちが目指しているのは、高性能なチャットシステムを作ることではありません。

「迷子のペットを見つけた。その瞬間に、迷わず行動できる仕組みを作ること。」

そのために、リアルタイム通信や匿名性、スケーラビリティといった技術を一つひとつ積み重ねています。

技術は目的ではなく、課題を解決するための手段です。

これからもL’s Craftsmanは、「テクノロジーを優しさに換える」という理念のもと、社会課題の解決につながるシステムづくりに挑戦していきます。

タイトルとURLをコピーしました