All Products
Search
Document Center

Server Load Balancer:Gunakan CLB dan WebSocket untuk pengiriman pesan real-time

Last Updated:Jul 25, 2026

WebSocket adalah protokol jaringan yang menyediakan saluran komunikasi full-duplex melalui satu koneksi TCP. Protokol ini memungkinkan koneksi persisten antara klien dan server, sehingga keduanya dapat secara proaktif mengirim dan menerima data. Desain ini mengurangi overhead dan latensi akibat seringnya pembentukan koneksi baru, sehingga lebih efisien dibandingkan model permintaan-respons HTTP tradisional. WebSocket terutama digunakan untuk aplikasi yang memerlukan komunikasi real-time. Classic Load Balancer (CLB) mendukung protokol WebSocket secara default.

Pengenalan WebSocket

Mengapa menggunakan WebSocket

Seiring perkembangan teknologi web, aplikasi semakin membutuhkan kemampuan server untuk mendorong data secara real-time, seperti pada fitur ruang obrolan langsung dan komentar real-time. Metode polling tradisional—di mana browser klien berulang kali mengirim permintaan HTTP ke server untuk mengambil data terbaru—memiliki kelemahan signifikan. Permintaan yang sering dengan header HTTP besar namun muatan data kecil meningkatkan beban server dan membuang bandwidth.

Untuk mengatasi masalah tersebut, HTML5 memperkenalkan protokol WebSocket sebagai solusi yang lebih efisien untuk komunikasi klien-server. WebSocket mendukung komunikasi full-duplex, artinya server dan klien dapat mengirim serta menerima data secara simultan. Hal ini memungkinkan server untuk secara proaktif mendorong data baru ke klien tanpa menunggu permintaan polling. Mekanisme komunikasi bi-directional dan real-time ini meningkatkan efisiensi transfer data, mengurangi permintaan jaringan yang tidak perlu, serta menghemat sumber daya server dan bandwidth, sehingga memberikan pengalaman pengguna yang lebih lancar dan responsif.

Fitur utama WebSocket

Komunikasi dimulai dengan handshake TCP tiga arah standar. Klien kemudian mengirim permintaan HTTP khusus, yang dikenal sebagai handshake upgrade protokol. Setelah handshake ini berhasil, koneksi beralih dari HTTP ke WebSocket. Seluruh komunikasi selanjutnya antara klien dan server menggunakan protokol WebSocket, memungkinkan pertukaran data bi-directional melalui koneksi yang sama.

Setelah koneksi WebSocket terbentuk, koneksi tersebut tetap aktif. Koneksi persisten berlatensi rendah ini memungkinkan transfer data berkelanjutan secara bi-directional, sehingga meningkatkan efisiensi pertukaran data.

WebSocket berkomunikasi menggunakan frame data, yang memiliki format protokol frame sendiri dengan header ringkas. Data dapat dikirim dalam bentuk teks atau biner. Metode ini mengurangi overhead protokol pada koneksi persisten, sehingga interaksi jaringan menjadi lebih efisien. Hal ini menghemat sumber daya server dan bandwidth sekaligus memberikan pengalaman interaktif real-time yang lebih lancar.

Untuk informasi lebih lanjut tentang protokol WebSocket, lihat dokumentasi resmi The WebSocket Protocol.

WebSocket use cases

WebSocket ideal untuk aplikasi yang memerlukan komunikasi bi-directional real-time yang cepat, seperti aplikasi AI, ruang obrolan online, sistem notifikasi real-time, game multipemain online, dan feed data pasar real-time.

Contoh skenario

Sebuah perusahaan ingin menerapkan aplikasi obrolan online berbasis web di Alibaba Cloud. Pengguna dapat mengakses layanan backend melalui nama domain untuk berkomunikasi secara real-time. Sebagai aplikasi pesan instan, aplikasi ini memerlukan latensi rendah serta komunikasi bi-directional real-time yang efisien.

