全部產品
Search
文件中心

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

更新時間:Nov 21, 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執行個體。具體操作,請參見建立和管理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. 組態稽核頁面,檢查配置參數是否有誤,無誤的話單擊提交,等待監聽建立完成。

步驟四:佈建網域名解析

實際業務情境中,建議您使用自有網域名稱,通過CNAME解析的方式將自有網域名稱指向ALB執行個體網域名稱。

  1. 在左側導覽列,選擇應用型負載平衡 ALB > 執行個體

  2. 執行個體頁面,複製已建立的ALB執行個體的DNS名稱。

  3. 執行以下步驟添加CNAME解析記錄。

    說明

    對於非阿里雲註冊網域名稱,需先將網域名稱添加到雲解析控制台,才可以進行網域名稱解析設定。具體操作,請參見網域名稱管理。如果您是阿里雲註冊的網域名稱,請直接執行以下步驟。

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

    2. 權威網域名稱解析頁面,找到目標網域名稱,在操作列單擊解析設定

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

    4. 添加記錄面板,配置以下資訊完成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伺服器出現問題可能造成系統單點故障。在實際生產環境中,建議您使用雲資料庫 Tair(相容 Redis),提升應用系統整體高可用性。雲資料庫Tair(相容Redis)如何快速入門?