全部產品
Search
文件中心

Server Load Balancer:ALB使用WebSocket協議實現資訊即時推送

更新時間:Jul 20, 2024

WebSocket是一種在單個TCP串連上提供全雙工系統通訊渠道的網路通訊協定。WebSocket的設計使得用戶端和伺服器之間可以實現持久串連,都能夠主動地向對方發送資料或接收資料,減少了頻繁建立串連的開銷和延遲,這通常比傳統的HTTP請求和響應模式更高效。WebSocket主要應用於需要即時通訊功能的情境,ALB預設支援WebSocket協議。

WebSocket簡介

為什麼使用WebSocket

隨著互連網技術的迅速發展,Web應用的多樣化趨勢日益顯著,其中不少應用情境,例如直播間聊天室、即時彈幕等,都需要伺服器具備即時推送資料的能力。傳統的實現方式是通過輪詢技術,即用戶端瀏覽器在固定的時間間隔(例如每1秒)向伺服器發起HTTP請求,伺服器隨後將最新資料返回給用戶端。然而,這種模式存在顯著的不足,用戶端需要頻繁地發起請求,而HTTP請求的頭部資訊通常較長,有效資料卻相對較少,這不僅增加了伺服器的負擔,也造成了頻寬資源的極大浪費。

為瞭解決這些問題,HTML5引入了WebSocket協議,它為伺服器與用戶端之間的通訊提供了更為高效的解決方案。WebSocket協議支援全雙工系統通訊,這意味著伺服器和用戶端可以同時進行資料的發送和接收,從而允許伺服器在有新資料時主動推送給用戶端,無需用戶端不斷輪詢。這種雙向即時通訊機制顯著提高了資料轉送的效率,減少不必要的網路請求,有效節省伺服器資源和頻寬,同時為使用者帶來更為流暢和即時的互動體驗。

WebSocket協議的特性

WebSocket通訊前,首先用戶端與伺服器要進行TCP三向交握串連,然後進行一次叫做“握手”的特殊HTTP請求進行協議升級,完成協議升級後原始的HTTP串連被升級到WebSocket串連。在協議升級後,用戶端和伺服器之間的通訊將使用WebSocket協議進行而不再是HTTP,可以在同一個WebSocket串連上進行雙向通訊。

WebSocket串連一旦經過握手協商成功建立,便能維持活躍狀態,使得雙方能如同使用原始通訊端(Socket)那樣進行連續不斷的雙向資料轉送,而不必為每個通訊回合重新發起串連或等待確認。通過WebSocket,用戶端和伺服器之間得以建立一種持久、低延遲的串連,極大地提升了資料交換效率。

WebSocket通過資料幀進行通訊,它有自己的幀協議格式,頭資訊更簡潔,資料可以作為文本或二進位傳輸。這種方式減少了持久串連上額外的協議開銷,允許更高效的網路互動,能夠在節省伺服器資源和頻寬的同時,提供更優質的即時互動體驗。

關於WebSocket協議的更多資訊,可參考官方文檔The WebSocket Protocol

WebSocket應用情境

WebSocket主要適用於需要快速、即時的雙向通訊的應用情境,例如AI應用、線上聊天室、即時通知系統、多人線上遊戲、即時市場資訊推送等。

情境樣本

某公司需要在阿里雲上部署Web線上聊天應用,使用者可以通過訪問網域名稱來接入後端服務進行即時交流。該應用由於其即時通訊的特性,要求使用者之間的資訊傳遞必須具備低延遲、高效率和雙向即時的特點。

該公司的網站服務面臨的挑戰是高並發與長串連管理。隨著使用者數量的增長,傳統的HTTP模式無法滿足大量使用者同時線上並保持即時通訊的需求,因為每次通訊都需要重建立立串連,這會導致伺服器壓力劇增且效能低下。

在這個情境下,選用ALB結合WebSocket協議,能夠有效解決高並發下的長串連管理問題。通過後端伺服器組多伺服器部署WebSocket應用程式,並使用Redis進行訊息同步,確保服務的高可用性,從而為線上聊天室應用提供了一個可靠、高效的即時資訊推送解決方案。

注意事項

ALB的HTTP監聽預設支援WebSocket協議。ALB預設支援熱更新,即配置變更時不會影響已有長串連。

