Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi

Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
Perangkat lunak sebagai layanan, infrastruktur sebagai layanan, platform sebagai layanan, platform komunikasi sebagai layanan, konferensi video sebagai layanan, bagaimana dengan cloud gaming sebagai layanan? Sudah ada beberapa upaya untuk menciptakan cloud gaming (Cloud Gaming), seperti Stadia yang baru-baru ini diluncurkan oleh Google. Stadion bukan orang baru di WebRTC, tetapi bisakah orang lain menggunakan WebRTC dengan cara yang sama?

Thanh Nguyen memutuskan untuk menguji peluang ini pada proyek sumber terbukanya, CloudRetro. CloudRetro didasarkan pada Pion, populer Perpustakaan WebRTC berdasarkan Go (terima kasih Shownu dari tim pengembangan Pion atas bantuannya dalam mempersiapkan artikel ini). Dalam artikel ini, Thanh memberikan gambaran umum tentang arsitektur proyeknya, dan juga berbicara tentang hal-hal berguna apa yang dia pelajari dan tantangan apa yang dia temui selama bekerja.

Masuk

Tahun lalu, ketika Google mengumumkan Stadia, saya terkejut. Idenya sangat unik dan inovatif sehingga saya selalu bertanya-tanya bagaimana hal ini bisa terjadi dengan teknologi yang ada. Keinginan untuk lebih memahami topik ini mendorong saya untuk membuat game cloud sumber terbuka versi saya sendiri. Hasilnya sungguh luar biasa. Di bawah ini saya ingin berbagi proses kerja di tahun saya proyek.

TLDR: versi slide pendek dengan highlight

Mengapa cloud gaming adalah masa depan

Saya percaya bahwa Cloud Gaming akan segera menjadi generasi berikutnya tidak hanya dalam bidang game, tetapi juga bidang ilmu komputer lainnya. Cloud gaming adalah puncak dari model klien/server. Model ini memaksimalkan manajemen backend dan meminimalkan pekerjaan frontend dengan menghosting logika game di server jarak jauh dan mengalirkan gambar/audio ke klien. Server melakukan pemrosesan berat sehingga klien tidak lagi bergantung pada keterbatasan perangkat keras.

Google Stadia pada dasarnya memungkinkan Anda bermain permainan AAA (yaitu game blockbuster kelas atas) pada antarmuka seperti YouTube. Metodologi yang sama dapat diterapkan pada aplikasi offline berat lainnya seperti sistem operasi atau desain grafis 2D/3D, dll. sehingga kami dapat menjalankannya secara konsisten pada perangkat berspesifikasi rendah di berbagai platform.

Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
Masa depan teknologi ini: Bayangkan jika Microsoft Windows 10 dijalankan di browser Chrome?

Cloud gaming secara teknis menantang

Game adalah salah satu area langka yang memerlukan respons pengguna yang cepat dan konstan. Jika terkadang kami mengalami penundaan 2 detik saat mengklik suatu halaman, hal ini dapat diterima. Streaming video langsung cenderung tertunda beberapa detik, namun tetap menawarkan kegunaan yang wajar. Namun, jika game sering mengalami lag hingga 500 md, game tersebut tidak dapat dimainkan. Sasaran kami adalah mencapai latensi yang sangat rendah sehingga kesenjangan antara input dan media menjadi sekecil mungkin. Oleh karena itu, pendekatan tradisional terhadap streaming video tidak berlaku di sini.

Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
Templat Permainan Cloud Umum

Proyek sumber terbuka CloudRetro

Saya memutuskan untuk membuat sampel uji permainan cloud untuk melihat apakah semua ini mungkin dilakukan dengan pembatasan jaringan yang begitu ketat. Saya memilih Golang sebagai bukti konsep karena itu adalah bahasa yang paling saya kenal dan sangat cocok untuk implementasi ini karena banyak alasan lain, seperti yang kemudian saya temukan. Go itu sederhana dan berkembang sangat cepat; Saluran di Go sangat bagus untuk mengelola multithreading.

