4 poin oleh GN⁺ 2024-03-19 | 1 komentar | Bagikan ke WhatsApp
  • Dalam aplikasi web real-time, pilihan antara Long Polling, WebSockets, SSE, WebRTC, WebTransport untuk pengiriman event server-klien sangat memengaruhi latensi, komunikasi dua arah, tingkat kesulitan implementasi, dan batasan operasional
  • WebSockets menyediakan komunikasi dua arah melalui satu koneksi jangka panjang, tetapi dalam operasi nyata sering dipakai bersama library seperti Socket.IO karena perlu mendeteksi koneksi terputus, melakukan reconnect, dan heartbeat ping-pong
  • Server-Sent Events adalah stream satu arah server→klien berbasis HTTP sehingga implementasi dan penanganan reconnect lebih sederhana, tetapi API EventSource bawaan memiliki batasan untuk mengirim body POST atau header kustom
  • WebTransport mendukung multi-stream serta transmisi andal dan tidak andal berbasis HTTP/3 QUIC, tetapi per Maret 2024 masih berstatus Working Draft dan belum memiliki dukungan native di Safari maupun Node.js, sehingga belum mudah dianggap sebagai pilihan umum
  • Karena penghentian di background pada mobile, batas jumlah koneksi per domain, proxy dan firewall perusahaan, serta event yang terlewat saat reconnect, aplikasi nyata juga membutuhkan logika pemulihan sinkronisasi dan pengujian infrastruktur

Alur teknologi komunikasi server-klien real-time

  • Dalam aplikasi web real-time, kemampuan server mengirim event ke klien menjadi kebutuhan utama
  • Pada awalnya, Long Polling yang berjalan di atas HTTP digunakan sebagai cara messaging server-klien yang memungkinkan di browser
  • Setelah itu, WebSockets muncul sebagai cara yang lebih kokoh untuk komunikasi dua arah
  • Server-Sent Events(SSE) menyediakan komunikasi satu arah dari server ke klien secara lebih sederhana
  • WebTransport berpotensi menjadi cara yang lebih efisien, fleksibel, dan skalabel, tetapi saat ini cakupan dukungannya masih terbatas
  • WebRTC dapat dipertimbangkan untuk sebagian penggunaan niche event server-klien, tetapi tujuannya berbeda sehingga tidak diperlakukan sebagai pilihan utama

Long Polling

  • Long Polling adalah cara meniru komunikasi server push menggunakan request XHR biasa
  • Klien membuka request ke server, lalu server menahan respons sampai ada data baru
  • Setelah informasi baru dikirim, koneksi ditutup, dan klien segera memulai request berikutnya
  • Dibanding polling periodik tradisional, update lebih cepat dan dapat mengurangi traffic jaringan serta beban server yang tidak perlu
  • Namun, efisiensinya lebih rendah dibanding teknologi real-time seperti WebSockets, dan latensi dapat muncul tergantung waktu pengiriman data
  • Implementasi klien sederhana, tetapi di backend sulit menjamin klien yang sedang reconnect tidak melewatkan event

WebSockets

  • WebSockets membuat satu koneksi jangka panjang antara klien dan server serta menyediakan komunikasi full-duplex
  • Setelah koneksi dibuat, kedua pihak dapat mengirim data secara independen tanpa overhead siklus request-response HTTP
  • Cocok untuk aplikasi yang membutuhkan latensi rendah dan update sering, seperti chat real-time, game, dan platform transaksi finansial
  • API WebSocket dasar mudah digunakan, tetapi di production penanganan koneksi terputus dan pembuatan ulang koneksi menjadi rumit
  • Karena sulit mendeteksi apakah koneksi masih dapat digunakan, biasanya ditambahkan heartbeat ping-and-pong
  • Karena kompleksitas ini, dalam banyak kasus digunakan library seperti Socket.IO, dan Socket.IO juga menyediakan fallback Long Polling jika diperlukan