使用時需要注意如下事項:

  • 若ALB與後端伺服器的串連採用某個版本的HTTP協議(例如HTTP/1.1),建議後端伺服器採用支援同樣HTTP協議版本的Web Server。

  • HTTP監聽的預設串連請求逾時時間為60秒,即如果ALB與後端服務超過60秒無訊息互動,會主動中斷連線。

    • 如果60秒無法滿足您的需求,您可以通過修改監聽的串連請求逾時時間欄位,調整該時間值。

    • 如果需要維持串連一直不中斷,需要主動實現保活機制,每60秒內進行一次報文互動。

前提條件

  • 已建立公網ALB執行個體。具體操作,請參見建立應用型負載平衡

  • 已準備3個Elastic Compute Service01、ECS02、ECS03。

    • ECS01、ECS02用於部署WebSocket應用程式,ECS03用於部署Redis。

    • 本文樣本中伺服器作業系統統一為CentOS7.9。

    • ECS01、ECS02、ECS03建議處於同一安全性群組中。如果分配了不同的安全性群組,注意互相允許存取伺服器需要通訊的連接埠。

  • 已經註冊網域名稱並完成備案。具體操作,請參見註冊阿里雲網域名稱ICP備案

操作步驟

步驟一:部署服務

您需要在您的ECS03伺服器中部署Redis,在ECS01、ECS02伺服器中部署WebSocket應用程式。

本文以CentOS 7.9為樣本,示範使用Python快速部署一個簡易的線上聊天室測試服務。樣本僅供參考,實際使用過程中以您自己開發的程式和服務為準。

在ECS03部署Redis服務

  1. 登入ECS03伺服器後台。

  2. 複製粘貼如下命令,並執行,完成Redis部署與配置。

    # 安裝 EPEL (Extra Packages for Enterprise Linux)
    sudo yum install epel-release -y
    
    # 安裝 Redis
    sudo yum install redis -y
    
    # 啟動並啟用 Redis 服務
    sudo systemctl start redis
    sudo systemctl enable redis
    
    # 檢查並編輯 Redis 設定檔,允許遠端連線
    sudo sed -i 's/^bind 127.0.0.1$/bind 0.0.0.0/' /etc/redis.conf
    sudo sed -i 's/^protected-mode yes/protected-mode no/' /etc/redis.conf
    
    # 重啟 Redis 服務以使更改生效
    sudo systemctl restart redis
    
    # 檢查 Redis 是否運行
    sudo systemctl status redis
    
  3. 命令執行無報錯,並且命令運行完成後,返回如下資訊並顯示Redis服務為active(running)狀態,表示部署與配置成功。

    image

