Todos los productos
Search
Centro de documentos

Server Load Balancer:Use CLB and WebSocket for real-time messaging

Última actualización: Sep 03, 2026

WebSocket es un protocolo de red que proporciona un canal de comunicación full-duplex sobre una única conexión TCP. Permite establecer una conexión persistente entre un cliente y un servidor, lo que facilita que ambos envíen y reciban datos de forma proactiva. Este diseño reduce la sobrecarga y la latencia asociadas con la creación frecuente de nuevas conexiones, por lo que resulta más eficiente que el modelo tradicional de solicitud-respuesta HTTP. WebSocket se utiliza principalmente en aplicaciones que requieren comunicación en tiempo real. Classic Load Balancer (CLB) admite el protocolo WebSocket de forma predeterminada.

Introducción a WebSocket

Razones para usar WebSocket

Con la evolución de las tecnologías web, las aplicaciones requieren cada vez más que los servidores envíen datos en tiempo real para funciones como salas de chat en vivo y comentarios instantáneos. El método tradicional de sondeo, en el que el navegador del cliente envía solicitudes HTTP repetidas al servidor para obtener los datos más recientes, presenta desventajas significativas. Las solicitudes frecuentes con encabezados HTTP grandes y cargas útiles de datos pequeñas aumentan la carga del servidor y desperdician ancho de banda.

Para resolver estos problemas, HTML5 introdujo el protocolo WebSocket, que ofrece una solución más eficiente para la comunicación entre cliente y servidor. WebSocket admite comunicación full-duplex, lo que significa que el servidor y el cliente pueden enviar y recibir datos simultáneamente. Esto permite que el servidor envíe nuevos datos al cliente de forma proactiva sin esperar una solicitud de sondeo. Este mecanismo de comunicación bidireccional y en tiempo real mejora la eficiencia en la transferencia de datos, reduce las solicitudes de red innecesarias y ahorra recursos del servidor y ancho de banda, lo que proporciona una experiencia de usuario más fluida y receptiva.

Funciones clave de WebSocket

La comunicación comienza con un saludo TCP estándar de tres vías. A continuación, el cliente envía una solicitud HTTP especial, conocida como saludo de actualización de protocolo. Una vez completado este saludo correctamente, la conexión cambia de HTTP a WebSocket. Toda la comunicación posterior entre el cliente y el servidor utiliza el protocolo WebSocket, lo que permite el intercambio bidireccional de datos sobre la misma conexión.

Una vez establecida, la conexión WebSocket permanece activa. Esta conexión persistente y de baja latencia permite una transferencia de datos continua y bidireccional, lo que mejora la eficiencia del intercambio de información.

image

WebSocket se comunica mediante tramas de datos, las cuales tienen su propio formato de protocolo de trama con encabezados concisos. Los datos se pueden transmitir como texto o en formato binario. Este método reduce la sobrecarga del protocolo en conexiones persistentes y hace que la interacción de red sea más eficiente. Además, ahorra recursos del servidor y ancho de banda, al tiempo que ofrece una experiencia interactiva en tiempo real más fluida.

Para obtener más información sobre el protocolo WebSocket, consulte la documentación oficial The WebSocket Protocol.

Casos de uso de WebSocket

WebSocket es ideal para aplicaciones que requieren comunicación bidireccional rápida y en tiempo real, como aplicaciones de IA, salas de chat en línea, sistemas de notificaciones en tiempo real, juegos multijugador en línea y fuentes de datos de mercado en tiempo real.

Escenario de ejemplo

Una empresa desea desplegar una aplicación de chat en línea basada en web en Alibaba Cloud. Los usuarios acceden al servicio de backend a través de un nombre de dominio para comunicarse en tiempo real. Al tratarse de una aplicación de mensajería instantánea, requiere baja latencia y una comunicación bidireccional eficiente y en tiempo real.