Server-Sent Events

  • Server-Sent Events(SSE) adalah cara standar untuk mendorong update server ke klien di atas HTTP
  • Berbeda dari WebSockets, SSE dirancang hanya untuk komunikasi satu arah server→klien
  • Cocok untuk situasi saat klien tidak perlu mengirim pesan ke server, seperti feed berita live, skor olahraga, dan update real-time
  • SSE dapat dipahami sebagai satu request HTTP yang koneksinya dipertahankan, sementara backend mengalirkan respons baris demi baris setiap kali ada event
  • Di klien browser, stream event diterima dengan menginisialisasi instance EventSource
  • Berbeda dari WebSockets, EventSource otomatis melakukan reconnect jika koneksi terputus
  • Server harus mengatur header Content-Type menjadi text/event-stream dan memformat field seperti tipe event, payload data, ID event, dan retry timing sesuai SSE specification

WebTransport

  • WebTransport adalah API untuk komunikasi efisien dan berlatensi rendah antara klien web dan server
  • Dengan memanfaatkan HTTP/3 QUIC protocol, data dapat dikirim melalui beberapa stream
  • Mendukung transmisi andal dan tidak andal, serta pengiriman data tanpa urutan
  • Dapat menjadi alat kuat untuk aplikasi yang membutuhkan jaringan berkinerja tinggi, seperti game real-time, live streaming, dan platform kolaborasi
  • Per Maret 2024, WebTransport berstatus Working Draft dan belum didukung luas
  • Belum dapat digunakan di Safari browser, dan Node.js juga belum memiliki dukungan native
  • Bahkan jika dukungannya meluas, API-nya sangat kompleks sehingga kemungkinan besar akan digunakan dalam bentuk library yang dibangun di atas WebTransport, bukan langsung di kode aplikasi

WebRTC

  • WebRTC adalah proyek open-source sekaligus standar API yang menyediakan kemampuan komunikasi real-time di dalam browser dan aplikasi mobile tanpa plugin
  • Mendukung koneksi peer-to-peer untuk pertukaran audio, video, dan data antar-browser
  • Menggunakan protokol seperti ICE, STUN, dan TURN untuk melewati NAT dan firewall
  • WebRTC dibuat untuk interaksi klien-ke-klien, tetapi juga dapat dimanfaatkan untuk komunikasi server-klien dengan membuat server bertindak seperti klien
  • Cara seperti ini hanya cocok untuk kasus penggunaan niche, sehingga dikecualikan dari perbandingan pilihan utama
  • Agar WebRTC bekerja, tetap diperlukan server signaling, dan server ini akan berjalan di atas salah satu dari WebSockets, SSE, atau WebTransport
  • Karena itu, tujuan memakai WebRTC sebagai pengganti langsung teknologi-teknologi tersebut menjadi lemah

