Todos os produtos
Search
Central de documentação

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

Última atualização: Jul 24, 2026

O WebSocket é um protocolo de rede que fornece um canal de comunicação full-duplex sobre uma única conexão TCP. Ele permite uma conexão persistente entre cliente e servidor, possibilitando que ambos enviem e recebam dados proativamente. Esse design reduz a sobrecarga e a latência associadas ao estabelecimento frequente de novas conexões, tornando-o mais eficiente que o modelo tradicional de requisição-resposta HTTP. O WebSocket é usado principalmente em aplicações que exigem comunicação em tempo real. O Classic Load Balancer (CLB) suporta o protocolo WebSocket por padrão.

Introdução ao WebSocket

Por que usar o WebSocket

Com a evolução das tecnologias web, as aplicações exigem cada vez mais que os servidores enviem dados em tempo real para funcionalidades como salas de bate-papo ao vivo e comentários instantâneos. O método tradicional de polling, no qual o navegador do cliente envia repetidamente requisições HTTP ao servidor para buscar os dados mais recentes, apresenta desvantagens significativas. Requisições frequentes com cabeçalhos HTTP grandes e cargas úteis de dados pequenas aumentam a carga do servidor e desperdiçam largura de banda.

Para resolver esses problemas, o HTML5 introduziu o protocolo WebSocket, que oferece uma solução mais eficiente para a comunicação entre cliente e servidor. O WebSocket suporta comunicação full-duplex, o que significa que servidor e cliente podem enviar e receber dados simultaneamente. Isso permite que o servidor envie novos dados proativamente ao cliente sem esperar por uma requisição de polling. Esse mecanismo de comunicação bidirecional e em tempo real melhora a eficiência da transferência de dados, reduz requisições de rede desnecessárias e economiza recursos do servidor e largura de banda, proporcionando uma experiência de usuário mais fluida e responsiva.

Principais recursos do WebSocket

A comunicação começa com um handshake TCP padrão de três vias. Em seguida, o cliente envia uma requisição HTTP especial, conhecida como handshake de upgrade de protocolo. Após a conclusão bem-sucedida desse handshake, a conexão muda de HTTP para WebSocket. Toda a comunicação subsequente entre cliente e servidor utiliza o protocolo WebSocket, permitindo a troca bidirecional de dados pela mesma conexão.

Uma vez estabelecida, a conexão WebSocket permanece ativa. Essa conexão persistente e de baixa latência permite a transferência contínua e bidirecional de dados, o que aumenta a eficiência da troca de informações.

image

O WebSocket comunica-se usando frames de dados, que possuem seu próprio formato de protocolo de frame com cabeçalhos concisos. Os dados podem ser transmitidos como texto ou binário. Esse método reduz a sobrecarga do protocolo em conexões persistentes, tornando a interação de rede mais eficiente. Ele economiza recursos do servidor e largura de banda, ao mesmo tempo que proporciona uma experiência interativa em tempo real mais fluida.

Para obter mais informações sobre o protocolo WebSocket, consulte a documentação oficial The WebSocket Protocol.

Casos de uso do WebSocket

O WebSocket é ideal para aplicações que exigem comunicação bidirecional rápida e em tempo real, como aplicações de IA, salas de bate-papo online, sistemas de notificação em tempo real, jogos online multiplayer e feeds de dados de mercado em tempo real.

Cenário de exemplo

Uma empresa deseja implantar uma aplicação web de bate-papo online na Alibaba Cloud. Os usuários acessam o service de backend por meio de um nome de domínio para comunicação em tempo real. Por ser uma aplicação de mensagens instantâneas, ela requer baixa latência e comunicação bidirecional eficiente e em tempo real.

O service de site da empresa enfrenta desafios relacionados a alta concorrência e gerenciamento de conexões persistentes. À medida que o número de usuários cresce, o modelo HTTP tradicional não consegue suportar muitos usuários simultâneos na comunicação em tempo real, pois cada interação exige uma nova conexão. Isso leva a um aumento abrupto na carga do servidor e a um desempenho insatisfatório.

Nesse cenário, o uso do CLB com o protocolo WebSocket gerencia eficazmente as conexões persistentes sob alta concorrência. Ao implantar a aplicação WebSocket em vários servidores de backend em um grupo vServer e usar o Redis para sincronização de mensagens, o service alcança alta disponibilidade. Isso fornece uma solução de mensagens em tempo real confiável e eficiente para a aplicação de bate-papo online.

image

Observações de uso