El servicio del sitio web de la empresa enfrenta desafíos relacionados con alta concurrencia y gestión de conexiones persistentes. A medida que crece el número de usuarios, el modelo HTTP tradicional no puede admitir muchos usuarios concurrentes en comunicación en tiempo real, ya que cada interacción requiere una nueva conexión. Esto provoca un aumento drástico en la carga del servidor y un rendimiento deficiente.

En este escenario, el uso de CLB con el protocolo WebSocket gestiona eficazmente las conexiones persistentes bajo alta concurrencia. Al desplegar la aplicación WebSocket en varios servidores backend dentro de un vServer group y utilizar Redis para la sincronización de mensajes, el servicio logra alta disponibilidad. Esto proporciona una solución de mensajería en tiempo real confiable y eficiente para la aplicación de chat en línea.

image

Notas de uso

Los listeners HTTP en CLB admiten el protocolo WebSocket de forma predeterminada. CLB admite actualizaciones en caliente, lo que significa que los cambios de configuración no afectan las conexiones persistentes existentes.

Tenga en cuenta lo siguiente:

  • Si la conexión entre CLB y los servidores backend utiliza una versión específica de HTTP, como HTTP/1.1, se debe usar un servidor web compatible con esa misma versión de HTTP en los servidores backend.

  • El tiempo de espera predeterminado para solicitudes de conexión en un listener HTTP es de 60 segundos. Si no se intercambian mensajes entre CLB y un servidor backend durante más de 60 segundos, CLB cierra la conexión de forma proactiva.

    • Si el tiempo de espera predeterminado de 60 segundos es insuficiente para sus necesidades, modifique el parámetro Connection Request Timeout del listener.

    • Para mantener la conexión abierta, implemente un mecanismo keepalive que intercambie paquetes al menos una vez cada 60 segundos.

  • Los listeners HTTP en CLB admiten el protocolo WebSocket de forma predeterminada, y los listeners HTTPS admiten el protocolo WebSocket Secure (WSS) también de forma predeterminada. No se requiere configuración adicional.

  • Cuando utiliza listeners TCP, CLB no proporciona soporte integrado para WebSocket. Debe configurar WebSocket en los servidores backend. Los elementos de configuración de los listeners TCP (algoritmo de programación, persistencia de sesión, limitación de ancho de banda y tiempo de espera de conexión) no incluyen opciones relacionadas con WebSocket.

  • Al configurar un puerto de escucha, evite puertos vulnerables como 25, 135, 139, 444, 445, 5800 y 5900. Esta restricción la imponen las redes de los ISP, no CLB. La consola de CLB no bloquea la configuración de estos puertos, pero algunas redes de ISP sí bloquean el tráfico en ellos.

Requisitos previos

  • Cuenta con created a Classic Load Balancer (CLB) instance.

  • Se requieren tres instancias ECS: ECS01, ECS02 y ECS03.

    • ECS01 y ECS02 se utilizan para desplegar la aplicación WebSocket, mientras que ECS03 se usa para desplegar Redis.

    • En este tutorial, todos los servidores ejecutan CentOS 7.9.

    • Se recomienda colocar ECS01, ECS02 y ECS03 en el mismo security group. Si se encuentran en diferentes security groups, asegúrese de configurar reglas que permitan el tráfico en los puertos de comunicación necesarios entre los servidores.

  • Se requiere un nombre de dominio registrado con un registro ICP completado. Para obtener más información, consulte Register an Alibaba Cloud domain name y ICP filing.

Procedimiento

Paso 1: Desplegar servicios

Debe desplegar Redis en su instancia ECS03 y la aplicación WebSocket en sus instancias ECS01 y ECS02.

Este tema utiliza una sala de chat en línea sencilla basada en Python sobre CentOS 7.9 con fines demostrativos. Este ejemplo es solo de referencia. En un entorno de producción, utilice su propia aplicación.