Batasan utama tiap teknologi

  • Pengiriman data dua arah

    • Cara menerima data server dan mengirim data klien pada koneksi yang sama hanya didukung oleh WebSockets dan WebTransport
    • Long Polling secara teori juga memungkinkan, tetapi tidak disarankan karena untuk mengirim data baru pada koneksi long-polling yang sudah ada diperlukan request HTTP tambahan
    • Pada Long Polling, lebih baik mengirim data klien→server lewat request HTTP terpisah tanpa mengganggu koneksi yang ada
    • SSE tidak mendukung kemampuan mengirim data tambahan ke server
    • EventSource API native bawaan tidak dapat mengirim data seperti POST di HTTP body bahkan pada request awal
    • Data harus dimasukkan ke parameter URL, tetapi credentials dapat bocor ke log server, proxy, dan cache, sehingga kurang baik dari sisi keamanan
    • Untuk menghindari masalah ini, RxDB menggunakan eventsource polyfill, bukan EventSource API native, dan library ini menambahkan kemampuan seperti header HTTP kustom
    • fetch-event-source dari Microsoft mengizinkan pengiriman data body dan penggunaan request POST, bukan GET
  • Batas jumlah koneksi per domain

    • Sebagian besar browser modern mengizinkan 6 koneksi per domain, dan batas ini membatasi kegunaan berbagai cara messaging server→klien yang stabil
    • Batas 6 koneksi juga dibagi antar-tab browser, sehingga jika halaman yang sama dibuka di beberapa tab, tab-tab tersebut harus berbagi connection pool yang sama
    • RFC HTTP/1.1 merekomendasikan angka yang lebih rendah, yaitu 2 koneksi per server atau proxy
    • Kebijakan ini masuk akal untuk mencegah DDoS yang memanfaatkan pengunjung, tetapi dapat menjadi masalah saat komunikasi server-klien yang sah membutuhkan beberapa koneksi
    • Untuk mengatasinya, gunakan HTTP/2 atau HTTP/3 agar browser hanya membuka satu koneksi per domain dan memproses data dengan multiplexing
    • Di HTTP/2 dan HTTP/3, pengaturan SETTINGS_MAX_CONCURRENT_STREAMS tetap membatasi jumlah stream simultan sebenarnya, dan nilai default pada sebagian besar konfigurasi adalah 100 concurrent streams
    • Browser bisa saja menaikkan batas koneksi untuk API tertentu seperti EventSource, tetapi isu terkait Chromium dan Firefox ditandai sebagai “won’t fix”
  • Mengurangi jumlah koneksi aplikasi browser

    • Dalam aplikasi browser, harus diasumsikan pengguna dapat membuka aplikasi di beberapa tab sekaligus
    • Secara default, setiap tab dapat membuka satu koneksi stream server, tetapi kebanyakan tidak diperlukan
    • Dimungkinkan untuk hanya membuka satu koneksi meskipun beberapa tab terbuka, lalu membagikannya antar-tab
    • RxDB menggunakan LeaderElection dari broadcast-channel npm package untuk mempertahankan hanya satu replication stream antara server dan klien
    • Package ini juga dapat digunakan sendiri di aplikasi lain tanpa RxDB

Batasan operasional pada mobile, proxy, dan firewall

  • Pada sistem operasi mobile seperti Android dan iOS, sulit mempertahankan koneksi terbuka termasuk WebSockets secara terus-menerus
  • Mobile OS dapat memindahkan aplikasi ke background dan menutup koneksi terbuka setelah periode tidak aktif tertentu
  • Perilaku ini merupakan bagian dari strategi pengelolaan resource untuk menghemat baterai dan mengoptimalkan performa
  • Developer sering menggunakan push notification mobile alih-alih koneksi persisten saat server perlu mengirim data ke klien
  • Push notification memungkinkan server memberi tahu aplikasi tentang data baru dan memicu tindakan atau update aplikasi tanpa koneksi terbuka yang terus-menerus
  • Di lingkungan perusahaan, proxy dan firewall dapat memblokir koneksi non-HTTP, sehingga sulit memasukkan server WebSocket ke infrastruktur
  • Dalam lingkungan seperti ini, SSE yang berbasis HTTP dapat menjadi cara yang lebih mudah untuk integrasi perusahaan
  • Long Polling juga dapat menjadi pilihan karena hanya menggunakan request HTTP biasa