Os listeners HTTP no CLB suportam o protocolo WebSocket por padrão. O CLB suporta atualizações a quente, o que significa que alterações de configuração não afetam as conexões persistentes existentes.

Observe os seguintes pontos:

  • Se a conexão entre o CLB e os servidores de backend usar uma versão específica do HTTP, como HTTP/1.1, utilize um servidor web que suporte a mesma versão HTTP nos servidores de backend.

  • O tempo limite padrão para requisição de conexão de um listener HTTP é de 60 segundos. Caso nenhuma mensagem seja trocada entre o CLB e um servidor de backend por mais de 60 segundos, o CLB encerra a conexão proativamente.

    • Se o tempo limite padrão de 60 segundos for insuficiente para suas necessidades, modifique o Connection Request Timeout do listener.

    • Para manter a conexão aberta, implemente um mecanismo de keepalive para trocar pacotes pelo menos uma vez a cada 60 segundos.

  • Os listeners HTTP no CLB suportam o protocolo WebSocket por padrão, e os listeners HTTPS suportam o protocolo WebSocket Secure (WSS) por padrão. Nenhuma configuração adicional é necessária.

  • Ao usar listeners TCP, o CLB não fornece suporte integrado ao WebSocket. Configure o WebSocket nos servidores de backend. Os itens de configuração para listeners TCP (algoritmo de agendamento, persistência de sessão, limitação de largura de banda e tempo limite de conexão) não incluem opções relacionadas ao WebSocket.

  • Ao configurar uma porta de escuta, evite portas vulneráveis, como as portas 25, 135, 139, 444, 445, 5800 e 5900. Essa restrição é imposta pelas redes dos provedores de internet (ISP), não pelo CLB. O console do CLB não bloqueia a configuração dessas portas, mas algumas redes de ISP bloqueiam o tráfego nelas.

Pré-requisitos

  • Você já criou uma instância do Classic Load Balancer (CLB).

  • São necessárias três instâncias ECS: ECS01, ECS02 e ECS03.

    • As instâncias ECS01 e ECS02 são usadas para implantar a aplicação WebSocket, e a ECS03 é usada para implantar o Redis.

    • Neste tutorial, todos os servidores executam o CentOS 7.9.

    • Recomendamos colocar as instâncias ECS01, ECS02 e ECS03 no mesmo grupo de segurança. Se elas estiverem em grupos de segurança diferentes, configure regras que permitam o tráfego nas portas de comunicação necessárias entre os servidores.

  • É necessário um nome de domínio registrado com registro ICP concluído. Para obter mais informações, consulte Registrar um nome de domínio na Alibaba Cloud e Registro ICP.

Procedimento

Etapa 1: Implantar services

Implante o Redis na instância ECS03 e a aplicação WebSocket nas instâncias ECS01 e ECS02.

Este tópico usa uma sala de bate-papo online simples baseada em Python no CentOS 7.9 para fins de demonstração. Este exemplo serve apenas como referência. Em um ambiente de produção, use sua própria aplicação.

Implantar o Redis na ECS03

  1. Faça logon na instância ECS03.

  2. Copie e execute os comandos a seguir para instalar e configurar o 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. Se os comandos forem executados sem erros e a saída mostrar que o service do Redis está no estado active (running), a implantação e a configuração foram bem-sucedidas.

    ● 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
    

Implantar o WebSocket na ECS01

  1. Faça logon na instância ECS01.

  2. Execute sudo pip3 install flask flask-socketio flask-cors redis para instalar as dependências.

  3. Execute vi ECS01_ws.py e pressione a tecla i para entrar no modo de edição.

  4. Copie e cole o código a seguir:

    Código de exemplo para o service de teste

    Nota

    Na linha 13, substitua o endereço IP em redis_url pelo endereço IP do seu 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. Pressione a tecla Esc e insira :wq para salvar as alterações.

  6. Execute o comando sudo python3 ECS01_ws.py para iniciar o script.

  7. Quando a seguinte saída for exibida, a aplicação WebSocket terá iniciado na porta 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)
    

    Se a aplicação falhar ao iniciar, verifique se a porta já está em uso ou se você copiou os comandos ou o código incorretamente.

● 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

