16 poin oleh GN⁺ 2024-10-24 | 1 komentar | Bagikan ke WhatsApp
  • Lichess adalah platform catur open source gratis dengan jutaan pemain di seluruh dunia
  • Menggunakan tab Network di Chrome DevTools untuk memantau komunikasi antara klien dan server

Koneksi WebSocket

  • Aktivitas jaringan pertama yang patut diperhatikan adalah koneksi WebSocket ke URL yang mirip seperti berikut:
wss://socket2.lichess.org/play/H5uHz0egyvIA/v6?sri=bt6QzcyOiZg5&v=0  
  • Protokol wss menunjukkan koneksi WebSocket terenkripsi yang menggunakan TLS
  • WebSocket memungkinkan komunikasi full-duplex sehingga pembaruan real-time antara klien dan server dapat dilakukan tanpa permintaan HTTP berulang

Giliran pemain lokal

  • Saat sebuah aksi dilakukan, paket data dipertukarkan:
// Dikirim pada 22:51:35.280  
{  
  "t": "move",   
  "d": {  
    "u": "d2d4",  
    "l": 32,  
    "a": 1  
  }  
}  
  • Pesan yang diterima dari server:
// Diterima pada 22:51:35.312  
{  
  "t": "ack",  
  "d": 1  
}  
  • Ini memberi tahu bahwa server telah menerima aksi kita
// Diterima pada 22:51:35.312  
{  
  "t": "move",  
  "v": 1,  
  "d": {  
    "uci": "d2d4",  
    "san": "d4",  
    "fen": "rnbqkbnr/pppppppp/8/8/3P4/8/PPP1PPPP/RNBQKBNR",  
    "ply": 1,  
    "clock": {  
      "white": 300,  
      "black": 300  
    }  
  }  
}  
  • Pesan ini memberikan informasi rinci tentang aksi yang kita lakukan dan status permainan yang telah diperbarui

Giliran lawan

  • Saat lawan bergerak, paket serupa diterima dari server:
// Diterima pada 22:51:43.489  
{   
  "t": "move",  
  "v": 2,  
  "d": {  
    "uci": "d7d5",  
    "san": "d5",  
    "fen": "rnbqkbnr/ppp1pppp/8/3p4/3P4/8/PPP1PPPP/RNBQKBNR",  
    "ply": 2,  
    "dests": {  
      "c2": "c3c4",  
      "g2": "g3g4"  
      // Langkah tambahan yang mungkin  
    },  
    "clock": {   
      "white": 300,  
      "black": 300  
    }  
  }  
}   
  • Parameter dests mencantumkan semua langkah yang tersedia dari posisi saat ini

Arsitektur Lichess

  • Sistem permainan real-time Lichess terutama terdiri dari dua layanan utama (keduanya ditulis dalam Scala):
    1. lila: layanan inti yang mengelola logika permainan, status, interaksi pengguna, dan fungsi inti lainnya
    2. lila-ws: layanan khusus penanganan WebSocket yang berperan sebagai jembatan antara klien dan lila

Gambaran umum arsitektur

lila <-> redis <-> lila-ws <-> websocket <-> client  
  • lila berkomunikasi dengan lila-ws melalui Redis, dan lila-ws mengelola koneksi WebSocket dengan klien

Komunikasi menggunakan Redis Pub/Sub

  • Event langkah dipublikasikan ke channel Redis Pub/Sub, yang kemudian dilanggan oleh lila untuk memproses langkah tersebut
  • Redis Pub/Sub menyediakan pengiriman at-most-once. Kehilangan pesan dimungkinkan, tetapi penggunaan memori berkurang

Persistensi data akhir dengan MongoDB

  • lila menyimpan status permainan ke MongoDB, tetapi tidak langsung menyimpan setiap langkah tunggal
  • Sebagai gantinya, langkah-langkah dibuffer dan disimpan secara berkala untuk mengurangi beban DB
  • Saat event penting terjadi, status permainan akan di-flush

Bergabung ke permainan yang sedang berlangsung

  • Saat pemain terhubung, mereka memberikan parameter v untuk memberi tahu sistem tentang versi terbaru permainan yang mereka ketahui
  • lila-ws menggunakan ConcurrentHashMap untuk melacak dan mengelola semua event dari permainan yang sedang berlangsung

Penutup