Layanan situs web perusahaan menghadapi tantangan konkurensi tinggi dan manajemen koneksi persisten. Seiring bertambahnya jumlah pengguna, model HTTP tradisional tidak mampu mendukung banyak pengguna konkuren dalam komunikasi real-time karena setiap interaksi memerlukan koneksi baru. Hal ini menyebabkan lonjakan beban server dan performa yang buruk.

Dalam skenario ini, penggunaan CLB dengan protokol WebSocket secara efektif mengelola koneksi persisten dalam kondisi konkurensi tinggi. Dengan menerapkan aplikasi WebSocket pada beberapa server backend dalam kelompok vServer dan menggunakan Redis untuk sinkronisasi pesan, layanan ini mencapai ketersediaan tinggi. Solusi ini memberikan layanan pengiriman pesan real-time yang andal dan efisien untuk aplikasi obrolan online.

Catatan penggunaan

Pendengar HTTP pada CLB mendukung protokol WebSocket secara default. CLB mendukung pembaruan panas (hot updates), artinya perubahan konfigurasi tidak memengaruhi koneksi persisten yang sedang berjalan.

Perhatikan hal-hal berikut:

  • Jika koneksi antara CLB dan server backend menggunakan versi HTTP tertentu, seperti HTTP/1.1, pastikan server backend menggunakan web server yang mendukung versi HTTP yang sama.

  • Timeout permintaan koneksi default untuk pendengar HTTP adalah 60 detik. Jika tidak ada pertukaran pesan antara CLB dan server backend selama lebih dari 60 detik, CLB akan secara proaktif menutup koneksi tersebut.

    • Jika timeout default 60 detik tidak mencukupi kebutuhan Anda, Anda dapat mengubah Connection Request Timeout pada pendengar.

    • Untuk menjaga koneksi tetap terbuka, Anda harus menerapkan mekanisme keepalive agar paket dipertukarkan minimal sekali setiap 60 detik.

  • Pendengar HTTP pada CLB mendukung protokol WebSocket secara default, dan pendengar HTTPS mendukung protokol WebSocket Secure (WSS) secara default. Tidak diperlukan konfigurasi tambahan.

  • Saat Anda menggunakan pendengar TCP, CLB tidak menyediakan dukungan WebSocket bawaan. Anda harus mengonfigurasi WebSocket pada server backend. Item konfigurasi untuk pendengar TCP (algoritma penjadwalan, persistensi sesi, pembatasan bandwidth, dan timeout koneksi) tidak mencakup opsi terkait WebSocket.

  • Saat mengonfigurasi port pendengar, hindari port yang rentan seperti port 25, 135, 139, 444, 445, 5800, dan 5900. Pembatasan ini diterapkan oleh jaringan ISP, bukan oleh CLB. Konsol CLB tidak memblokir konfigurasi port-port tersebut, tetapi beberapa jaringan ISP memblokir trafik pada port-port tersebut.

Prasyarat

  • Anda telah membuat instance Classic Load Balancer (CLB).

  • Diperlukan tiga instance ECS: ECS01, ECS02, dan ECS03.

    • ECS01 dan ECS02 digunakan untuk menerapkan aplikasi WebSocket, sedangkan ECS03 digunakan untuk menerapkan Redis.

    • Dalam tutorial ini, semua server menjalankan CentOS 7.9.

    • Kami merekomendasikan agar Anda menempatkan ECS01, ECS02, dan ECS03 dalam grup keamanan yang sama. Jika berada dalam grup keamanan berbeda, pastikan Anda mengonfigurasi aturan yang mengizinkan trafik pada port komunikasi yang diperlukan antar server.

  • Diperlukan nama domain terdaftar dengan Pendaftaran ICP yang telah selesai. Untuk informasi lebih lanjut, lihat Daftarkan nama domain Alibaba Cloud dan Pendaftaran ICP.

Prosedur

Langkah 1: Terapkan layanan

Anda perlu menerapkan Redis pada instance ECS03 dan aplikasi WebSocket pada instance ECS01 serta ECS02.