Perbandingan performa

  • Saat membandingkan WebSockets, SSE, Long Polling, dan WebTransport, latensi, throughput, beban server, dan skalabilitas perlu dilihat bersama
  • realtime-web repo yang menguji waktu pesan pada implementasi server Go menunjukkan bahwa performa WebSockets, WebRTC, dan WebTransport mirip
  • Karena WebTransport adalah teknologi baru berbasis HTTP/3, lebih banyak optimasi performa dapat muncul setelah Maret 2024
  • WebTransport dioptimalkan untuk mengurangi konsumsi daya, tetapi metrik tersebut tidak diuji
  • Latensi

    • WebSockets memberikan latensi terendah karena komunikasi full-duplex di atas satu koneksi persisten
    • SSE juga memberikan latensi rendah untuk komunikasi server→klien, tetapi diperlukan request HTTP tambahan jika klien ingin mengirim pesan ke server
    • Long Polling memiliki latensi lebih tinggi karena membuat koneksi HTTP baru untuk setiap pengiriman data
    • Pada Long Polling, latensi dapat meningkat besar jika klien sedang membuka koneksi baru tepat saat server ingin mengirim event
    • WebTransport diharapkan memberikan latensi rendah yang mirip dengan WebSockets, dengan memanfaatkan multiplexing dan congestion control HTTP/3 yang lebih efisien
  • Throughput

    • WebSockets dapat menghasilkan throughput tinggi berkat koneksi persisten, tetapi masalah backpressure, saat klien tidak dapat memproses secepat laju pengiriman server, dapat memengaruhi throughput
    • SSE memiliki overhead lebih kecil daripada WebSockets sehingga berpotensi menghasilkan throughput lebih tinggi untuk broadcast satu arah server→klien
    • Long Polling umumnya memiliki throughput rendah dan mengonsumsi lebih banyak resource server karena overhead membuka dan menutup koneksi secara sering
    • WebTransport diperkirakan mendukung throughput tinggi untuk stream satu arah maupun dua arah dalam satu koneksi, dan dapat mengungguli WebSockets pada skenario yang membutuhkan banyak stream
  • Skalabilitas dan beban server

    • WebSockets dapat sangat meningkatkan beban server seiring bertambahnya koneksi yang dipertahankan, sehingga dapat memengaruhi skalabilitas aplikasi dengan banyak pengguna
    • SSE lebih skalabel terutama pada skenario yang membutuhkan update server→klien
    • SSE menggunakan request HTTP biasa tanpa prosedur WebSocket seperti protocol upgrade, sehingga overhead koneksinya lebih rendah
    • Long Polling memiliki beban server besar karena koneksi sering dibuat, sehingga skalabilitasnya paling rendah dan hanya cocok sebagai mekanisme fallback
    • WebTransport dirancang dengan target skalabilitas tinggi berdasarkan efisiensi pemrosesan koneksi dan stream HTTP/3, dan berpotensi mengurangi beban server dibanding WebSockets dan SSE

Rekomendasi berdasarkan kasus penggunaan

  • SSE adalah pilihan dengan implementasi paling langsung, menggunakan protokol HTTP/S yang sudah ada sehingga lebih mudah menghindari batasan firewall perusahaan dan masalah teknis yang dapat muncul pada protokol lain
  • Dapat diintegrasikan dengan mudah ke Node.js dan framework server lain
  • Cocok untuk aplikasi yang sering membutuhkan update server→klien, seperti feed berita, harga saham, dan live event streaming
  • WebSockets kuat untuk skenario yang membutuhkan komunikasi dua arah berkelanjutan
  • Menjadi pilihan utama untuk kasus yang membutuhkan interaksi berkelanjutan, seperti game browser, aplikasi chat, dan update olahraga live
  • WebTransport punya potensi, tetapi dukungan framework server belum luas dan kompatibilitas dengan Node.js serta Safari masih kurang
  • WebTransport bergantung pada HTTP/3, sementara dukungan HTTP/3 di banyak web server seperti nginx masih berstatus experimental
  • Ini adalah teknologi masa depan yang mendukung transmisi data andal maupun tidak andal, tetapi untuk sebagian besar kasus penggunaan saat ini belum menjadi pilihan yang praktis
  • Long Polling umumnya merupakan cara lama karena inefisiensi dan overhead tinggi dari pembuatan koneksi HTTP baru secara berulang
  • Dapat digunakan sebagai fallback di lingkungan yang tidak mendukung WebSockets atau SSE, tetapi penggunaan umum tidak disarankan karena batasan performanya

