31
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

WebSocketが切断された際に、自動的に再接続する方法

Last updated at Posted at 2020-04-17

先日、WEBサイト制作者さん向けのウェブサービスをリリースしたのですが、制作の際に得た知見をシリーズで共有していこうと思います。

WebSocket の自動再接続が行われない

Crew'sHubには、リアルタイムのチャット機能があり、Web Socketを利用しています。
また、データ管理画面でも、プロジェクトメンバーが編集したら即座に更新されるようになっており、やはりここでもWebSocketを利用しています。

開発中に遭遇した問題として、WebSocketが切断された際に、自動再接続がうまく行われないということがありました。

クライアント側では、Reconnecting WebSocketという、WebSocketがクローズされた際に自動的に再接続が行われるモジュールを採用しています。

reconnecting-websocket
https://www.npmjs.com/package/reconnecting-websocket

自動再接続されるはずのモジュールではありますが、ノートPCでスリープから復帰した際など、切断されたままの状態になってしまう不具合が度々発生しました。

そこで、SetTimeoutで定期的にWebSocketのreadyStateを確認して、コネクションが切断されていたら再接続するようにしてみたのですが、それもうまく機能しませんでした。どうもコネクションが切断されているにも関わらず、readyStateにそれが反映しないことがあるようです。

Ping Pong で接続状況を確認する

WebSocket.readyStateが使えないので、実際にサーバと定期的に通信を行って接続状況を確認する方法に切り替えました。

クライアント側はこんな感じです。

let pingPongTimer = null

const ws = new ReconnectingWebSocket(`wss://${process.env.API_HOST}/api/v1/`)

const checkConnection = () => {
  setTimeout(() => {
    ws.send('ping')
    pingPongTimer = setTimeout(() => {
      console.log('再接続を試みます')
      pingPongTimer = null
      ws.reconnect()
    }, 1000)
  }, 30000)
}

ws.onopen = () => {
  checkConnection()
  ...
}

ws.onmessage = ({ data }) => {
  if (data === 'pong') {
    if (pingPongTimer) {
      clearTimeout(pingPongTimer)
    }
    return checkConnection()
  }
  ...
}

以下のような処理が行われます。

  1. WebSocketがopenしたら、checkConnectionをコールします。
  2. checkConnectionは、呼ばれてから30秒後にサーバにpingを送信します。
  3. ping送信後1秒以内にpongが返って来なかったら再接続を試みます。
  4. ping送信後1秒以内にpongが返って来たら、checkConnectionを再度コールします。

サーバ側はNodeで構成されており、以下のように実装しています。(一部抜粋)

// ユーザーからのメッセージを処理する
ws.on('message', (message) => {
  // pingの処理
  if (message === 'ping') {
    return ws.send('pong')
  }
  ...
}

以上のような処理に変更してからは、コネクションが維持されるようになりました。
現在は、コネクションの確認を30秒ごとに行っていますが、目的によって間隔を調整すると良いと思います。

最後に

繰り返しになりますが、WEBサイト制作者さん向けのサービスをリリースしましたので、お気軽にお試しいただけると幸いです。(無料で使えます)
元々は自分たち向けに作ったシステムでして、WEBサイト再作時に大量の情報やファイルを管理・共有するのに疲れ果て、それを解消するために作ったウェブアプリです。なかなか評判が良かったので、一般向けに作り直してリリースしました。

31
20
1

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
31
20

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?