Topik ini menggunakan ruang obrolan online sederhana berbasis Python pada CentOS 7.9 untuk tujuan demonstrasi. Contoh ini hanya sebagai referensi. Di lingkungan produksi, gunakan aplikasi Anda sendiri.

Terapkan Redis pada ECS03

  1. Login ke instance ECS03.

  2. Salin dan jalankan perintah berikut untuk menginstal dan mengonfigurasi 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. Jika perintah dijalankan tanpa error dan output menunjukkan layanan Redis berada dalam status active (running), maka penerapan dan konfigurasi berhasil.

    ● 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
    

Terapkan WebSocket pada ECS01

  1. Login ke instance ECS01.

  2. Jalankan sudo pip3 install flask flask-socketio flask-cors redis untuk menginstal dependensi.

  3. Jalankan vi ECS01_ws.py dan tekan tombol i untuk memasuki mode edit.

  4. Salin dan tempel kode berikut:

    Kode contoh untuk layanan uji coba

    Catatan

    Pada baris 13, ganti alamat IP dalam redis_url dengan alamat IP server Redis Anda (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. Tekan tombol Esc, lalu masukkan :wq untuk menyimpan perubahan.

  6. Jalankan perintah sudo python3 ECS01_ws.py untuk menjalankan skrip.

  7. Saat output berikut ditampilkan, aplikasi WebSocket telah berjalan pada port 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)
    

    Jika aplikasi gagal berjalan, periksa apakah port tersebut sedang digunakan atau apakah Anda salah menyalin perintah atau kode.

● 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

Terapkan WebSocket pada ECS02

  1. Login ke instance ECS02.

  2. Jalankan sudo pip3 install flask flask-socketio flask-cors redis untuk menginstal dependensi.

  3. Jalankan vi ECS02_ws.py dan tekan tombol i untuk memasuki mode edit.

  4. Salin dan tempel kode berikut:

    Kode contoh untuk layanan uji coba

    Catatan

    Pada baris 13, ganti alamat IP dalam redis_url dengan alamat IP server Redis Anda (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. Tekan tombol Esc, lalu masukkan :wq untuk menyimpan perubahan.

  6. Jalankan perintah sudo python3 ECS02_ws.py untuk menjalankan skrip.

  7. Saat output berikut ditampilkan, aplikasi WebSocket telah berjalan pada port 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)
    

    Jika aplikasi gagal berjalan, periksa apakah port tersebut sedang digunakan atau apakah Anda salah menyalin perintah atau kode.

Langkah 2: Konfigurasi kelompok vServer

  1. Login ke Konsol Classic Load Balancer (CLB).

  2. Pada bilah navigasi atas, pilih wilayah tempat instance CLB diterapkan.

  3. Pada panel navigasi kiri, pilih Instances. Pada halaman Instances, temukan instance target dan klik ID-nya.

  4. Pada tab vServer groups, klik Create vServer Group. Pada halaman Create vServer Group, konfigurasikan parameter berikut. Anda dapat menggunakan nilai default untuk parameter lain atau mengubahnya sesuai kebutuhan. Setelah selesai mengonfigurasi, klik Create dan ikuti petunjuk di layar.

    Parameter

    Description

    vServer Group Name

    Masukkan RS1 sebagai nama kelompok vServer.

  5. Pada tab vServer groups, temukan kelompok vServer yang telah Anda buat dan klik Modify pada kolom Actions.

  6. Pada halaman Modify vServer Group, klik Add. Pada halaman Servers, tambahkan server backend ECS01 dan ECS02. Atur port kedua server ke 5000, yaitu port yang digunakan oleh aplikasi WebSocket.

  7. Pada halaman Modify vServer Group, pilih server yang telah ditambahkan dan klik Save.

