LoginSignup
19
2

More than 5 years have passed since last update.

Sunnychatでのwebsocket利用事例

Last updated at Posted at 2016-12-03

この記事はSupership株式会社 Advent Calendar 2016の3日目の記事になります。

弊社サービス、Sunychatのサーバーサイドを担当している @astapi です。

スクリーンショット 2016-12-03 18.16.44.png

Sunnychatではアプリへの更新通知にwebsocketを使用しています。

この投稿では、下記2つについて書こうと思います。

  • なぜ、websocketを使用しているのか
  • どう実装しているのか

なぜ、websocketを使用しているのか

前提として以下のような背景がありました。

  • ポーリングで5秒ごとに更新を検知するリクエストをアプリから行っていた。
  • ポーリングを脱却し、更新がある時だけ、サーバー側から通知を行う仕組みを作りたかった。

結論を一言でいうと、要件を満たしていて、一番実装がしやすかったからです。

他の候補としては、HTTP/2なのか、MQTTなのかぐらいしか調べてはいなかったのですが、調べたときの感覚は以下です。

  • HTTP/2は調べてる段階では、サーバー側のライブラリが対応されていなかった。
    • ブラウザでのケースはあるが、アプリでのケースがわからなかった。
  • MQTTのウリとしては、QoSだと思っていますが、サービス要件としてそこまでの到達保証が必要なかった。
    • 多少、失敗したとしても他の手段で更新可能
    • websocketに比べて、実装イメージがサーバー、アプリともに薄かった。

websocketに関しては、使える状況ではない。という意見も見たりしますが、
それは、特定状況を含めた話しであり、且つ対象がWebブラウザなので、
アプリを対象にした場合の選択肢としては、アリだと思っています。

websocketがいいと思う理由が以下です。

  • サーバーサイドの実装が楽。
    • これについては後述します。
  • アプリ側のhttpクライアントも対応している。
    • アプリでの利用ならversion差異によって使えないという事を気になくていい。
  • 通信内容はjson(にしている)なので普段使用しているAPIと変わらない感覚。

サンプルだったり、やってみた系の情報はよく見られますが、
実際にproductionで利用しているというケースは、どの選択肢でもあまり聞かないので、実際に実装してみてうまく行くかどうかは、わかんないな。という感じでした。
今考えてみると、アプリ側もクライアントが対応してるしwebsocketいけるよね。って感じで大した検証もせずにサーバーサイドを実装してたので、うまくいってよかったです。

どう実装しているか

言語: Elixir
フレームワーク: Phoenix
の構成で実装しています。

こちらのスライドでも紹介していますが、
Phoenixには、ChannelというPub/Subの仕組みがあり、その内部はwebsocketが使用されています。
Channelを使用して、通知したいユーザーに対して、websocketを通じてpushを行っています。

実装する内容としては、簡単で、
PhoenixではRailsのコントローラーの実装をするように、websocketを扱うことができます。
フレームワーク内部ではwebsocketの通信(json)をデシリアライズし、Elixirで扱うMapに変換してくれます。
その通信内容を元に、コントローラーにディスパッチしてくれて、レスポンスとしてjsonを返せばいいです。

ChannelのバックエンドのPub/Subには、Redisを使用しています。
PhoenixのデフォルトはPG2というErlangのライブラリが利用されていますが、
こちらを利用する場合、ErlangVMのNodeでクラスタを構成しないといけません。
そこの構築の仕組みを作るより、Redisサーバーを挟んだほうが楽だった。
且つ、性能も悪くないためRedisを選択しました。

Phoenixは、単体のサーバーで200万コネクションを実現しています。
ソケットの管理は内部で使用しているCowboyというErlangのサーバーです。
性能的にも、求めているものを充分に満たしています。

なぜ、Elixirなのか

  • すでにサービス内の別の部分でElixirを使っていた。
    • そのため、言語としての導入障壁は低かった。
  • Elixirの軽量プロセスを用いたアクターモデルが、サービスに合っていた。
  • Goは知らなかった。
  • Phoenixでwebsocketを扱うのがすごく簡単だった。
  • Erlangの大規模サービスの実績は多くある。
  • 並列、並行処理が強い言語が来ると思っている。

最後に

Sunnychatでのwebsocketの利用事例を紹介しました。

今回のように技術選択を行うシーンで何を考えて、何故選択したか。を残しておくことは、次の選択で結構約に立つかも。って思いました。
振り返ってみると、「なぜ」が弱いと感じました。
色んな選択肢をしっかりと調べるのは結構大変で、割りと決め打ちでwebsocketを重点的に調べていたので、ひいき的な選択だったかもしれません。
結果的にはうまくいったのでよかったです。

ぜひ、アプリをインストールして、使ってみてください:whale:
iOS
Android

19
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
2