14 poin oleh GN⁺ 2025-01-09 | 5 komentar | Bagikan ke WhatsApp
  • Dalam backend berbasis Node.js/TypeScript, ada kebutuhan untuk menangani pembaruan real-time dalam skala besar
  • Menggunakan PostgreSQL sebagai backend, ratusan node worker harus terus memeriksa pekerjaan baru, dan agent perlu menerima pembaruan status eksekusi serta chat
  • Awalnya dimulai dengan mengeksplorasi WebSocket, tetapi berakhir pada solusi 'jadul' yang ternyata sangat efektif
    → "HTTP Long Polling dengan Postgres"

Situasi masalah: pembaruan real-time dalam skala besar

  • Pembaruan node worker :
    • Ada ratusan node worker yang menjalankan SDK Node.js/Golang/C#
    • Mereka harus mengetahui segera setelah pekerjaan baru tersedia, sehingga dibutuhkan strategi query yang tidak menjatuhkan database Postgres
  • Sinkronisasi status agent :
    • Agent membutuhkan pembaruan real-time untuk status eksekusi dan chat, dan ini harus di-stream dengan efisien

Perbandingan Long Polling dan WebSocket

  • Short polling seperti kereta yang berangkat ketat sesuai jadwal, sehingga tetap berangkat pada interval tetap terlepas ada penumpang atau tidak
  • Long polling membuat server menunggu sebelum merespons, lalu segera mengembalikan hasil saat data tersedia, dan akan mengembalikan respons timeout jika waktu tertentu terlewati
    • Dengan kata lain, ini seperti kereta yang “menunggu lalu berangkat saat data muncul”. Hanya jika tidak ada penumpang dalam waktu tertentu (TTL), kereta berangkat dalam keadaan kosong
    • Saat ada data (penumpang), ia langsung berangkat; saat tidak ada, resource dapat digunakan secara efisien — memberi dua keuntungan sekaligus
  • WebSocket mempertahankan koneksi secara terus-menerus untuk bertukar data dua arah
    • Karena lingkungan organisasi, infrastruktur, firewall, dan masalah lainnya, long polling lebih sederhana dan lebih kompatibel daripada menyiapkan WebSocket

Detail implementasi long polling

  • Fungsi getJobStatusSync memegang peran penting
    • Fungsi ini menerima parameter seperti jobId, owner, ttl, lalu berulang kali memeriksa status pekerjaan tertentu selama jangka waktu tertentu
  • Pengecekan berulang dilakukan sampai salah satu kondisi berikut terpenuhi
    • Status pekerjaan menjadi success atau failure
    • ttl (timeout) terlewati
  • Database diperiksa setiap 500ms; jika hasilnya belum final, sistem menunggu lalu memeriksa lagi
  • Jika melebihi timeout, error dilempar; jika berhasil, hasil dikembalikan

Optimasi database

  • Menempatkan indeks yang tepat di Postgres untuk meminimalkan biaya query
  • Contoh: CREATE INDEX idx_jobs_status ON jobs(id, cluster_id);

Keuntungan long polling

  • Kemudahan mempertahankan monitoring : stack logging dan monitoring HTTP yang sudah ada bisa tetap digunakan
  • Kesederhanaan autentikasi : tidak perlu mengimplementasikan metode autentikasi baru, cukup memakai autentikasi HTTP yang sudah ada
  • Kompatibilitas infrastruktur : tidak memerlukan konfigurasi khusus pada firewall atau load balancer, dan diperlakukan sebagai traffic HTTP biasa
  • Kesederhanaan operasional : saat server restart, tidak perlu menangani status koneksi secara terpisah, dan debugging lebih mudah
  • Implementasi klien yang praktis : cukup tambahkan logika retry ke struktur request-response HTTP standar

Perbandingan dengan ElectricSQL

  • ElectricSQL adalah solusi untuk menyinkronkan data Postgres dengan frontend
  • Solusi ini memiliki struktur yang menjamin sifat real-time sambil menggunakan HTTP alih-alih WebSocket
  • Jika untuk menangani pembaruan real-time tidak dibutuhkan kontrol ekstrem atau struktur tingkat rendah, ElectricSQL direkomendasikan