Langkah 3: Konfigurasi pendengar HTTP

  1. Login ke Konsol Classic Load Balancer (CLB).

  2. Pada bilah navigasi atas, pilih wilayah tempat instance CLB diterapkan.

  3. Pada panel navigasi kiri, pilih Instances.

  4. Pada halaman Instances, temukan instance target dan klik Configure Listener pada kolom Actions.

  5. Pada halaman Protocol & Listener, konfigurasikan parameter berikut. Anda dapat menggunakan nilai default untuk parameter lain atau mengubahnya sesuai kebutuhan. Setelah selesai mengonfigurasi, klik Next.

    Parameter

    Description

    Select Listener Protocol

    Pilih HTTP.

    Listener Port

    Dalam contoh ini, port diatur ke 5000.

  6. Pada halaman Backend Servers, konfigurasikan parameter berikut. Anda dapat menggunakan nilai default untuk parameter lain atau mengubahnya sesuai kebutuhan. Setelah selesai mengonfigurasi, klik Next.

    Parameter

    Description

    Server Group

    Pilih kelompok vServer yang telah Anda buat.

  7. Pada halaman Health Check, Anda dapat menggunakan nilai default untuk parameter atau mengubahnya sesuai kebutuhan. Lalu, klik Next.

  8. Pada halaman Confirm, tinjau konfigurasi dan klik Submit untuk membuat pendengar.

Langkah 4: Konfigurasi resolusi DNS

Catatan
  • Untuk domain yang tidak didaftarkan di Alibaba Cloud, Anda harus terlebih dahulu menambahkan domain ke konsol Alibaba Cloud DNS sebelum dapat mengonfigurasi rekaman DNS.

  • Jika instance CLB Anda adalah instance akses internal, Anda harus terlebih dahulu mengaitkan alamat IP elastis (EIP) dengannya, lalu membuat Rekaman A yang memetakan nama domain ke EIP agar dapat diakses publik.

  1. Pada panel navigasi kiri, pilih CLB > Instances.

  2. Pada halaman Instances, pilih instance target dan salin IP Address-nya.

  3. Lakukan langkah-langkah berikut untuk menambahkan Rekaman A:

    1. Login ke Konsol Alibaba Cloud DNS.

    2. Pada halaman Public Zone, temukan nama domain target dan klik Settings pada kolom Actions.

    3. Pada halaman Settings, klik Add Record.

    4. Pada panel Add Record, konfigurasikan parameter berikut. Anda dapat membiarkan parameter lain dengan nilai default atau mengubahnya sesuai kebutuhan. Lalu, klik OK.

      Parameter

      Description

      Record Type

      Pilih A dari daftar drop-down.

      Hostname

      Awalan nama domain Anda.

      Catatan

      Untuk domain root, atur hostname ke @.

      Record Value

      Masukkan alamat IP instance CLB yang telah Anda salin.

Langkah 5: Verifikasi hasil

Siapkan dua komputer dengan alamat IP publik berbeda. Pada masing-masing komputer, gunakan browser untuk mengirim dan melihat pesan obrolan guna memverifikasi bahwa CLB mengirimkan pesan secara real-time melalui WebSocket.

  1. Pada browser, buka http://<your-domain-name>:5000 untuk mengakses aplikasi ruang obrolan online.

    Antarmuka Online Chat Room dimuat. Pesan "You have entered the chat room!" muncul di area pesan obrolan, yang menandakan bahwa koneksi WebSocket telah terbentuk. Halaman berisi area pengaturan username dengan tombol Set Username dan area pengiriman pesan dengan tombol Send.

    Jika Anda membuka developer tools browser Anda, tab Network menunjukkan bahwa browser berkomunikasi menggunakan protokol WebSocket.

    Pada panel Network, atur filter ke websocket. Permintaan WebSocket dengan kode status 101 menandakan bahwa upgrade protokol berhasil. Status koneksi adalah Pending, yang berarti koneksi WebSocket persisten telah terbentuk dan aktif.

  2. Masukkan username untuk obrolan dan klik Set Username.

  3. Pada masing-masing komputer, masukkan beberapa pesan obrolan dan klik Send untuk menguji aplikasi.

    Kedua browser menerima pesan secara real-time.

    Aplikasi Online Chat Room berhasil diterapkan. Halaman berisi kotak input Username dan tombol Set Username, area tampilan pesan obrolan, serta kotak input pesan dengan tombol Send di bagian bawah. Beberapa pengguna, seperti User1 dan User2, dapat melakukan percakapan real-time di ruang obrolan.

  4. Hal ini memverifikasi bahwa penggunaan CLB dengan WebSocket memungkinkan pengiriman pesan real-time dengan ketersediaan tinggi.