在ECS01中部署WebSocket應用程式

  1. 登入ECS01伺服器後台。

  2. 執行sudo pip3 install flask flask-socketio flask-cors redis,安裝依賴庫。

  3. 執行vi ECS01_ws.py,按i鍵進入編輯模式。

  4. 複製並粘貼如下代碼:

    部署測試服務代碼參考

    說明

    注意第13行的redis_url中的IP地址,需要修改為Redis伺服器的IP地址,即ECS03的IP地址。

    import os
    import redis
    from flask import Flask, render_template, request
    from flask_cors import CORS
    from flask_socketio import SocketIO, emit, disconnect
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'secret!'
    # 啟用跨域資源共用(CORS)
    CORS(app)
    
    # 配置 Redis 作為訊息佇列和狀態儲存
    redis_url = "redis://192.168.*.*:6379/0"  # 替換為你的 Redis 伺服器 IP
    redis_client = redis.StrictRedis.from_url(redis_url)
    
    # 記錄層級增加為 DEBUG 以便於調試
    socketio = SocketIO(app, message_queue=redis_url, manage_session=True, logger=True, engineio_logger=True, cors_allowed_origins="*")
    
    SESSION_PREFIX = "session:"
    
    
    def set_session_data(session_id, key, value):
        redis_client.hset(f"{SESSION_PREFIX}{session_id}", key, value)
    
    
    def get_session_data(session_id, key):
        return redis_client.hget(f"{SESSION_PREFIX}{session_id}", key)
    
    
    def delete_session_data(session_id):
        redis_client.delete(f"{SESSION_PREFIX}{session_id}")
    
    
    @app.route('/')
    def index():
        return render_template('index.html')
    
    
    @socketio.on('connect')
    def handle_connect():
        try:
            session_id = request.sid  # 擷取用戶端的 session ID
            print(f"Session {session_id} connected.")
            welcome_message = "您已進入聊天室!"
            emit('message', welcome_message)
            set_session_data(session_id, "username", '')  # 初始化使用者名稱為空白
        except Exception as e:
            print(f"Error during connection: {str(e)}")
    
    
    @socketio.on('disconnect')
    def handle_disconnect():
        try:
            session_id = request.sid
            username = get_session_data(session_id, "username")
            if username:
                username = username.decode()
                leave_message = f"{username} 已離開聊天室。"
                emit('message', leave_message, broadcast=True)
                print(leave_message)
            delete_session_data(session_id)
            print(f"Session {session_id} disconnected.")
        except Exception as e:
            print(f"Error during disconnection: {str(e)}")
    
    
    @socketio.on('set_username')
    def handle_set_username(username):
        session_id = request.sid
        set_session_data(session_id, "username", username)
        print(f"用戶端 {session_id} 的使用者名稱設定為 {username}")
        emit('message', f"您的使用者名稱已設定為:{username}")
    
    
    @socketio.on('message')
    def handle_message(msg):
        session_id = request.sid
        username = get_session_data(session_id, "username")
        if username:
            username = username.decode()
            formatted_message = f"{username}:{msg}"
            emit('message', formatted_message, broadcast=True)
            print(formatted_message)
        else:
            warning_message = "發送訊息失敗:請先設定使用者名稱。"
            emit('message', warning_message)
            print(warning_message)
    
    
    if __name__ == '__main__':
        # 確儲存在 templates 目錄
        if not os.path.exists('templates'):
            os.makedirs('templates')
    
        # 使用 Flask 模板(index.html)
        html_code = '''<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>聊天室</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                display: flex;
                flex-direction: column;
                align-items: center;
                margin: 0;
                padding: 0;
                background-color: #f0f0f0;
            }
            h1 {
                color: #333;
            }
            .chat-container {
                width: 90%;
                max-width: 600px;
                background: white;
                padding: 20px;
                border-radius: 8px;
                box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            }
            .user-container, .message-container {
                display: flex;
                margin-bottom: 10px;
            }
            .user-container input, .message-container input {
                flex: 1;
                padding: 10px;
                margin-right: 10px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
            .message-container {
                margin-top: 10px;
            }
            button {
                padding: 10px;
                background-color: #0056b3;
                color: white;
                border: none;
                border-radius: 4px;
                cursor: pointer;
            }
            button:hover {
                background-color: #004099;
            }
            #messages {
                border: 1px solid #ccc;
                padding: 10px;
                height: 300px;
                overflow-y: scroll;
                margin-bottom: 10px;
                border-radius: 4px;
                background-color: #f9f9f9;
            }
        </style>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
        <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    </head>
    <body>
        <h1>線上聊天室</h1>
        <div class="chat-container">
            <div class="user-container">
                <input type="text" id="username" autocomplete="off" placeholder="請輸入使用者名稱">
                <button onclick="setUsername()">設定使用者名稱</button>
            </div>
            <div id="messages"></div>
            <div class="message-container">
                <input type="text" id="myMessage" autocomplete="off" placeholder="請輸入訊息...">
                <button onclick="sendMessage()">發送</button>
            </div>
        </div>
        <script>
            var socket = io({ transports: ['websocket', 'polling', 'flashsocket'] });
            var usernameSet = false;
            socket.on('connect', function() {
                console.log("Connected to the server!");
                socket.on('message', function(msg){
                    $('#messages').append($('<div>').text(msg));
                    $('#messages').scrollTop($('#messages')[0].scrollHeight);
                });
            });
            function setUsername() {
                var username = $('#username').val();
                if (username) {
                    socket.emit('set_username', username);
                    usernameSet = true;  // 設定使用者名稱標識
                } else {
                    alert("使用者名稱不可為空!");
                }
            }
            function sendMessage() {
                if (usernameSet) {
                    var message = $('#myMessage').val();
                    if (message) {
                        socket.send(message);
                        $('#myMessage').val('');
                    } else {
                        alert("訊息不可為空!");
                    }
                } else {
                    alert("請先設定使用者名稱!");
                }
            }
        </script>
    </body>
    </html>
    '''
    
        # 將模板儲存到檔案
        with open('templates/index.html', 'w') as file:
            file.write(html_code)
    
        socketio.run(app, host='0.0.0.0', port=5000)
    

  5. Esc鍵,輸入:wq儲存修改。

  6. 執行sudo python3 ECS01_ws.py命令,運行指令碼。

  7. 當最後顯示如下執行結果時,表示WebSocket應用程式已啟動,連接埠為5000。

    Server initialized for threading.
     * Serving Flask app 'ECS01_ws' (lazy loading)
     * Environment: production
       WARNING: This is a development server. Do not use it in a production deployment.
       Use a production WSGI server instead.
     * Debug mode: off
     * Running on all addresses.
       WARNING: This is a development server. Do not use it in a production deployment.
     * Running on http://192.168.*.*:5000/ (Press CTRL+C to quit)
    

    如果出現啟動失敗,需要排查下連接埠是否已被佔用,或者命令及代碼是否複製粘貼錯誤。