Implantar o WebSocket na ECS02

  1. Faça logon na instância ECS02.

  2. Execute sudo pip3 install flask flask-socketio flask-cors redis para instalar as dependências.

  3. Execute vi ECS02_ws.py e pressione a tecla i para entrar no modo de edição.

  4. Copie e cole o código a seguir:

    Código de exemplo para o service de teste

    Nota

    Na linha 13, substitua o endereço IP em redis_url pelo endereço IP do seu 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. Pressione a tecla Esc e insira :wq para salvar as alterações.

  6. Execute o comando sudo python3 ECS02_ws.py para iniciar o script.

  7. Quando a seguinte saída for exibida, a aplicação WebSocket terá iniciado na porta 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)
    

    Se a aplicação falhar ao iniciar, verifique se a porta já está em uso ou se você copiou os comandos ou o código incorretamente.

Etapa 2: Configurar um grupo vServer

  1. Faça logon no console do Classic Load Balancer (CLB).

  2. Na barra de navegação superior, selecione a região onde a instância CLB está implantada.

  3. No painel de navegação à esquerda, escolha Instances. Na página Instances, localize a instância de destino e clique em seu ID.

  4. Na aba vServer groups, clique em Create vServer Group. Na página Create vServer Group, configure o parâmetro a seguir. Utilize os valores padrão para os outros parâmetros ou modifique-os conforme necessário. Após concluir a configuração, clique em Create e siga as instruções na tela.

    Parâmetro

    Descrição

    vServer Group Name

    Insira RS1 como o nome do grupo vServer.

  5. Na aba vServer groups, localize o grupo vServer criado e clique em Modify na coluna Actions.

  6. Na página Modify vServer Group, clique em Add. Na página Servers, adicione os servidores de backend ECS01 e ECS02. Defina a porta de ambos os servidores como 5000, que é a porta utilizada pela aplicação WebSocket.

  7. Na página Modify vServer Group, selecione os servidores adicionados e clique em Save.

Etapa 3: Configurar um listener HTTP

  1. Faça logon no console do Classic Load Balancer (CLB).

  2. Na barra de navegação superior, selecione a região onde a instância CLB está implantada.

  3. No painel de navegação à esquerda, escolha Instances.

  4. Na página Instances, localize a instância de destino e clique em Configure Listener na coluna Actions.

  5. Na página Protocol & Listener, configure os parâmetros a seguir. Utilize os valores padrão para os outros parâmetros ou modifique-os conforme necessário. Após concluir a configuração, clique em Next.

    Parâmetro

    Descrição

    Select Listener Protocol

    Selecione HTTP.

    Listener Port

    Neste exemplo, a porta está definida como 5000.

  6. Na página Backend Servers, configure o parâmetro a seguir. Utilize os valores padrão para os outros parâmetros ou modifique-os conforme necessário. Após concluir a configuração, clique em Next.

    Parâmetro

    Descrição

    Server Group

    Selecione o grupo vServer que você criou.

  7. Na página Health Check, utilize os valores padrão para os parâmetros ou modifique-os conforme necessário. Em seguida, clique em Next.

  8. Na página Confirm, revise a configuração e clique em Submit para criar o listener.

Etapa 4: Configurar a resolução DNS

Nota
  • Para domínios não registrados na Alibaba Cloud, é necessário primeiro adicionar o domínio ao console do Alibaba Cloud DNS antes de configurar os registros DNS.

  • Se sua instância CLB for voltada para a rede interna, associe primeiro um endereço Elastic IP (EIP) a ela e crie um registro A que mapeie o nome de domínio para o EIP para habilitar o acesso público.

  1. No painel de navegação à esquerda, escolha CLB > Instances.

  2. Na página Instances, selecione a instância de destino e copie seu IP Address.

  3. Siga as etapas abaixo para adicionar um registro A:

    1. Faça logon no console do Alibaba Cloud DNS.

    2. Na página Public Zone, localize o nome de domínio de destino e clique em Settings na coluna Actions.

    3. Na página Settings, clique em Add Record.

    4. No painel Add Record, configure os parâmetros a seguir. Mantenha os valores padrão para os outros parâmetros ou modifique-os conforme necessário. Em seguida, clique em OK.

      Parâmetro

      Descrição

      Record Type

      Selecione A na lista suspensa.

      Hostname

      O prefixo do seu nome de domínio.

      Nota

      Para um domínio raiz, defina o hostname como @.

      Record Value

      Insira o endereço IP copiado da instância CLB.

Etapa 5: Verificar o resultado