Konfigurasi WebSocket untuk pendengar TCP

Pendengar TCP hanya melakukan forwarding Lapisan 4 (lapisan transport). CLB meneruskan koneksi TCP langsung ke server backend tanpa ikut serta dalam pemrosesan protokol Lapisan 7 (lapisan aplikasi). CLB tidak menyediakan upgrade protokol WebSocket bawaan untuk pendengar TCP. Layanan backend harus mengimplementasikan handshake HTTP Upgrade untuk menyelesaikan upgrade protokol WebSocket.

Catatan

Hal ini berbeda dengan pendengar HTTP dan HTTPS. Pendengar HTTP mendukung protokol WebSocket (WS) secara default, dan pendengar HTTPS mendukung protokol WebSocket Secure (WSS) secara default. Tidak diperlukan konfigurasi tambahan untuk jenis pendengar ini.

Langkah konfigurasi

Untuk menggunakan layanan WebSocket dengan pendengar TCP:

  1. Login ke Konsol Classic Load Balancer (CLB). Temukan instance CLB target dan klik Configure Listener pada kolom Actions. Atur protokol frontend ke TCP dan tentukan port pendengar.

  2. Pada server backend, terapkan layanan WebSocket. Layanan backend harus mengimplementasikan handshake HTTP Upgrade untuk menyelesaikan upgrade protokol WebSocket. CLB meneruskan aliran TCP apa adanya dan tidak memproses protokol Lapisan 7.

  3. CLB meneruskan semua koneksi TCP masuk langsung ke server backend. Server backend menangani handshake WebSocket dan mempertahankan koneksi WebSocket persisten.

Perbandingan: Pendengar TCP vs. Pendengar HTTP dan HTTPS

Jenis pendengar

Dukungan WebSocket

Konfigurasi yang diperlukan

HTTP listener

Mendukung WebSocket (WS) secara default

Tidak diperlukan konfigurasi tambahan

HTTPS listener

Mendukung WebSocket Secure (WSS) secara default

Tidak diperlukan konfigurasi tambahan

TCP listener

Tidak ada dukungan WebSocket bawaan

Backend harus mengimplementasikan handshake HTTP Upgrade

Use cases

  • Pendengar HTTP atau HTTPS — Direkomendasikan untuk aplikasi web standar yang menggunakan protokol WebSocket. CLB menangani upgrade protokol secara otomatis, sehingga menyederhanakan konfigurasi.

  • Pendengar TCP — Cocok untuk skenario yang memerlukan penanganan protokol kustom pada lapisan aplikasi, atau ketika satu pendengar harus mendukung beberapa protokol lapisan aplikasi secara bersamaan.

FAQ

Bagaimana cara menggunakan protokol WebSocket Secure?

WebSocket Secure adalah versi terenkripsi dari protokol WebSocket.

Pendengar HTTPS mendukung protokol WebSocket Secure secara default. Untuk menggunakan protokol WebSocket Secure, pilih HTTPS saat mengonfigurasi pendengar.

Apakah ada biaya tambahan untuk menggunakan WebSocket?

Tidak ada biaya tambahan untuk menggunakan protokol WebSocket dan WebSocket Secure.

Wilayah mana saja yang mendukung WebSocket?

Semua wilayah yang mendukung CLB juga mendukung WebSocket dan WebSocket Secure.

Referensi

Tutorial ini menunjukkan penerapan Redis pada instance ECS untuk pengujian. Namun, server Redis tunggal merupakan titik kegagalan potensial. Untuk lingkungan produksi, kami merekomendasikan Anda menggunakan Tair untuk memastikan ketersediaan tinggi. Untuk informasi lebih lanjut, lihat Quick start for Tair.