Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WebSocket における Graceful Update

Toru Sasaki
December 25, 2023
95

WebSocket における Graceful Update

クライアントと常時接続している WebSocket アプリケーションの場合、通常のサーバーと同じようにデプロイするとそのタイミングで一斉に接続が切れて、再接続の波が押し寄せてしまいます。EVサービス事業部でとった対策方法についてまとめています。

Toru Sasaki

December 25, 2023
Tweet

Transcript

  1. ENECHANGE株式会社
    佐々木 徹
    WebSocketにおけるGraceful Update

    View full-size slide

  2. Copyright © ENECHANGE Ltd. All Rights Reserved. | 2
    自己紹介
    佐々木 徹
    所属 EV充電サービス事業部 開発チーム
    入社 2023年5月
    経歴
    ● 新卒で SI 下請SE … 2年
    ● Webシステム受託開発会社でサーバーサイドエンジニア
    …8年
    ○ 大規模ブログサービス
    ■ 記事検索システムのフルリプレイス
    ■ 記事更新通知システムの開発
    ○ 広告代理店案件管理システム新規開発
    ○ 社内用Web会議システムのR&D
    GitHub tetsu040e
    所有EV VW ID.4 Lite (2023年10月納車)

    View full-size slide

  3. Copyright © ENECHANGE Ltd. All Rights Reserved. | 3
    今回お話しする内容
    ● EV充電サービスのシステムについて
    ● WebSocket を使ったプロダクトのデプロイ問題
    ● WebSocket における Graceful Update

    View full-size slide

  4. EV充電サービスについて

    View full-size slide

  5. Copyright © ENECHANGE Ltd. All Rights Reserved. | 5
    EV充電エネチェンジ
    日本政府の掲げた「2035年までに新車販売の100%を電動車にする」という目標を背景に、2021年11月からサービスを開始
    2027年までの3万台設置へ向け鋭意成長中
    基本的な機能
    ● 充電スポットを探す
    ● 充電開始・終了
    ● 経路検索v2
    ● 充電スポットへのコメント投稿・閲覧
    ● 使えた・使えなかった報告
    https://ev-charge-enechange.jp/

    View full-size slide

  6. Copyright © ENECHANGE Ltd. All Rights Reserved. | 6
    システム構成
    AWS
    データベース
    フロント
    サーバー
    充電器管理
    サーバー
    アプリユーザー
    (スポットを探すなど)
    アプリ・ゲストユーザー
    (アプリ・Web から充電)
    充電カードユーザー
    (カードをかざして充電
    )
    外部システム
    充電器ステータスなどを同期
    OCPP
    HTTPS
    HTTP
    HTTPSなど

    View full-size slide

  7. Copyright © ENECHANGE Ltd. All Rights Reserved. | 7
    OCPP (Open Charge Point Protocol)
    ● EV用充電スタンドと中央管理システム(充電器管理サーバー)との通信に使用されるプロ
    トコル
    ● JSON over WebSocket で充電操作や電力データの連携を行う
    ○ StartTransaction
    ○ StopTransaction
    ○ StatusNotification
    ○ MeterValue
    ○ …など
    => 充電器1台ごとに充電器管理サーバーと WebSocket で接続している
    WebSocket
    JSON
    JSON

    View full-size slide

  8. WebSocket を使ったプロダクトのデプロイ問題

    View full-size slide

  9. Copyright © ENECHANGE Ltd. All Rights Reserved. | 9
    EV充電サービスで悩まされてた課題
    ● 4月
    ○ 充電器管理サーバーダウン (8時間)
    ○ 充電器管理サーバーダウン (8時間)
    ○ 充電器の利用ステータス更新が途絶える (1時間)
    ● 6月
    ○ DB ダウン (5時間)
    => いずれの障害も、多くの充電器で充電開始できないという致命的な障害
    => デプロイによる充電器からの再接続が集中してサーバーが耐えられなかった

    View full-size slide

  10. Copyright © ENECHANGE Ltd. All Rights Reserved. | 10
    デプロイによって WebSocket 切断・再接続が集中する問題
    デプロイ前 デプロイ後の再接続
    デプロイによる切断
    ● 常時 WebSocket で接続しているサーバーで単純にデプロイをすると、一斉に切断されてしまう
    ● 切断を検知して即時再接続するクライアントだと、再接続アクセスがスパイクしてサーバーがパン
    クしてしまうことがある

    View full-size slide

  11. Copyright © ENECHANGE Ltd. All Rights Reserved. | 11
    解決策は明白
    再接続が集中しない Graceful な仕組みを導入する

    View full-size slide

  12. WebSocket における Graceful Update

    View full-size slide

  13. Copyright © ENECHANGE Ltd. All Rights Reserved. | 13
    ● Exponential Backoff
    ● AWS CodeDeploy の線形デプロイオプション
    ● 独自実装
    考えられるソリューション

    View full-size slide

  14. Copyright © ENECHANGE Ltd. All Rights Reserved. | 14
    Exponential Backoff
    ● リトライ(再接続)間隔を指数関数的に後退させていくアルゴリズム
    ○ 例: 1秒後に再接続、NGなら2秒後に再接続、4秒後、8秒後...
    ● ジッターと組み合わせて実装すればサーバーへの再接続が集中しにくくなる
    ● クライアント側での実装が必要
    ○ クライアント側の実装ができるのであれば、これが一番シンプルな解決策
    ● IoT システムの場合、クライアントである端末側のシステムアップデートが難しい場合がある
    ○ ENECHANGE の EV充電サービスにおいても、充電器はメーカーから購入しているためそこ
    で動くソフトウェアの更新には時間とコストがかかる

    View full-size slide

  15. Copyright © ENECHANGE Ltd. All Rights Reserved. | 15
    AWS CodeDeploy の機能を使った線形デプロイ
    ● AWS CodeDeploy には線形デプロイのオプションがあり簡単に設定できる!
    ○ CodeDeployDefault.ECSLinear10PercentEvery3Minutes
    ● Blue 環境 (既存) から Green 環境 (新) へ設定に応じて徐々にトラフィックを置き換えてくれる
    ● これを使えばデプロイ時の再接続が集中しなくて Graceful になるのでは
    => しかし、実際はそうならない...

    View full-size slide

  16. Copyright © ENECHANGE Ltd. All Rights Reserved. | 16
    Green環境立ち上げ
    AWS CodeDeploy の線形デプロイと WebSocket
    ● トラフィックを置き換えてくれるのは新規接続のみ
    ● WebSocket で接続済みのものはそのまま Blue 環境と繋がったまま
    ● 結局 Blue 環境が破棄されるタイミングで一斉切断 -> 再接続が集中するのは変わらない
    トラフィックを置き換え
    各端末
    Blue環境
    コンテナ
    コンテナ
    Green環境
    コンテナ
    コンテナ
    Blue環境
    コンテナ
    コンテナ
    各端末
    ALB
    Green環境
    コンテナ
    コンテナ
    Blue環境破棄
    各端末
    Blue環境 Green環境
    コンテナ
    コンテナ
    既存のWebSocket接続
    ALB ALB

    View full-size slide

  17. Copyright © ENECHANGE Ltd. All Rights Reserved. | 17
    少しずつ切断用の
    エンドポイントを叩く
    Graceful Update の独自実装
    Graceful Update の仕組みを自前で実装する
    ● WebSocket サーバーに任意の端末との接続を切るための内部向けエンドポイントを作成
    ● トラフィックの置き換えが完了したタイミングを EventBridge で検知
    ● Lambda を起動し、 10〜15分かけて少しずつ充電器と接続を切っていく
    ● 切断された端末から順に Green 環境へ再接続される
    各端末
    Blue環境
    コンテナ
    コンテナ
    CodeDeploy EventBridge
    Lambda
    トラフィック置き換え
    トラフィック置き換え完了
    のイベント
    WebSocket切断用の
    関数起動
    Green環境
    コンテナ
    コンテナ
    ALB

    View full-size slide

  18. Copyright © ENECHANGE Ltd. All Rights Reserved. | 18
    Graceful Update の独自実装
    トラフィックのシフトが完了したイベントを検知
    {
    "detail": {
    "deploymentGroup": ["xxxxxx"],
    "state": ["SUCCESS"]
    },
    "detail-type": ["CodeDeploy Instance State-change Notification"],
    "source": ["aws.codedeploy"]
    }
    参照: https://docs.aws.amazon.com/codedeploy/latest/userguide/monitoring-cloudwatch-events.html
    待機時間の間に Lambda で少しずつ切断用エンドポイントを叩く
    const waitingTimePerDevice = 100; // 実際は待機時間と端末数から適切な待ち時間を算出する
    for (const device of devices) {
    const url = `http://ws.example.com/foo/${device.id}/close`
    await http.post(url).catch((err) => {
    console.log(err);
    })
    console.log(`Close websocket. deviceId: ${device.id}`);
    await scheduler.wait(waitingTimePerDevice);
    }
    切断処理用の Lambda 関数を実行

    View full-size slide

  19. Copyright © ENECHANGE Ltd. All Rights Reserved. | 19
    まとめ
    ● Exponential Backoff
    ○ クライアント側での実装ハードルが容易であれば、一番ポピュラーでシンプルな選択肢
    ○ IoT 端末などがクライアントである場合、クライアント側の対応が難しいケースもある
    ● AWS CodeDeploy
    ○ 線形デプロイのオプションがあるためパッと見では簡単に対応できそう (だができない)
    ○ 新規接続のトラフィックを移行してくれるものなので、常時接続している WebSocket ではう
    まく使いにくい
    ● 独自実装
    ○ CodeDeploy のイベントを EventBridge で拾って Lambda を起動し、徐々に既存接続を切断
    していく仕組みを自ら実装する
    ○ 端末の仕様にあわせてカスタマイズ可能

    View full-size slide

  20. ありがとうございました

    View full-size slide