Proyek CloudRetro.io adalah layanan cloud gaming sumber terbuka untuk game retro. Tujuan dari proyek ini adalah untuk menghadirkan pengalaman bermain game paling nyaman ke game retro tradisional dan menambahkan multipemain.
Anda dapat mempelajari lebih lanjut tentang proyek ini di sini: https://github.com/giongto35/cloud-game.

Fungsionalitas CloudRetro

CloudRetro menggunakan game retro untuk mendemonstrasikan kekuatan cloud gaming. Yang memungkinkan Anda mendapatkan banyak pengalaman bermain game yang unik.

  • Portabilitas permainan
    • Pemutaran instan saat membuka halaman; tidak perlu mengunduh atau menginstal
    • Bekerja di browser seluler, jadi tidak diperlukan perangkat lunak untuk menjalankannya

  • Sesi permainan dapat dibagikan ke beberapa perangkat dan disimpan di cloud untuk saat Anda masuk lagi
  • Game ini dapat dialirkan, atau dapat dimainkan oleh beberapa pengguna sekaligus:
    • Crowdplay seperti TwitchPlayPokemon, hanya saja lebih bersifat lintas platform dan lebih real-time
    • Permainan luring daring. Banyak pengguna dapat bermain tanpa menyiapkan jaringan. Samurai Shodown kini dapat dimainkan oleh 2 pemain melalui jaringan CloudRetro

    Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
    Versi demo game multipemain daring di perangkat berbeda

    Infrastruktur

    Persyaratan dan tumpukan teknologi

    Di bawah ini adalah daftar persyaratan yang saya tetapkan sebelum memulai proyek.

    1. Satu pemain
    Persyaratan ini mungkin tidak tampak terlalu penting atau jelas di sini, tetapi ini adalah salah satu kesimpulan utama saya, hal ini memungkinkan cloud gaming untuk menjauh dari layanan streaming tradisional. Jika kita fokus pada game single-player, kita bisa menyingkirkan server terpusat atau CDN karena kita tidak perlu melakukan streaming ke banyak orang. Daripada mengunggah aliran ke server sink atau meneruskan paket ke server WebSocket terpusat, aliran layanan dikirimkan langsung ke pengguna melalui koneksi WebRTC peer-to-peer.

    2. Aliran media latensi rendah
    Membaca tentang Stadia, saya sering melihat WebRTC disebutkan di beberapa artikel. Saya menyadari bahwa WebRTC adalah teknologi luar biasa dan sempurna untuk digunakan dalam cloud gaming. WebRTC adalah proyek yang menyediakan browser web dan aplikasi seluler dengan komunikasi real-time melalui API sederhana. Ini menyediakan konektivitas peer-to-peer, dioptimalkan untuk media, dan memiliki codec standar bawaan seperti VP8 dan H264.

    Saya memprioritaskan memastikan pengalaman pengguna sebaik mungkin daripada mempertahankan grafis berkualitas tinggi. Beberapa kerugian dapat diterima dalam algoritma. Google Stadia memiliki langkah tambahan untuk mengurangi ukuran gambar di server, dan bingkai ditingkatkan ke kualitas yang lebih tinggi sebelum dikirimkan ke rekan-rekan.

    3. Infrastruktur terdistribusi dengan rute geografis
    Tidak peduli seberapa optimal algoritma dan kode kompresi, jaringan tetap menjadi faktor penentu yang berkontribusi paling besar terhadap latensi. Arsitekturnya harus memiliki mekanisme untuk memasangkan server yang paling dekat dengan pengguna untuk mengurangi waktu pulang pergi (RTT). Arsitekturnya harus memiliki 1 koordinator dan beberapa server streaming yang didistribusikan ke seluruh dunia: AS Barat, AS Timur, Eropa, Singapura, Tiongkok. Semua server streaming harus diisolasi sepenuhnya. Sistem dapat menyesuaikan distribusinya ketika server bergabung atau meninggalkan jaringan. Jadi, dengan lalu lintas yang besar, penambahan server tambahan memungkinkan penskalaan horizontal.

    4. Kompatibilitas peramban
    Cloud gaming berada dalam kondisi terbaiknya ketika kebutuhannya paling sedikit dari pengguna. Artinya, dapat dijalankan di browser. Browser membantu membuat pengalaman bermain game senyaman mungkin bagi pengguna, sehingga mereka tidak perlu menginstal perangkat lunak dan perangkat keras. Browser juga membantu menyediakan fungsionalitas lintas platform antara versi seluler dan desktop. Untungnya, WebRTC didukung dengan baik di berbagai browser.

    5. Pemisahan yang jelas antara antarmuka dan layanan game
    Saya melihat layanan cloud gaming sebagai sebuah platform. Setiap orang harus dapat menghubungkan apa pun ke platform. Sekarang saya sudah terintegrasi LibRetro dengan layanan cloud gaming karena LibRetro menawarkan antarmuka emulator game yang indah untuk game retro seperti SNES, GBA, PS.

    6. Ruang untuk multipemain, permainan massal, dan tautan eksternal (tautan dalam) dengan permainan
    CloudRetro mendukung banyak gameplay baru seperti CrowdPlay dan MultiPlayer Online untuk game retro. Jika beberapa pengguna membuka tautan dalam yang sama di komputer yang berbeda, mereka akan melihat permainan yang sedang berjalan dan bahkan dapat bergabung di dalamnya.

    Selain itu, status permainan disimpan di penyimpanan cloud. Hal ini memungkinkan pengguna untuk terus bermain kapan saja di perangkat lain.

    7. Penskalaan horizontal
    Seperti SAAS lainnya saat ini, cloud gaming harus dirancang agar dapat diskalakan secara horizontal. Desain koordinator-pekerja memungkinkan Anda menambahkan lebih banyak pekerja untuk melayani lebih banyak lalu lintas.

    8. Tidak ada koneksi ke satu cloud
    Infrastruktur CloudRetro dihosting di penyedia cloud yang berbeda (Digital Ocean, Alibaba, penyedia khusus) untuk wilayah berbeda. Saya mengaktifkan berjalan di wadah Docker untuk infrastruktur dan mengonfigurasi pengaturan jaringan menggunakan skrip bash untuk menghindari terkunci pada satu penyedia cloud. Dengan menggabungkan ini dengan NAT Traversal di WebRTC, kami memiliki fleksibilitas untuk menerapkan CloudRetro di platform cloud apa pun dan bahkan di mesin pengguna mana pun.

    Desain arsitektur

    Pekerja: (atau server streaming yang disebutkan di atas) mengalikan permainan, menjalankan saluran pengkodean, dan mengalirkan media yang dikodekan ke pengguna. Instance pekerja didistribusikan ke seluruh dunia, dan setiap pekerja dapat menangani beberapa sesi pengguna secara bersamaan.

    Koordinator: bertanggung jawab untuk memasangkan pengguna baru dengan pekerja yang paling cocok untuk streaming. Koordinator berinteraksi dengan pekerja melalui WebSocket.

    Penyimpanan status permainan: penyimpanan jarak jauh pusat untuk semua status game. Penyimpanan ini menyediakan fungsi penting seperti penyimpanan/pemuatan jarak jauh.

    Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
    Arsitektur CloudRetro tingkat atas

    Skrip Kustom

    Saat pengguna baru membuka CloudRetro pada langkah 1 dan 2 yang ditunjukkan pada gambar di bawah, koordinator beserta daftar pekerja yang tersedia diminta ke halaman pertama. Setelah ini, pada langkah 3 klien menghitung penundaan untuk semua kandidat menggunakan permintaan ping HTTP. Daftar penundaan ini kemudian dikirim kembali ke koordinator sehingga dia dapat menentukan pekerja yang paling cocok untuk melayani pengguna. Langkah 4 di bawah ini membuat game. Koneksi streaming WebRTC dibuat antara pengguna dan pekerja yang ditugaskan.
    Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
    Skrip pengguna setelah mendapatkan akses

    Apa yang ada di dalam pekerja

    Pipeline game dan streaming disimpan di dalam pekerja secara terpisah dan bertukar informasi di sana melalui antarmuka. Saat ini komunikasi tersebut dilakukan dengan mentransfer data dalam memori melalui Saluran Golang dalam proses yang sama. Tujuan selanjutnya adalah segregasi, yaitu. peluncuran game secara independen dalam proses lain.

    Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
    Interaksi komponen pekerja

    Komponen utama:

    • WebRTC: komponen klien yang menerima input dan output pengguna media yang dikodekan dari server.
    • Emulator permainan: komponen permainan. Berkat perpustakaan Libretro, sistem dapat menjalankan game dalam proses yang sama dan secara internal mencegat media dan aliran input.
    • Bingkai dalam game diambil dan dikirim ke pembuat enkode.
    • Pembuat Enkode Gambar/Audio: saluran pengkodean yang mengambil bingkai media, mengkodekannya di latar belakang, dan mengeluarkan gambar/audio yang dikodekan.

    Implementasi

    CloudRetro mengandalkan WebRTC sebagai teknologi tulang punggungnya, jadi sebelum mendalami detail implementasi Golang, saya memutuskan untuk membahas tentang WebRTC itu sendiri. Ini adalah teknologi luar biasa yang sangat membantu saya dalam mencapai latensi subdetik untuk streaming data.

    WebRTC

    WebRTC dirancang untuk menyediakan koneksi peer-to-peer berkualitas tinggi pada aplikasi seluler dan browser asli menggunakan API sederhana.

    Lintasan NAT

    WebRTC dikenal dengan fungsionalitas NAT Traversal-nya. WebRTC dirancang untuk komunikasi peer-to-peer. Tujuannya adalah untuk menemukan rute langsung yang paling sesuai, menghindari gateway NAT dan firewall untuk komunikasi peer-to-peer melalui proses yang disebut ES. Sebagai bagian dari proses ini, API WebRTC menemukan alamat IP publik Anda menggunakan server STUN dan meneruskannya ke server relai (MENGHIDUPKAN) ketika sambungan langsung tidak dapat dibuat.

    Namun CloudRetro tidak sepenuhnya memanfaatkan fitur ini. Koneksi peer-to-peernya tidak terjadi antar pengguna, tetapi antara pengguna dan server cloud. Sisi server model memiliki batasan komunikasi langsung yang lebih sedikit dibandingkan perangkat pengguna pada umumnya. Ini memungkinkan Anda untuk membuka terlebih dahulu port masuk atau menggunakan alamat IP publik secara langsung, karena server tidak berada di belakang NAT.

    Sebelumnya, saya ingin mengubah proyek ini menjadi platform distribusi game untuk Cloud Gaming. Idenya adalah untuk memungkinkan pembuat game menyediakan game dan sumber daya streaming. Dan pengguna akan berinteraksi dengan penyedia secara langsung. Dengan cara yang terdesentralisasi ini, CloudRetro hanyalah sebuah kerangka kerja untuk menghubungkan sumber daya streaming pihak ketiga ke pengguna, membuatnya lebih terukur ketika tidak lagi dihosting. Peran WebRTC NAT Traversal di sini sangat penting untuk memfasilitasi inisialisasi koneksi peer-to-peer pada sumber daya streaming pihak ketiga, sehingga memudahkan pembuatnya untuk terhubung ke jaringan.

    Kompresi video

    Kompresi video adalah bagian tak terpisahkan dari saluran dan memberikan kontribusi besar terhadap kelancaran aliran. Meskipun tidak perlu mengetahui setiap detail pengkodean video VP8/H264, memahami konsepnya dapat membantu Anda memahami opsi kecepatan streaming video, men-debug perilaku yang tidak terduga, dan menyesuaikan latensi.

    Mengompresi video untuk layanan streaming merupakan tantangan karena algoritma harus memastikan bahwa total waktu pengkodean + waktu transmisi jaringan + waktu decoding serendah mungkin. Selain itu, proses pengkodean harus konsisten dan berkesinambungan. Beberapa pengorbanan pengkodean tidak berlaku—misalnya, kami tidak menyukai waktu pengkodean yang lama dibandingkan ukuran file dan waktu decoding yang lebih kecil, atau menggunakan kompresi yang tidak konsisten.

    Ide dibalik kompresi video adalah untuk menghilangkan potongan informasi yang tidak perlu sambil mempertahankan tingkat akurasi yang dapat diterima oleh pengguna. Selain menyandikan masing-masing bingkai gambar statis, algoritme juga menyimpulkan bingkai saat ini dari bingkai sebelumnya dan berikutnya, sehingga hanya perbedaannya yang dikirim. Seperti dapat dilihat dari contoh Pacman, hanya titik diferensial yang ditransmisikan.

    Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
    Perbandingan frame video menggunakan Pacman sebagai contoh

    Kompresi audio

    Demikian pula, algoritma kompresi audio menghilangkan data yang tidak dapat dilihat oleh manusia. Opus saat ini merupakan codec audio dengan performa terbaik. Ini dirancang untuk mengirimkan gelombang audio melalui protokol datagram yang dipesan seperti RTP (Real Time Transport Protocol). Latensinya lebih rendah dari mp3 dan aac, dan kualitasnya lebih tinggi. Latensi biasanya sekitar 5~66,5ms.

    Pion, WebRTC di Golang

    Menggadaikan adalah proyek sumber terbuka yang menghadirkan WebRTC ke Golang. Daripada membungkus pustaka C++ WebRTC asli seperti biasa, Pion adalah implementasi WebRTC asli Golang dengan kinerja lebih baik, integrasi Go, dan kontrol versi pada protokol WebRTC.

    Pustaka ini juga memungkinkan streaming dengan banyak fitur bawaan yang bagus dengan latensi subdetik. Ia memiliki implementasi STUN, DTLS, SCTP, dll. dan beberapa eksperimen dengan QUIC dan WebAssembly. Pustaka sumber terbuka ini sendiri adalah sumber pembelajaran yang sangat bagus dengan dokumentasi yang sangat baik, implementasi protokol jaringan, dan contoh-contoh keren.

    Komunitas Pion, dipimpin oleh seorang pencipta yang sangat bersemangat, cukup hidup, dengan banyak diskusi berkualitas tentang WebRTC. Jika Anda tertarik dengan teknologi ini, bergabunglah http://pion.ly/slack – Anda akan belajar banyak hal baru.

    Menulis CloudRetro di Golang

    Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
    Implementasi pekerja di Go

    Buka Saluran dalam Aksi

    Berkat desain saluran Go yang indah, masalah streaming acara dan konkurensi menjadi lebih sederhana. Seperti pada diagram, GoRoutine yang berbeda memiliki beberapa komponen yang berjalan secara paralel. Setiap komponen mengelola statusnya dan berkomunikasi melalui saluran. Pernyataan selektif Golang memaksa satu peristiwa atom diproses setiap kali dalam game (game tick). Ini berarti tidak diperlukan penguncian untuk desain ini. Misalnya, saat pengguna menyimpan, diperlukan gambaran lengkap tentang status game. Status ini harus tetap berlanjut, login hingga penyimpanan selesai. Selama setiap tick permainan, backend hanya dapat menangani operasi penyimpanan atau input, sehingga membuat thread proses aman.

    func (e *gameEmulator) gameUpdate() {
    for {
    	select {
    		case <-e.saveOperation:
    			e.saveGameState()
    		case key := <-e.input:
    			e.updateGameState(key)
    		case <-e.done:
    			e.close()
    			return
    	}
        }
    }

    Fan-in/Fan-out

    Templat Golang ini sangat cocok dengan kasus penggunaan CrowdPlay dan Banyak Pemain saya. Mengikuti pola ini, semua masukan pengguna dalam satu ruangan dibangun ke dalam saluran masuk pusat. Media permainan kemudian disebarkan ke seluruh pengguna dalam satu ruangan yang sama. Dengan cara ini, kami mencapai pembagian status permainan antara beberapa sesi permainan dari pengguna yang berbeda.

    Game cloud sumber terbuka di WebRTC: p2p, multipemain, tanpa latensi
    Sinkronisasi antar sesi yang berbeda

    Kekurangan Golang

    Golang tidak sempurna. Salurannya lambat. Dibandingkan dengan pemblokiran, saluran Go hanyalah cara yang lebih mudah untuk menangani kejadian serentak dan berulir, namun saluran tidak memberikan kinerja terbaik. Ada logika pemblokiran yang rumit di bawah saluran. Jadi saya membuat beberapa penyesuaian pada implementasinya, menerapkan kembali kunci dan nilai atomik saat mengganti saluran untuk mengoptimalkan kinerja.

    Selain itu, pemulung di Golang tidak dikelola, yang terkadang menyebabkan jeda panjang yang mencurigakan. Hal ini sangat mengganggu aplikasi streaming real-time.

    Cgo

    Proyek ini menggunakan pustaka Golang VP8/H264 open source yang ada untuk kompresi media dan Libretro untuk emulator game. Semua perpustakaan ini hanyalah pembungkus dari perpustakaan C yang digunakan Go Cgo. Beberapa kelemahannya tercantum dalam posting ini oleh Dave Cheney. Masalah yang saya temui:

    • ketidakmampuan untuk mengalami kerusakan di CGO, bahkan dengan Golang RecoveryCrash;
    • kegagalan untuk mengidentifikasi hambatan kinerja ketika kami tidak dapat mendeteksi masalah secara rinci di CGO.

    Kesimpulan

    Saya mencapai tujuan saya dalam memahami layanan cloud gaming dan menciptakan platform yang membantu saya memainkan game retro nostalgia bersama teman-teman saya secara online. Proyek ini tidak akan mungkin terwujud tanpa perpustakaan Pion dan dukungan komunitas Pion. Saya sangat bersyukur atas pengembangannya yang intensif. API sederhana yang disediakan oleh WebRTC dan Pion memastikan integrasi yang lancar. Bukti konsep pertama saya dirilis pada minggu yang sama, meskipun saya tidak memiliki pengetahuan sebelumnya tentang komunikasi peer-to-peer (P2P).

    Meskipun integrasinya mudah, streaming P2P memang merupakan bidang yang sangat kompleks dalam ilmu komputer. Dia harus menghadapi kompleksitas arsitektur jaringan lama seperti IP dan NAT untuk membuat sesi peer-to-peer. Saat mengerjakan proyek ini, saya memperoleh banyak pengetahuan berharga tentang jaringan dan pengoptimalan kinerja, jadi saya mendorong semua orang untuk mencoba membuat produk P2P menggunakan WebRTC.

    CloudRetro melayani semua kasus penggunaan yang saya harapkan dari sudut pandang saya sebagai gamer retro. Namun, menurut saya ada banyak area dalam proyek ini yang dapat saya tingkatkan, seperti membuat jaringan lebih andal dan berkinerja, menyediakan grafis game dengan kualitas lebih tinggi, atau kemampuan untuk berbagi game antar pengguna. Saya sedang bekerja keras dalam hal ini. Mohon mengikuti proyek dan dukung jika Anda menyukainya.

Sumber: www.habr.com

Tambah komentar