Masalah event yang terlewat saat reconnect

  • Saat membangun fitur di atas teknologi streaming real-time apa pun, situasi koneksi terputus dan reconnect harus dipertimbangkan
  • Jika klien sedang tersambung, sedang reconnect, atau offline, event yang terjadi di server bisa saja tidak diterima lewat stream
  • Jika server men-streaming seluruh isi setiap kali, seperti harga saham, event yang terlewat mungkin tidak penting
  • Jika backend hanya men-streaming hasil parsial, event yang terlewat wajib ditangani
  • Cara backend mengingat event mana yang berhasil dikirim untuk tiap klien tidak skalabel
  • Masalah ini lebih baik ditangani dengan logika sisi klien
  • RxDB Sync Engine menggunakan dua mode operasi
    • checkpoint iteration mode: mengambil data backend berulang kali dengan request HTTP biasa sampai klien mengejar ketertinggalan dan tersinkronisasi kembali
    • event observation mode: menjaga klien tetap sinkron dengan update dari stream real-time
  • Jika koneksi klien terputus atau terjadi error, replication sementara beralih ke checkpoint iteration mode dan melakukan sinkronisasi sampai kembali ke state yang sama dengan server
  • Cara ini mengoreksi event yang terlewat dan memungkinkan klien selalu tersinkronisasi persis dengan server

Hal yang perlu diperiksa di infrastruktur perusahaan

  • Di infrastruktur perusahaan, berbagai teknologi streaming dapat mengalami masalah
  • Proxy dan firewall dapat memblokir traffic atau merusak request/response secara tidak sengaja
  • Saat mengimplementasikan aplikasi real-time di lingkungan seperti ini, terlebih dahulu perlu menguji apakah teknologi yang dipilih memang berjalan di infrastruktur tersebut