Prepare dois computadores com endereços IP públicos diferentes. Em cada computador, use um navegador para enviar e visualizar mensagens de bate-papo, a fim de verificar se o CLB entrega mensagens em tempo real via WebSocket.

  1. Em um navegador, acesse http://<your-domain-name>:5000 para abrir a aplicação de sala de bate-papo online.

    A interface Online Chat Room é carregada. A mensagem "You have entered the chat room!" aparece na área de mensagens, indicando que a conexão WebSocket foi estabelecida. A página contém uma área de definição de nome de usuário com um botão Set Username e uma área de envio de mensagens com um botão Send.

    Se você abrir as ferramentas de desenvolvedor do navegador, a aba Network mostrará que o navegador está se comunicando usando o protocolo WebSocket.

    No painel Network, defina o filtro como websocket. Uma requisição WebSocket com código de status 101 indica que o upgrade de protocolo foi bem-sucedido. O status da conexão será Pending, o que significa que a conexão persistente WebSocket está estabelecida e ativa.

  2. Insira um nome de usuário para o bate-papo e clique em Set Username.

  3. Em cada computador, insira várias mensagens de bate-papo e clique em Send para testar a aplicação.

    Ambos os navegadores recebem as mensagens em tempo real.

    A aplicação Online Chat Room foi implantada com sucesso. A página contém uma caixa de entrada Username e um botão Set Username, uma área de exibição de mensagens e uma caixa de entrada de mensagens com um botão Send na parte inferior. Vários usuários, como User1 e User2, podem conversar em tempo real na sala de bate-papo.

  4. Isso confirma que o uso do CLB com WebSocket possibilita mensagens em tempo real e com alta disponibilidade.

Configuração de WebSocket para listeners TCP

Os listeners TCP realizam apenas encaminhamento de Camada 4 (camada de transporte). O CLB encaminha conexões TCP diretamente para os servidores de backend sem participar do processamento de protocolo da Camada 7 (camada de aplicação). O CLB não fornece upgrade de protocolo WebSocket integrado para listeners TCP. Os services de backend devem implementar o handshake HTTP Upgrade para concluir o upgrade do protocolo WebSocket.

Nota

Isso difere dos listeners HTTP e HTTPS. Os listeners HTTP suportam o protocolo WebSocket (WS) por padrão, e os listeners HTTPS suportam o protocolo WebSocket Secure (WSS) por padrão. Nenhuma configuração adicional é necessária para esses tipos de listener.

Etapas de configuração

Para usar um service WebSocket com um listener TCP:

  1. Faça logon no console do Classic Load Balancer (CLB). Localize a instância CLB de destino e clique em Configure Listener na coluna Actions. Defina o protocolo de frontend como TCP e especifique a porta de escuta.

  2. Nos servidores de backend, implante o service WebSocket. O service de backend deve implementar o handshake HTTP Upgrade para concluir o upgrade do protocolo WebSocket. O CLB encaminha fluxos TCP tal como estão e não processa protocolos da Camada 7.

  3. O CLB encaminha todas as conexões TCP recebidas diretamente para os servidores de backend. O servidor de backend lida com o handshake WebSocket e mantém a conexão WebSocket persistente.

Comparação: listeners TCP vs. listeners HTTP e HTTPS

Tipo de listener

Suporte a WebSocket

Configuração necessária

Listener HTTP

Suporta WebSocket (WS) por padrão

Nenhuma configuração adicional necessária

Listener HTTPS

Suporta WebSocket Secure (WSS) por padrão

Nenhuma configuração adicional necessária

Listener TCP

Sem suporte integrado a WebSocket

O backend deve implementar o handshake HTTP Upgrade

Casos de uso

  • Listener HTTP ou HTTPS — Recomendado para aplicações web padrão que usam o protocolo WebSocket. O CLB lida com o upgrade de protocolo automaticamente, o que simplifica a configuração.

  • Listener TCP — Adequado para cenários que exigem tratamento personalizado de protocolo na camada de aplicação ou quando um único listener precisa suportar múltiplos protocolos da camada de aplicação simultaneamente.

Perguntas frequentes

Como usar o protocolo WebSocket Secure?

O WebSocket Secure é a versão criptografada do protocolo WebSocket.

Os listeners HTTPS suportam o protocolo WebSocket Secure por padrão. Para usar o protocolo WebSocket Secure, selecione HTTPS ao configurar o listener.

Há cobrança pelo uso do WebSocket?

Não há taxas extras pelo uso dos protocolos WebSocket e WebSocket Secure.

Quais regiões suportam o WebSocket?

Todas as regiões que suportam o CLB também suportam WebSocket e WebSocket Secure.

Referências

Este tutorial demonstra a implantação do Redis em uma instância ECS para testes. No entanto, um único servidor Redis representa um potencial ponto único de falha. Para ambientes de produção, recomendamos o uso de Tair para garantir alta disponibilidade. Para obter mais informações, consulte Início rápido do Tair.