Desplegar Redis en ECS03

  1. Inicie sesión en la instancia ECS03.

  2. Copie y ejecute los siguientes comandos para instalar y configurar Redis.

    # Install EPEL (Extra Packages for Enterprise Linux)
    sudo yum install epel-release -y
    # Install Redis
    sudo yum install redis -y
    # Start and enable the Redis service
    sudo systemctl start redis
    sudo systemctl enable redis
    # Edit the Redis configuration file to allow remote connections
    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
    # Restart the Redis service for the changes to take effect
    sudo systemctl restart redis
    # Check the Redis status
    sudo systemctl status redis
    
  3. Si los comandos se ejecutan sin errores y la salida muestra que el servicio Redis está en estado active (running), el despliegue y la configuración se realizaron correctamente.

    ● redis.service - Redis persistent key-value database
       Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
       Active: active (running) since ...
     Main PID: 12345 (redis-server)
       CGroup: /system.slice/redis.service
               └─12345 /usr/bin/redis-server 0.0.0.0:6379
    

Desplegar WebSocket en ECS01

  1. Inicie sesión en la instancia ECS01.

  2. Ejecute sudo pip3 install flask flask-socketio flask-cors redis para instalar las dependencias.

  3. Ejecute vi ECS01_ws.py y presione la tecla i para entrar en modo de edición.

  4. Copie y pegue el siguiente código:

    Código de ejemplo para el servicio de prueba

    Nota

    En la línea 13, reemplace la dirección IP en redis_url con la dirección IP de su servidor Redis (ECS03).

    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!'
    # Enable Cross-Origin Resource Sharing (CORS)
    CORS(app)
    # Configure Redis as the message queue and state store
    redis_url = "redis://192.168.*.*:6379/0"  # Replace with the IP address of your Redis server
    redis_client = redis.StrictRedis.from_url(redis_url)
    # Set the log level to DEBUG for easier debugging
    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  # Get the client's session ID
            print(f"Session {session_id} connected.")
            welcome_message = "You have entered the chat room!"
            emit('message', welcome_message)
            set_session_data(session_id, "username", '')  # Initialize the username as empty
        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} has left the chat room."
                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"Username for client {session_id} set to {username}")
        emit('message', f"Your username has been set to: {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 = "Failed to send message: Please set a username first."
            emit('message', warning_message)
            print(warning_message)
    if __name__ == '__main__':
        # Make sure the templates directory exists
        if not os.path.exists('templates'):
            os.makedirs('templates')
        # Use the Flask template (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>Chat Room</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>Online Chat Room</h1>
        <div class="chat-container">
            <div class="user-container">
                <input type="text" id="username" autocomplete="off" placeholder="Enter a username">
                <button onclick="setUsername()">Set Username</button>
            </div>
            <div id="messages"></div>
            <div class="message-container">
                <input type="text" id="myMessage" autocomplete="off" placeholder="Enter a message...">
                <button onclick="sendMessage()">Send</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;  // Mark that username is set.
                } else {
                    alert("Username cannot be empty!");
                }
            }
            function sendMessage() {
                if (usernameSet) {
                    var message = $('#myMessage').val();
                    if (message) {
                        socket.send(message);
                        $('#myMessage').val('');
                    } else {
                        alert("Message cannot be empty!");
                    }
                } else {
                    alert("Please set a username first!");
                }
            }
        </script>
    </body>
    </html>
    '''
        # Save the template to a file
        with open('templates/index.html', 'w') as file:
            file.write(html_code)
        socketio.run(app, host='0.0.0.0', port=5000)
    
  5. Presione la tecla Esc y luego introduzca :wq para guardar los cambios.

  6. Ejecute el comando sudo python3 ECS01_ws.py para ejecutar el script.

  7. Cuando aparezca la siguiente salida, la aplicación WebSocket se ha iniciado en el puerto 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)
    

    Si la aplicación no se inicia, compruebe si el puerto ya está en uso o si copió los comandos o el código incorrectamente.

● redis.service – Redis persistent key-value database
   Loaded: loaded (/usr/lib/systemd/system/redis.service; enabled; vendor preset: disabled)
  Drop-In: /etc/systemd/redis.service.d
           └─limit.conf
   Active: active (running) since Thu 2xxx xxx xxx xxx CST; 6s ago
  Process: 14715 ExecStop=/usr/libexec/redis-shutdown (code=exited, status=0/SUCCESS)
 Main PID: 14730 (redis-server)
   CGroup: /system.slice/redis.service
           └─14730 /usr/bin/redis-server 0.0.0.0:6379

Desplegar WebSocket en ECS02

  1. Inicie sesión en la instancia ECS02.

  2. Ejecute sudo pip3 install flask flask-socketio flask-cors redis para instalar las dependencias.

  3. Ejecute vi ECS02_ws.py y presione la tecla i para entrar en modo de edición.

  4. Copie y pegue el siguiente código:

    Código de ejemplo para el servicio de prueba

    Nota

    En la línea 13, reemplace la dirección IP en redis_url con la dirección IP de su servidor Redis (ECS03).

    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!'
    # Enable Cross-Origin Resource Sharing (CORS)
    CORS(app)
    # Configure Redis as the message queue and state store
    redis_url = "redis://192.168.*.*:6379/0"  # Replace with the IP address of your Redis server
    redis_client = redis.StrictRedis.from_url(redis_url)
    # Set the log level to DEBUG for easier debugging
    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  # Get the client's session ID
            print(f"Session {session_id} connected.")
            welcome_message = "You have entered the chat room!"
            emit('message', welcome_message)
            set_session_data(session_id, "username", '')  # Initialize the username as empty
        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} has left the chat room."
                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"Username for client {session_id} set to {username}")
        emit('message', f"Your username has been set to: {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 = "Failed to send message: Please set a username first."
            emit('message', warning_message)
            print(warning_message)
    if __name__ == '__main__':
        # Make sure the templates directory exists
        if not os.path.exists('templates'):
            os.makedirs('templates')
        # Use the Flask template (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>Chat Room</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>Online Chat Room</h1>
        <div class="chat-container">
            <div class="user-container">
                <input type="text" id="username" autocomplete="off" placeholder="Enter a username">
                <button onclick="setUsername()">Set Username</button>
            </div>
            <div id="messages"></div>
            <div class="message-container">
                <input type="text" id="myMessage" autocomplete="off" placeholder="Enter a message...">
                <button onclick="sendMessage()">Send</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;  // Mark that username is set.
                } else {
                    alert("Username cannot be empty!");
                }
            }
            function sendMessage() {
                if (usernameSet) {
                    var message = $('#myMessage').val();
                    if (message) {
                        socket.send(message);
                        $('#myMessage').val('');
                    } else {
                        alert("Message cannot be empty!");
                    }
                } else {
                    alert("Please set a username first!");
                }
            }
        </script>
    </body>
    </html>
    '''
        # Save the template to a file
        with open('templates/index.html', 'w') as file:
            file.write(html_code)
        socketio.run(app, host='0.0.0.0', port=5000)
                      
  5. Presione la tecla Esc y luego introduzca :wq para guardar los cambios.

  6. Ejecute el comando sudo python3 ECS02_ws.py para ejecutar el script.

  7. Cuando aparezca la siguiente salida, la aplicación WebSocket se ha iniciado en el puerto 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)
    

    Si la aplicación no se inicia, compruebe si el puerto ya está en uso o si copió los comandos o el código incorrectamente.