1 komentar

 
GN⁺ 2024-03-19
Opini Hacker News
  • Server-Sent Events selalu terasa menyenangkan. Sederhana serta mudah dipakai/diimplementasikan

    • Dengan IPv6, sekarang ini mudah dibuat benar-benar skalabel, dan jika dirancang dengan benar, cukup memberi klien daftar layanan SSE sehingga ia bekerja hampir seperti stateless, jauh lebih mudah untuk diskalakan
      WebSocket menjadi cukup rumit untuk diskalakan begitu penggunaannya melewati tingkat tertentu
    • Karena sederhana, ia bisa diskalakan lewat CDN jauh lebih mudah daripada WebSocket: https://www.fastly.com/blog/server-sent-events-fastly
    • Setuju. Namun ada batas 6 stream SSE per origin untuk setiap instans browser, jadi tanpa menambah kompleksitas di sisi klien, batasnya bisa saja 6 tab
      https://crbug.com/275955
    • Kekurangannya adalah payload harus dienkode sebagai base64 atau karakter baris baru harus dihapus
      Saya penasaran kenapa tidak dibuat saja sebagai respons streaming multipart. Itu mendukung metadata dan merupakan format yang sangat umum diimplementasikan
    • Bahkan berjalan di Apache prefork biasa dan PHP
  • Ada beberapa kekurangan tambahan yang perlu diketahui
    WebSocket tidak punya kontrol aliran (backpressure) dan multiplexing, jadi jika diperlukan harus membuatnya sendiri atau memakai sesuatu seperti RSocket. SSE juga tidak bisa mengirim data biner secara langsung, sehingga perlu encoding seperti base64
    WebTransport menangani masalah-masalah ini dan juga menyelesaikan HOL blocking, tetapi saya khawatir akan muncul masalah seperti transisi Python 2→3 atau IPv6, ketika orang mudah tetap memakai versi lama dan manfaat upgrade terasa kecil
    Selama browser tetap berjalan dengan TCP, sebagian jaringan bisa saja memblokir UDP, sehingga HTTP/3/WebTransport sama sekali tidak bisa dipakai

    • HOL blocking memang masalah, tetapi TCP menyediakan kontrol aliran. Jika tidak memakainya, berarti Anda naik ke atas HTTP/3
      Kekhawatiran bahwa transisi ke WebTransport bisa lambat adalah hal yang dulu juga bisa dikatakan persis sama tentang transport TLS, HTTP/3, dan XHR. Karena strukturnya didominasi beberapa engine browser utama, distribusi fitur dan protokol browser baru relatif mudah
      Jika logikanya adalah sebagian jaringan memblokir UDP karena TCP tersedia, itu mirip dengan mengatakan HTTP/2 dan TLS akan terus diblokir karena HTTP 1.1 non-TLS tersedia. Tidak sepenuhnya salah, tetapi melihat adopsi luas HTTP/2 dan terutama TLS, tampaknya ini bukan masalah sebesar yang dibayangkan
    • Saya sering mendengar soal jaringan yang memblokir UDP, tetapi belum pernah benar-benar melihatnya. Banyak juga yang berjalan di atas UDP
      Mungkin kantor kecil atau lingkungan perusahaan distopia yang seperti di film bisa menutupnya, tetapi saya tidak mengerti mengapa fakta bahwa sebagian jaringan bisa melarang UDP menjadi sangat relevan. Sebagian jaringan juga memblokir google.com atau wikipedia.com, tetapi bukan berarti layanan-layanan itu gagal
    • WebSocketStream akan segera masuk ke Chrome dan menambahkan backpressure: https://chromestatus.com/feature/5189728691290112
    • Ada binary-sse sebagai pendekatan yang lebih baik daripada base64: https://github.com/luciopaiva/binary-sse
    • Dalam situasi seperti itu, HTTP/2 masih akan berfungsi, jadi kekhawatiran soal multiplexing berkurang
  • Penjelasan WebRTC dalam artikel itu tidak akurat. WebRTC klien/server bisa dilakukan tanpa “server signaling” terpisah; server dapat melakukan signaling
    Hanya butuh beberapa round-trip tambahan, tidak perlu server terpisah. Kanal data WebRTC bekerja cukup baik sebagai pengganti WebSocket atau SSE, terutama saat ingin menghindari HOL blocking. Ada banyak library seperti Pion atau str0m yang mengurus hampir semua pekerjaan
    Pernyataan bahwa API WebTransport rumit juga tampak berlebihan. Jika tidak butuh fitur tingkat lanjut, abaikan saja; jika ingin memakainya seperti WebSocket, cukup buka satu stream dua arah dan hampir selesai. Untuk menghindari HOL blocking, buka stream untuk setiap pesan. Memang sedikit lebih rumit, tetapi tidak sampai wajib memakai library, dan GitHub Copilot kemungkinan besar bisa menuliskan kodenya. Namun WebTransport masih dalam tahap pematangan, jadi library server belum banyak dan dukungan Safari juga masih ditunggu

    • Saya ragu dengan klaim bahwa WebRTC klien/server bisa dilakukan tanpa “server signaling”
      Biasanya server signaling diimplementasikan dengan WebSocket. Kecuali Anda mengusulkan bootstrap terdesentralisasi dari klien-klien yang sudah ada, itu tidak bisa diimplementasikan dengan WebRTC itu sendiri
  • Jika Anda membuat sesuatu untuk pelanggan dengan infrastruktur TI “enterprise” dan “keamanan” tradisional, lebih baik tambahkan tombol refresh saja dan selesai
    Dalam pengalaman saya di lingkungan seperti ini, hal yang terus-menerus gagal dan tidak bisa diperbaiki karena prosedur tanpa akhir adalah upaya membangun fitur real-time untuk pelanggan semacam itu

    • Jetty/CometD akan fallback ke long polling jika metode transport lain tidak bisa dipakai
    • Sejujurnya, semua teknologi dalam keluarga ini punya masalah masing-masing, dan tombol refresh juga bukan pengecualian
    • Browser memang punya tombol refresh, tetapi kemungkinan besar jika ditekan aplikasinya akan rusak
  • WebSocket dan SSE menjadi sakit kepala besar untuk dikelola ketika skalanya membesar. Khususnya di backend, dibutuhkan observability terpisah, dan di perangkat mobile, kalau tidak diimplementasikan dengan sangat hati-hati, debugging frontend bisa menjadi mimpi buruk
    Perangkat mematikan atau memperlambat jaringan demi menghemat baterai, terlebih lagi jika I/O tidak dilakukan secara eksplisit lewat API khusus
    Membuat koneksi baru adalah operasi yang mahal, dan server harus menyimpan state di suatu tempat. Jika lapisan penyimpanan state ini bermasalah, klien akan terus mencoba ulang dan terkena timeout, lalu selamanya tersandera oleh operasi mahal. Ini juga bukan cara untuk mengendalikan throughput dengan mudah sambil memberi beban ke database secara perlahan
    Dari sisi keandalan, berdasarkan pengalaman, long polling adalah yang terbaik. Kalaupun alur berbasis event benar-benar penting, lebih baik memakai struktur 2 lapis: frontend melakukan long polling ke backend lapis 1, lalu lapis 1 itu berlangganan ke backend lapis 2 lewat WebSocket. Kontrol keandalannya jauh lebih baik

    • Sangat setuju. Saya pernah melihat orang menembak kaki sendiri dengan WebSocket dan SSE. Long polling memang ada biayanya, tetapi menurut saya itu pendekatan yang paling mudah dijelaskan dan paling dapat diskalakan
    • SSE mendukung long polling. Server bisa dibuat menutup koneksi kapan pun diinginkan
      SSE mendukung rekoneksi otomatis, dan juga menyertakan ID terakhir yang terlihat agar server bisa melanjutkan tanpa terputus
    • Cukup banyak bagian seperti ini dibahas dalam artikel yang ditautkan, dan rxdb punya mekanisme untuk meredakan berbagai kekhawatiran
  • Tidak ada di artikel, tetapi short polling juga relevan. Ini memang bukan cara mengirim pesan dari server ke klien, tetapi tetap berguna ketika tidak ada pilihan lain, misalnya di shared hosting
    Dalam pengalaman saya, meski interval polling panjang, misalnya 20 detik, cara ini berjalan cukup baik jika setiap respons ikut menyertakan daftar pesan. Saat pengguna menekan tombol, klien mengirim permintaan ke server, lalu server merespons dengan data beserta daftar pesan terbaru sehingga klien menjadi up to date

    • Ini juga bisa diterapkan pada data yang berubah cepat. Terutama jika proporsi polling yang memuat update cukup tinggi
  • Saya masih tidak mengerti mengapa WebSocket dan SSE sejak request awal tidak mendukung pengiriman header seperti Authorization. Semua autentikasi layanan real-time akhirnya diserahkan kepada implementornya
    Mungkin ada cara yang baik di spesifikasinya, tetapi saya sudah melihat terlalu banyak pendekatan berbeda sampai-sampai sekarang bisa dibilang secara praktis tidak ada

    • EventSource API punya banyak kekurangan. Saya adalah maintainer salah satu polyfill EventSource yang paling banyak dipakai, tetapi belakangan saya memulai proyek untuk membuat ulang klien EventSource secara lebih modern: https://github.com/rexxars/eventsource-client
      Selain menangani header kustom, ini juga mendukung semua metode request (POST, PATCH, dll.), penyertaan body request, berlangganan event bernama, dan penetapan last event ID awal. Bisa juga dipakai sebagai async iterator
      Saya menyukai kesederhanaan Server-Sent Events, tetapi API EventSource terlihat seperti diimplementasikan tergesa-gesa lalu dibiarkan begitu saja
      [1]: https://github.com/eventsource/eventsource
    • Bukankah request awal bisa mengirim seluruh header HTTP standar, bahkan cookie?
    • Cookie memang dikirim
    • Sertifikat TLS juga ada
    • Saya sudah memakainya bertahun-tahun; apakah saya melewatkan sesuatu?
  • Mungkin ini pemikiran naif, tetapi jika mengasumsikan HTTP/2 atau lebih baru, kombinasi EventSource dan fetch() untuk pengiriman pesan terlihat sama baiknya dengan protokol lain yang memakai satu koneksi TCP. HTTP/3 memakai UDP, jadi lebih bagus lagi
    Asumsinya koneksi hanya perlu dipertahankan saat tab berada di foreground. Saya penasaran masalah apa yang muncul ketika cara ini benar-benar dicoba

    • Salah satu batasannya adalah SSE hanya teks, jadi tidak bisa mengirim data biner secara efisien. Perlu encoding seperti base64
    • Ada library yang melakukan hal yang Anda inginkan
      https://www.npmjs.com/package/@microsoft/fetch-event-source
    • Saya juga berpikir persis sama. Dengan HTTP/2 dan SSE, rasanya 99% masalah sudah terselesaikan
      Saya penasaran apakah SSE bisa didorong lebih jauh dengan latensi, penggunaan memori, dan sumber daya CPU yang lebih rendah, alih-alih melakukan sesuatu yang sepenuhnya berbeda
    • Benar, jika asumsi use case utamanya adalah server→klien
  • Agak menarik melihat tulisan seperti ini. Pada akhir 90-an saya merancang sistem lelang online, dan sama sekali tidak ada request XHR
    Semua update real-time ditangani dengan server-push/HTTP streaming. Saat itu memang tidak mudah menangani semua koneksi terbuka, tetapi dengan arsitektur yang tepat, ini bisa dilakukan hingga skala yang dapat diterima

    • Saya menghabiskan sangat banyak waktu menjelaskan pentingnya HTTP streaming kepada orang-orang, dan itu jelas bukan perjuangan yang mudah
      Keunggulan HTTP/2 atau HTTP/3 memang luar biasa, tetapi perlu juga tahu apa yang bisa dimanfaatkan dari HTTP 1.1 yang secara praktis didukung di mana-mana
  • Saya agak merindukan long polling. Dibanding teknologi modern, itu benar-benar sederhana. Bahkan dari posisi saya yang menganggap WebRTC sebagai yang terbaik, saya tetap merasa begitu

    • SSE tidak jauh lebih rumit daripada long polling. Bedanya hanya koneksi tidak ditutup tepat setelah server mengirim respons
      Sebagai gantinya, server kembali menunggu data lalu mengirim respons tambahan lewat stream yang sama
    • Saya juga berharap sesederhana itu, tapi tidak
      Networking Second Life memakai HTTPS long polling untuk “event channel”, dan server mengirim pesan event ke klien lewat channel tersebut. Sebagian besar pesan dikirim lewat UDP, tetapi pesan yang memerlukan enkripsi atau berukuran besar masuk lewat event channel HTTPS/TCP
      Di sisi klien, klien C++ memakai libcurl, tetapi pengaturan timeout bawaannya tidak cocok dengan long polling. libcurl memutus koneksi dan membuat request baru, sehingga akibatnya bisa terjadi pesan hilang atau terduplikasi
      Di sisi server, Apache berada di depan server simulasi sebenarnya untuk menyaring upaya koneksi yang tidak relevan, tetapi Apache juga punya timeout sendiri, sehingga memutus koneksi dan memicu klien untuk mencoba lagi
      Mereka berusaha mencegah kehilangan pesan dengan nomor urut pesan, tetapi server Second Life mengabaikan nomor urut yang dikirim balik klien sebagai konfirmasi. Beberapa server kompatibel Open Simulator bahkan melompati nomor urut
      Hasilnya adalah sistem berbasis HTTPS yang bisa kehilangan atau menggandakan pesan yang semestinya andal. Jika sebagian pesan hilang, aktivitas pengguna di dalam game bisa terhenti
      Orang-orang yang merancang ini sudah pergi sejak lama, dan staf saat ini tidak tahu seberapa parah kekacauan ini. Pengguna eksternal harus menemukan dan mendokumentasikan masalahnya, sementara karyawan perusahaan sudah berbulan-bulan berusaha memperbaikinya. Karena cukup sulit untuk diperbaiki, saat ini tampaknya pekerjaan itu cenderung ditunda
      Jadi long polling tidak “sesederhana orang bodoh”. Cara yang benar kemungkinan adalah mengirim pesan keep-alive cukup sering agar lapisan TCP dan HTTPS tidak timeout. Dengan begitu, Apache dan libcurl tetap berada pada jalur yang bekerja dengan baik
    • Masih sering dipakai. Ada banyak aplikasi yang masuk akal untuk menanggung overhead request demi menjaga semuanya tetap dalam konteks HTTP API yang sudah ada
    • Saat ini pun long polling masih bisa dipakai dengan HTTP/2, dan tidak akan menghilang