在ECS02中部署WebSocket應用程式

  1. 登入ECS02伺服器後台。

  2. 執行sudo pip3 install flask flask-socketio flask-cors redis,安裝依賴庫。

  3. 執行vi ECS02_ws.py,按i鍵進入編輯模式。

  4. 複製並粘貼如下代碼:

    部署測試服務代碼參考

    說明

    注意第13行的redis_url中的IP地址,需要修改為Redis伺服器的IP地址,即ECS03的IP地址。

    import os
    import redis
    from flask import Flask, render_template, request
    from flask_cors import CORS
    from flask_socketio import SocketIO, emit, disconnect
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'secret!'
    # 啟用跨域資源共用(CORS)
    CORS(app)
    
    # 配置 Redis 作為訊息佇列和狀態儲存
    redis_url = "redis://192.168.*.*:6379/0"  # 替換為你的 Redis 伺服器 IP
    redis_client = redis.StrictRedis.from_url(redis_url)
    
    # 記錄層級增加為 DEBUG 以便於調試
    socketio = SocketIO(app, message_queue=redis_url, manage_session=True, logger=True, engineio_logger=True, cors_allowed_origins="*")
    
    SESSION_PREFIX = "session:"
    
    
    def set_session_data(session_id, key, value):
        redis_client.hset(f"{SESSION_PREFIX}{session_id}", key, value)
    
    
    def get_session_data(session_id, key):
        return redis_client.hget(f"{SESSION_PREFIX}{session_id}", key)
    
    
    def delete_session_data(session_id):
        redis_client.delete(f"{SESSION_PREFIX}{session_id}")
    
    
    @app.route('/')
    def index():
        return render_template('index.html')
    
    
    @socketio.on('connect')
    def handle_connect():
        try:
            session_id = request.sid  # 擷取用戶端的 session ID
            print(f"Session {session_id} connected.")
            welcome_message = "您已進入聊天室!"
            emit('message', welcome_message)
            set_session_data(session_id, "username", '')  # 初始化使用者名稱為空白
        except Exception as e:
            print(f"Error during connection: {str(e)}")
    
    
    @socketio.on('disconnect')
    def handle_disconnect():
        try:
            session_id = request.sid
            username = get_session_data(session_id, "username")
            if username:
                username = username.decode()
                leave_message = f"{username} 已離開聊天室。"
                emit('message', leave_message, broadcast=True)
                print(leave_message)
            delete_session_data(session_id)
            print(f"Session {session_id} disconnected.")
        except Exception as e:
            print(f"Error during disconnection: {str(e)}")
    
    
    @socketio.on('set_username')
    def handle_set_username(username):
        session_id = request.sid
        set_session_data(session_id, "username", username)
        print(f"用戶端 {session_id} 的使用者名稱設定為 {username}")
        emit('message', f"您的使用者名稱已設定為:{username}")
    
    
    @socketio.on('message')
    def handle_message(msg):
        session_id = request.sid
        username = get_session_data(session_id, "username")
        if username:
            username = username.decode()
            formatted_message = f"{username}:{msg}"
            emit('message', formatted_message, broadcast=True)
            print(formatted_message)
        else:
            warning_message = "發送訊息失敗:請先設定使用者名稱。"
            emit('message', warning_message)
            print(warning_message)
    
    
    if __name__ == '__main__':
        # 確儲存在 templates 目錄
        if not os.path.exists('templates'):
            os.makedirs('templates')
    
        # 使用 Flask 模板(index.html)
        html_code = '''<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>聊天室</title>
        <style>
            body {
                font-family: Arial, sans-serif;
                display: flex;
                flex-direction: column;
                align-items: center;
                margin: 0;
                padding: 0;
                background-color: #f0f0f0;
            }
            h1 {
                color: #333;
            }
            .chat-container {
                width: 90%;
                max-width: 600px;
                background: white;
                padding: 20px;
                border-radius: 8px;
                box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            }
            .user-container, .message-container {
                display: flex;
                margin-bottom: 10px;
            }
            .user-container input, .message-container input {
                flex: 1;
                padding: 10px;
                margin-right: 10px;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
            .message-container {
                margin-top: 10px;
            }
            button {
                padding: 10px;
                background-color: #0056b3;
                color: white;
                border: none;
                border-radius: 4px;
                cursor: pointer;
            }
            button:hover {
                background-color: #004099;
            }
            #messages {
                border: 1px solid #ccc;
                padding: 10px;
                height: 300px;
                overflow-y: scroll;
                margin-bottom: 10px;
                border-radius: 4px;
                background-color: #f9f9f9;
            }
        </style>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
        <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    </head>
    <body>
        <h1>線上聊天室</h1>
        <div class="chat-container">
            <div class="user-container">
                <input type="text" id="username" autocomplete="off" placeholder="請輸入使用者名稱">
                <button onclick="setUsername()">設定使用者名稱</button>
            </div>
            <div id="messages"></div>
            <div class="message-container">
                <input type="text" id="myMessage" autocomplete="off" placeholder="請輸入訊息...">
                <button onclick="sendMessage()">發送</button>
            </div>
        </div>
        <script>
            var socket = io({ transports: ['websocket', 'polling', 'flashsocket'] });
            var usernameSet = false;
            socket.on('connect', function() {
                console.log("Connected to the server!");
                socket.on('message', function(msg){
                    $('#messages').append($('<div>').text(msg));
                    $('#messages').scrollTop($('#messages')[0].scrollHeight);
                });
            });
            function setUsername() {
                var username = $('#username').val();
                if (username) {
                    socket.emit('set_username', username);
                    usernameSet = true;  // 設定使用者名稱標識
                } else {
                    alert("使用者名稱不可為空!");
                }
            }
            function sendMessage() {
                if (usernameSet) {
                    var message = $('#myMessage').val();
                    if (message) {
                        socket.send(message);
                        $('#myMessage').val('');
                    } else {
                        alert("訊息不可為空!");
                    }
                } else {
                    alert("請先設定使用者名稱!");
                }
            }
        </script>
    </body>
    </html>
    '''
    
        # 將模板儲存到檔案
        with open('templates/index.html', 'w') as file:
            file.write(html_code)
    
        socketio.run(app, host='0.0.0.0', port=5000)
    

  5. Esc鍵,輸入:wq儲存修改。

  6. 執行sudo python3 ECS02_ws.py命令,運行指令碼。

  7. 當最後顯示如下執行結果時,表示WebSocket應用程式已啟動,連接埠為5000。

    Server initialized for threading.
     * Serving Flask app 'ECS02_ws' (lazy loading)
     * Environment: production
       WARNING: This is a development server. Do not use it in a production deployment.
       Use a production WSGI server instead.
     * Debug mode: off
     * Running on all addresses.
       WARNING: This is a development server. Do not use it in a production deployment.
     * Running on http://192.168.*.*:5000/ (Press CTRL+C to quit)
    

    如果出現啟動失敗,需要排查下連接埠是否已被佔用,或者命令及代碼是否複製粘貼錯誤。