Paso 2: Configurar un vServer group

  1. Inicie sesión en la consola de Classic Load Balancer (CLB).

  2. En la barra de navegación superior, seleccione la región donde se despliega la instancia CLB.

  3. En el panel de navegación izquierdo, elija Instances. En la página Instances, busque la instancia objetivo y haga clic en su ID.

  4. En la pestaña vServer groups, haga clic en Create vServer Group. En la página Create vServer Group, configure el siguiente parámetro. Puede usar los valores predeterminados para otros parámetros o modificarlos según sea necesario. Una vez completada la configuración, haga clic en Create y siga las instrucciones en pantalla.

    Parámetro

    Descripción

    vServer Group Name

    Introduzca RS1 como nombre del vServer group.

  5. En la pestaña vServer groups, busque el vServer group que creó y haga clic en Modify en la columna Actions.

  6. En la página Modify vServer Group, haga clic en Add. En la página Servers, agregue los servidores backend ECS01 y ECS02. Establezca el puerto de ambos servidores en 5000, que es el puerto utilizado por la aplicación WebSocket.

  7. En la página Modify vServer Group, seleccione los servidores agregados y haga clic en Save.

Paso 3: Configurar un listener HTTP

  1. Inicie sesión en la consola de Classic Load Balancer (CLB).

  2. En la barra de navegación superior, seleccione la región donde se despliega la instancia CLB.

  3. En el panel de navegación izquierdo, elija Instances.

  4. En la página Instances, busque la instancia objetivo y haga clic en Configure Listener en la columna Actions.

  5. En la página Protocol & Listener, configure los siguientes parámetros. Puede usar los valores predeterminados para otros parámetros o modificarlos según sea necesario. Una vez completada la configuración, haga clic en Next.

    Parámetro

    Descripción

    Select Listener Protocol

    Seleccione HTTP.

    Listener Port

    En este ejemplo, el puerto se establece en 5000.

  6. En la página Backend Servers, configure el siguiente parámetro. Puede usar los valores predeterminados para otros parámetros o modificarlos según sea necesario. Una vez completada la configuración, haga clic en Next.

    Parámetro

    Descripción

    Server Group

    Seleccione el vServer group que creó.

  7. En la página Health Check, puede usar los valores predeterminados para los parámetros o modificarlos según sea necesario. Luego, haga clic en Next.

  8. En la página Confirm, revise la configuración y haga clic en Submit para crear el listener.