Proses langkah di Lichess dapat diringkas sebagai berikut:

  1. Klien membuat koneksi WebSocket ke lila-ws
  2. Saat pemain melakukan langkah, klien mengirim event langkah ke lila-ws
  3. lila-ws mengirim respons ack untuk mengonfirmasi penerimaan langkah
  4. Event langkah dipublikasikan ke channel Redis Pub/Sub dan diproses oleh lila
  5. lila menerima langkah, memperbarui status permainan, lalu pada akhirnya menyimpannya ke MongoDB. Status permainan yang telah diperbarui dikirim kembali ke klien melalui lila-ws
  6. Klien menerima status permainan yang telah diperbarui yang mencerminkan langkah baru dan perubahan status permainan

Pendapat GN⁺

  • Tulisan ini membahas secara rinci arsitektur backend dan proses yang memungkinkan gameplay real-time di lichess.org, platform catur open source yang populer
  • Tulisan ini memperkenalkan elemen teknis utama yang perlu dipertimbangkan saat membangun aplikasi web real-time, misalnya komunikasi real-time dengan WebSocket, pengiriman pesan yang skalabel melalui Redis Pub/Sub, dan penyimpanan data akhir dengan MongoDB
  • Arsitektur Lichess sangat cocok untuk game multipemain real-time, tetapi pola dan teknologi serupa juga dapat diterapkan pada jenis aplikasi web real-time lain seperti chat, alat kolaborasi, dan feed media sosial
  • Fitur real-time dapat meningkatkan pengalaman dan interaksi pengguna, tetapi juga menimbulkan tantangan teknis tersendiri seperti skalabilitas, keandalan, dan konsistensi data. Tulisan ini menawarkan strategi untuk mengatasi tantangan tersebut
  • Proyek open source dengan stack teknologi serupa antara lain Socket.IO (framework aplikasi real-time berbasis Node.js) dan RethinkDB (database NoSQL yang dioptimalkan untuk aplikasi web real-time)
  • Analisis dalam tulisan ini tidak didasarkan pada peninjauan langsung terhadap source code Lichess, sehingga implementasi nyatanya mungkin berbeda. Namun, konsep dasar dan pola arsitektur yang dijelaskan tetap relevan
  • Saat merancang sistem real-time, perlu dipertimbangkan dengan saksama apakah pengiriman at-most-once (kemungkinan kehilangan pesan) atau at-least-once (kemungkinan duplikasi pesan) lebih tepat. Ini bergantung pada kebutuhan dan trade-off aplikasi

1 komentar

 
GN⁺ 2024-10-24
Opini Hacker News
  • Ada keluhan tentang struktur waktu di Chess.com. Tampaknya server melacak waktu sehingga mengabaikan waktu pengiriman dan latensi. Ini terasa sangat tidak nyaman saat memainkan game berbatas waktu di klien mobile

    • Ini juga bisa jadi masalah pada kode jaringan, dan kesalahan sering terjadi di puzzle
    • Teknologi Chess.com terasa agak kasar
  • Lichess memilih pendekatan StackOverflow dan menggunakan server yang kuat

    • Status game disimpan secara berkala, tetapi tidak jelas disimpan di mana
    • Biaya per game sangat rendah: $0.00027, 1 dolar untuk 3.671 game
    • Ketergantungan pada satu data center pernah menyebabkan downtime selama 10 jam
  • Menghitung langkah di sisi server menjamin konsistensi dan mengoptimalkan performa klien yang memiliki daya pemrosesan atau energi terbatas

    • Ini mungkin untuk menurunkan hambatan implementasi klien perangkat lunak open source di platform baru
    • Implementasi aturan catur bisa merepotkan, dan Lichess juga pernah memiliki bug logika
  • Kurang ada penjelasan tentang bagaimana kehilangan pesan ditangani di kanal Redis pub/sub

  • Parameter "l" mungkin menunjukkan latensi yang diamati server

  • Menarik bahwa server mencantumkan dan mengirim semua langkah legal berikutnya

    • Ini bisa menguntungkan bagi klien yang terbatas, tetapi dipertanyakan apakah lebih murah dibanding menghitungnya di sisi klien
  • Ada pertanyaan tentang cara melindungi server WebSocket

    • Menggunakan paket gratis Cloudflare menimbulkan latensi
    • Ada rasa ingin tahu tentang solusi gratis
  • Ada yang bertanya-tanya mengapa protokol memerlukan ack

    • WebSocket yang dibungkus TLS dapat menjamin integritas pesan
  • FEN hanya mengodekan status papan, tidak mencakup status game

    • Proyek scalachess yang ditulis dengan Scala terus dipelihara dengan baik