步驟二:設定管理員組

  1. 登入應用型負載平衡ALB控制台

  2. 在頂部功能表列,選擇執行個體所屬的地區。

  3. 在左側導覽列,選擇伺服器組

  4. 單擊建立伺服器組。在建立伺服器組頁面配置以下資訊,其他參數可保持預設值或根據實際情況修改。完成後單擊建立

    配置

    說明

    伺服器群組類型

    選擇伺服器類型

    VPC

    選擇後端伺服器即ECS01、ECS02所在的VPC。

    後端伺服器需要與ALB執行個體處於同一VPC中。

  5. 在彈出的伺服器組建立成功視窗中,單擊添加後端伺服器

  6. 添加後端伺服器配置頁面,選中ECS01與ECS02並完成添加,注意連接埠需要配置為WebSocket應用程式連接埠。本文程式碼範例中WebSocket應用程式連接埠為5000。

步驟三:配置HTTP監聽

  1. 登入應用型負載平衡ALB控制台

  2. 在頂部功能表列,選擇執行個體所屬的地區。

  3. 在左側導覽列,選擇執行個體

  4. 執行個體頁面,找到目標執行個體,然後在操作列單擊建立監聽

  5. 配置監聽頁面配置以下資訊,其他參數可保持預設值或根據實際情況修改。完成後單擊下一步

    配置

    說明

    選擇監聽協議

    選擇HTTP

    監聽連接埠

    本文配置連接埠5000。

  6. 選擇伺服器組頁面配置以下資訊,其他參數可保持預設值或根據實際情況修改。完成後單擊下一步

    配置

    說明

    選擇伺服器組

    選擇此前已建立好的伺服器組。

  7. 組態稽核頁面,檢查配置參數是否有誤,無誤的話單擊提交,等待監聽建立完成。