Paso 4: Configurar la resolución DNS

Nota
  • Para dominios no registrados en Alibaba Cloud, primero debe add the domain to the Alibaba Cloud DNS console antes de poder configurar registros DNS.

  • Si su instancia CLB es interna, primero debe asociarle una dirección Elastic IP (EIP) y luego crear un registro A que asigne el nombre de dominio a la EIP para habilitar el acceso público.

  1. En el panel de navegación izquierdo, elija CLB > Instances.

  2. En la página Instances, seleccione la instancia objetivo y copie su IP Address.

  3. Realice los siguientes pasos para agregar un registro A:

    1. Inicie sesión en la consola de Alibaba Cloud DNS.

    2. En la página Public Zone, busque el nombre de dominio objetivo y haga clic en Settings en la columna Actions.

    3. En la página Settings, haga clic en Add Record.

    4. En el panel Add Record, configure los siguientes parámetros. Puede dejar otros parámetros con sus valores predeterminados o modificarlos según sea necesario. Luego, haga clic en OK.

      Parámetro

      Descripción

      Record Type

      Seleccione A en la lista desplegable.

      Hostname

      El prefijo de su nombre de dominio.

      Nota

      Para un dominio raíz, establezca el hostname en @.

      Record Value

      Introduzca la dirección IP copiada de la instancia CLB.

Paso 5: Verificar el resultado

Prepare dos computadoras con direcciones IP públicas diferentes. En cada computadora, use un navegador para enviar y ver mensajes de chat, con el fin de verificar que CLB entrega mensajes en tiempo real a través de WebSocket.

  1. En un navegador, vaya a http://<your-domain-name>:5000 para acceder a la aplicación de sala de chat en línea.

    Se carga la interfaz Online Chat Room. El mensaje "You have entered the chat room!" aparece en el área de mensajes del chat, lo que indica que la conexión WebSocket se estableció correctamente. La página contiene un área de configuración de nombre de usuario con un botón Set Username y un área de envío de mensajes con un botón Send.

    Si abre las herramientas de desarrollador de su navegador, la pestaña Network muestra que el navegador se comunica mediante el protocolo WebSocket.

    En el panel Network, establezca el filtro en websocket. Una solicitud WebSocket con código de estado 101 indica que la actualización de protocolo fue exitosa. El estado de la conexión es Pending, lo que significa que la conexión persistente de WebSocket está establecida y activa.

  2. Introduzca un nombre de usuario para el chat y haga clic en Set Username.

  3. En cada computadora, introduzca varios mensajes de chat y haga clic en Send para probar la aplicación.

    Ambos navegadores reciben los mensajes en tiempo real.

    La aplicación Online Chat Room se desplegó correctamente. La página contiene un cuadro de entrada Username y un botón Set Username, un área de visualización de mensajes de chat y un cuadro de entrada de mensajes con un botón Send en la parte inferior. Varios usuarios, como User1 y User2, pueden mantener una conversación en tiempo real en la sala de chat.

  4. Esto verifica que el uso de CLB con WebSocket permite mensajería en tiempo real y de alta disponibilidad.