Mengapa kami memilih Raw Long Polling

  • Mekanisme pengiriman pesan bukan sekadar detail implementasi sederhana, melainkan elemen inti produk
  • Fitur inti tidak boleh bergantung pada library pihak ketiga (sehebat apa pun library tersebut)
  • Kebutuhan
    • Kontrol atas produk inti : mekanisme pengiriman pesan harus dikendalikan sepenuhnya. Ini bukan level infrastruktur, melainkan bagian dari produk itu sendiri
    • Menghilangkan dependensi eksternal : meminimalkan dependensi eksternal untuk menyederhanakan self-hosting
    • Kontrol tingkat rendah : mengendalikan sendiri mekanisme polling dan pengelolaan koneksi
    • Kontrol maksimal : detail seperti implementasi interval polling dinamis harus bisa disetel dengan rinci
    • Kesederhanaan kode : dirancang sesederhana mungkin agar pengguna mudah memahami dan memodifikasi codebase
  • Kesimpulannya, dengan memilih implementasi HTTP Long Polling yang sederhana, didapatkan kontrol langsung dan kesederhanaan

Hal-hal yang perlu diperhatikan saat mengimplementasikan long polling

  • Pengaturan TTL : server harus selalu memaksakan TTL maksimum, dan memastikan TTL yang diminta klien tidak melampaui batas itu
  • Mempertimbangkan timeout infrastruktur : TTL harus cukup lebih pendek daripada pengaturan timeout pada load balancer, edge server, proxy, dan sebagainya
  • Interval polling DB : beri delay sekitar 500ms untuk mengurangi beban DB
  • Strategi backoff (opsional) : interval polling dapat dinaikkan secara bertahap agar resource sistem digunakan lebih efisien

Kapan perlu mempertimbangkan WebSocket

  • WebSocket sendiri bukan pilihan yang salah, dan tetap berguna dalam aspek lain
    • Saat perlu memantau banyak koneksi yang stateful, dan terus-menerus bertukar event yang kompleks
    • Saat tersedia cukup resource dan waktu untuk menyelesaikan masalah autentikasi, infrastruktur, dan observabilitas
  • Ada kompleksitas karena harus membangun sendiri hal-hal seperti operasional dan logging, penanganan reconnect, mekanisme autentikasi, dan sebagainya

WebSockets: cerita tentang opsi lain

  • Long Polling cocok untuk kebutuhan kami, tetapi WebSockets juga layak dipertimbangkan sepenuhnya
  • WebSockets sendiri tidak buruk; hanya saja membutuhkan banyak perhatian dan pengelolaan
  • Tantangan utama WebSockets dan arah penyelesaiannya
    • Visibilitas : karena WebSockets bersifat stateful, perlu menambahkan logging dan monitoring untuk koneksi yang persisten
    • Autentikasi : perlu mengimplementasikan mekanisme autentikasi baru untuk koneksi WebSocket
    • Infrastruktur : agar mendukung WebSocket, infrastruktur seperti load balancer dan firewall harus dikonfigurasi dengan benar
    • Manajemen operasional : pengelolaan koneksi dan reconnect WebSocket. Termasuk timeout koneksi dan penanganan error
    • Implementasi klien : implementasi library WebSocket di sisi klien, termasuk fitur reconnect dan manajemen status

5 komentar

 
jhj0517 2025-01-10

Saya memakai struktur "short polling" yang dibahas di sini untuk serving model ML, dan cukup banyak mempertimbangkan mana yang lebih efisien. Dari yang saya cari ke sana kemari, ada pendapat bahwa short polling umumnya lebih aman karena biaya besar untuk menangani reconnect pada WebSocket atau SSE, jadi saya memang memilih short polling.. 😭

 
bbulbum 2025-01-10

Long polling terasa agak hacky, jadi sepertinya orang enggan memakainya. Di browser, kemungkinan akan terus terlihat seolah-olah permintaannya belum selesai. Kadang ada situs yang loading-nya tidak pernah selesai, dan saya jadi berpikir, apakah kontennya belum termuat sepenuhnya? Jadi saya kurang suka. Dalam aplikasi juga pada akhirnya akan ada bagian yang dibuat hang dan menunggu respons, jadi terlihat agak canggung.

 
joyfui 2025-01-09