步驟四:佈建網域名解析

  1. 登入應用型負載平衡ALB控制台

  2. 在頂部功能表列選擇地區。

  3. 選擇要進行網域名稱解析的ALB執行個體,複製其對應的DNS名稱。

  4. 完成以下步驟來添加CNAME解析記錄。

    1. 登入網域名稱解析控制台

    2. 網域名稱解析頁面單擊添加網域名稱

    3. 添加網域名稱對話方塊中輸入您的主機網域名稱,然後單擊確認

      重要

      您的主機網域名稱需已完成TXT記錄驗證。

    4. 在目標網域名稱的操作列單擊解析設定

    5. 解析設定頁面單擊添加記錄

    6. 添加記錄面板配置以下資訊完成CNAME解析配置,然後單擊確認

      配置

      說明

      記錄類型

      在下拉式清單中選擇CNAME

      主機記錄

      您的網域名稱的首碼。

      解析請求來源

      選擇預設。

      記錄值

      輸入欄位名對應的CNAME地址,即您複製的ALB執行個體的DNS名稱。

      TTL

      全稱Time To Live,表示DNS記錄在DNS伺服器上的緩衝時間,本文使用預設值。

步驟五:結果驗證

準備2個不同IP地址的能夠訪問公網的終端電腦,通過在瀏覽器輸入聊天訊息並查看效果,驗證ALB使用WebSocket協議實現資訊即時推送。

  1. 在瀏覽器中輸入http://網域名稱:5000,訪問線上聊天室應用。

    頁面訪問成功樣本:

    image

    如果您開啟了瀏覽器開發人員工具,您可以在網路Network頁簽看到,瀏覽器已經在使用WebSocket協議進行通訊。

    image

  2. 輸入使用者名稱用於後續聊天互動,完成後單擊設定使用者名稱

  3. 在不同終端電腦中,分別輸入多條聊天訊息並單擊發送,進行測試。

    所有瀏覽器中,均可以即時收到訊息。

    image

  4. 如上驗證過程表明,通過ALB使用WebSocket協議實現了資訊即時推送,並且實現了高可用。

常見問題

如何使用WebSocket Secure協議?

WebSocket Secure是WebSocket協議的加密版本。

HTTPS監聽預設支援WebSocket Secure協議。您在配置監聽時,選擇使用HTTPS監聽,即可使用WebSocket Secure協議。

使用WebSocket收費嗎?

WebSocket和WebSocket Secure協議不額外收取費用。

哪些地區支援WebSocket?

ALB支援的所有地區,都已支援WebSocket和WebSocket Secure。

相關文檔

本文的樣本中使用了在ECS部署Redis的簡單方式,便於您做業務測試,如果Redis伺服器出現問題可能造成系統單點故障。在實際生產環境中,建議您使用ApsaraDB for Redis,提升應用系統整體高可用性。ApsaraDB for Redis如何快速入門?