Configuración de WebSocket para listeners TCP

Los listeners TCP realizan únicamente reenvío de capa 4 (capa de transporte). CLB reenvía las conexiones TCP directamente a los servidores backend sin participar en el procesamiento de protocolos de capa 7 (capa de aplicación). CLB no proporciona actualización integrada del protocolo WebSocket para listeners TCP. Los servicios backend deben implementar el saludo HTTP Upgrade para completar la actualización del protocolo WebSocket.

Nota

Esto difiere de los listeners HTTP y HTTPS. Los listeners HTTP admiten el protocolo WebSocket (WS) de forma predeterminada, y los listeners HTTPS admiten el protocolo WebSocket Secure (WSS) también de forma predeterminada. No se requiere configuración adicional para estos tipos de listeners.

Pasos de configuración

Para usar un servicio WebSocket con un listener TCP:

  1. Inicie sesión en la consola de Classic Load Balancer (CLB). Busque la instancia CLB objetivo y haga clic en Configure Listener en la columna Actions. Establezca el protocolo frontend en TCP y especifique el puerto de escucha.

  2. Despliegue el servicio WebSocket en los servidores backend. El servicio backend debe implementar el saludo HTTP Upgrade para completar la actualización del protocolo WebSocket. CLB reenvía los flujos TCP tal cual y no procesa protocolos de capa 7.

  3. CLB reenvía todas las conexiones TCP entrantes directamente a los servidores backend. El servidor backend gestiona el saludo WebSocket y mantiene la conexión persistente de WebSocket.

Comparación: listeners TCP vs. listeners HTTP y HTTPS

Tipo de listener

Soporte de WebSocket

Configuración requerida

Listener HTTP

Admite WebSocket (WS) de forma predeterminada

No se requiere configuración adicional

Listener HTTPS

Admite WebSocket Secure (WSS) de forma predeterminada

No se requiere configuración adicional

Listener TCP

Sin soporte integrado para WebSocket

El backend debe implementar el saludo HTTP Upgrade

Casos de uso

  • Listener HTTP o HTTPS: recomendado para aplicaciones web estándar que utilizan el protocolo WebSocket. CLB gestiona la actualización de protocolo automáticamente, lo que simplifica la configuración.

  • Listener TCP: adecuado para escenarios que requieren manejo personalizado de protocolos en la capa de aplicación, o cuando un solo listener debe admitir múltiples protocolos de capa de aplicación simultáneamente.

Preguntas frecuentes

¿Cómo uso el protocolo WebSocket Secure?

WebSocket Secure es la versión cifrada del protocolo WebSocket.

Los listeners HTTPS admiten el protocolo WebSocket Secure de forma predeterminada. Para usar el protocolo WebSocket Secure, seleccione HTTPS al configurar el listener.

¿Hay algún costo por usar WebSocket?

No hay cargos adicionales por usar los protocolos WebSocket y WebSocket Secure.

¿Qué regiones admiten WebSocket?

Todas las regiones que admiten CLB también admiten WebSocket y WebSocket Secure.

Referencias

Este tutorial demuestra el despliegue de Redis en una instancia ECS con fines de prueba. Sin embargo, un único servidor Redis representa un posible punto único de falla. Para entornos de producción, se recomienda utilizar Tair para garantizar alta disponibilidad. Para obtener más información, consulte Quick start for Tair.