"Agen perlu menerima pembaruan status eksekusi dan chat"
Begitu melihat ini saya langsung terpikir SSE, dan memang di opini Hacker News juga banyak yang menyebut SSE.

 
GN⁺ 2025-01-09
Komentar Hacker News
  • Long polling punya masalahnya sendiri

    • Second Life menggunakan kanal HTTPS long polling antara klien dan server
    • Di sisi klien menggunakan libcurl, dan timeout bisa terjadi
    • Jika server mencoba mengirim pesan di antara timeout dan permintaan berikutnya, kondisi balapan bisa terjadi sehingga pesan hilang
    • Server Apache berada di depan untuk memblokir permintaan yang tidak perlu, tetapi timeout tetap bisa terjadi
    • Middlebox dan server proxy bisa tidak menyukai long polling
    • Ada banyak komponen yang tidak suka mempertahankan koneksi HTTP tetap terbuka lama
    • Akibatnya, ini menjadi kanal pesan yang tidak andal sehingga nomor urut diperlukan untuk mendeteksi duplikasi dan pesan bisa hilang
    • Bagian diagram yang ditandai sebagai "loop" di artikel asli tidak menyebutkan penanganan timeout
    • Jika menggunakan long polling, data perlu dikirim setiap beberapa detik untuk menjaga koneksi tetap hidup
  • Senang menggunakan Phoenix dan LiveView setiap hari

    • Karena memakai WebSockets, jadi tidak perlu terlalu dipikirkan
  • Penasaran apakah ada keuntungan teknis dibanding menggunakan Server-Sent Events (SSE)

    • Keduanya sama-sama mempertahankan koneksi HTTP tetap terbuka dan punya kelebihan berupa HTTP yang sederhana
    • SSE tampaknya lebih cocok ketika pembaruan atau hasil bisa di-streaming
    • Contoh use case yang cocok mungkin saat memantau semua ID pekerjaan atas nama klien tertentu
  • Artikel ini menghubungkan "Websocket" dan "Long-polling" sebagai keputusan yang berdiri sendiri

    • Server long-polling bisa menangani klien websocket dengan sedikit pekerjaan tambahan
    • Jika arsitektur yang ada sudah berbasis websocket, mendukung klien long-polling memerlukan dua lapisan server
  • Cara yang lebih mudah menggunakan setTimeout di Node.js

    • Gunakan import { setTimeout } from "node:timers/promises"; await setTimeout(500);
  • Suka long polling, mudah dipahami dan dari sudut pandang klien bekerja seperti koneksi yang sangat lambat

    • Tetap perlu menangani retry dan melacak koneksi yang dibatalkan di sisi klien
    • Dalam contoh kode, loop yang berulang kali melakukan query data terlihat canggung
  • Server-Sent Events maupun WebSockets tidak bisa menggantikan semua use case long polling

    • Batas koneksi SSE sering muncul sebagai masalah
    • WebSockets tidak andal di sebagian besar lingkungan
    • Masalah mendeteksi perubahan di backend dan menyebarkannya ke klien yang tepat tetap belum terselesaikan
  • Sebaiknya menggunakan fitur notifikasi asinkron milik Postgres

    • Server bisa LISTEN pada kanal dan PG dapat melakukan TRIGGER serta NOTIFY saat data berubah
  • Tidak yakin apakah long polling masih punya arti dengan timeout singkat dan permintaan yang ditutup secara elegan

    • Jika HTTP/2 atau QUIC tidak digunakan, trik ini mungkin masih masuk akal
  • Menyegarkan untuk diingatkan pada alternatif yang relatif sederhana terhadap WebSockets

    • Pernah bekerja di startup yang memilih WebSockets, dan sulit melakukan pengujian di Wi-Fi hotel dan restoran
 
luminance 2025-01-10

Saya ingin mencoba memakai WebSockets melalui Elixir, framework Phoenix, dan LiveView.