{"id":89303,"date":"2020-07-22T01:42:30","date_gmt":"2020-07-21T23:42:30","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency"},"modified":"2020-07-22T01:42:30","modified_gmt":"2020-07-21T23:42:30","slug":"oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","status":"publish","type":"post","link":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","title":{"rendered":"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/511626\/\"><img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/22dbf7665d7fded15671d98a2afe599b.png\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\nPaaS, IaaS, PaaS, CaaS, videoconferencing as a service; en hoe zit het met cloud gaming als een dienst? Er zijn al verschillende pogingen gedaan om cloud gaming (Cloud Gaming) te cre\u00ebren, zoals Stadia, onlangs gelanceerd door Google. Stadia <noindex><a rel=\"nofollow\" href=\"https:\/\/youtu.be\/avtlQeaxd_I?t=440\">is geen nieuwkomer in WebRTC<\/a><\/noindex>, maar kunnen anderen WebRTC ook gebruiken op dezelfde manier?<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Thanh Nguyen besloot deze mogelijkheid uit te testen met zijn open source project CloudRetro. CloudRetro is gebaseerd op Pion, <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/webrtc-open-source-most-popular\/\">een populaire<\/a><\/noindex> WebRTC-bibliotheek gebaseerd op Go (dank aan <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/Sean-Der\">Shawn<\/a><\/noindex> van de Pion-ontwikkelaarsgroep voor de hulp bij het opstellen van dit artikel). In dit artikel geeft Thanh een overzicht van de architectuur van zijn project en deelt hij de nuttige inzichten en uitdagingen die hij tijdens het werk is tegengekomen.<\/p>\n<h2>Inleiding<\/h2>\n<p>\nVorig jaar, toen Google Stadia aankondigde, was ik gewoon omver geblazen. Het idee is zo uniek en innovatief dat ik me constant afvroeg hoe dit mogelijk is met de huidige technologie. De wens om dit onderwerp beter te begrijpen, heeft me ertoe aangezet om mijn eigen versie van een open source cloud gaming te maken. Het resultaat was gewoon fantastisch. Hieronder wil ik het proces delen van mijn jaarlange <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">project<\/a><\/noindex>.<\/p>\n<p><i>TLDR: een korte slideversie met de belangrijkste punten<\/i><\/p>\n<h3>Waarom cloud gaming de toekomst heeft<\/h3>\n<p>\nIk geloof dat Cloud Gaming snel de nieuwe generatie zal worden, niet alleen voor games, maar ook voor andere informatica-toepassingen. Cloud gaming is de top van het client\/server-model. Dit model maximaliseert het backendbeheer en minimaliseert de frontend-werkzaamheden door de game-logica op een externe server te plaatsen en beelden\/audio naar de client te streamen. De server voert de zware verwerking uit, zodat de client niet meer afhankelijk is van hardwarebeperkingen.<\/p>\n<p>Google Stadia stelt in wezen in staat om te spelen in <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/AAA_(%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B5_%D0%B8%D0%B3%D1%80%D1%8B)\">AAA-games<\/a><\/noindex> (d.w.z. high-end blockbuster games) via een interface zoals YouTube. Dezelfde methodologie kan ook worden toegepast op andere zware offline applicaties, zoals besturingssystemen of 2D\/3D grafisch ontwerp, zodat we ze stabiel kunnen draaien op apparaten met lage specificaties op verschillende platforms.<\/p>\n<p><img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/d6ca3e47db5c8e3d9880b304cc3be33b.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDe toekomst van deze technologie: stel je voor dat Microsoft Windows 10 zou werken in de Chrome-browser?<\/p>\n<h3>Cloud gaming is technisch complex<\/h3>\n<p>\nGaming is one of those rare areas where a constant quick response from the user is required. If we occasionally experience a 2-second delay when clicking on a page, it's acceptable. Live video streams usually lag by a few seconds, yet still offer sufficient usability. However, if a game frequently lags by 500 ms, it's simply unplayable. Our goal is to achieve extremely low latency to minimize the gap between input and media. Therefore, the traditional approach to streaming video is not applicable here.<\/p>\n<p><img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/d73765a3c9277c026f407883e1091473.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nAlgemene sjabloon voor cloudgaming<\/p>\n<h2>Open-source project CloudRetro<\/h2>\n<p>\nIk besloot een testvoorbeeld van cloudgaming te cre\u00ebren om te testen of dit mogelijk is onder zulke strikte netwerkbeperkingen. Voor de conceptvalidatie koos ik voor Golang, omdat dit de taal is die mij het meest bekend is en goed geschikt blijkt voor deze implementatie om vele andere redenen, zoals later bleek. Go is eenvoudig en ontwikkelt zich zeer snel; de kanalen in Go zijn uitstekend voor het beheren van multithreading.<\/p>\n<p>Project <noindex><a rel=\"nofollow\" href=\"http:\/\/cloudretro.io\/\">CloudRetro.io<\/a><\/noindex> \u2013 cloud gaming service met open source voor retro-gaming. Het doel van het project is om het meest comfortabele speelervaring in traditionele retro games te brengen en multiplayer toe te voegen.<br \/>\nJe kunt hier meer over het project lezen: <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">https:\/\/github.com\/giongto35\/cloud-game<\/a><\/noindex>.<\/p>\n<h3>Functionaliteit van CloudRetro<\/h3>\n<p>\nOm de volledige kracht van cloudgaming te demonstreren, maakt CloudRetro gebruik van retro games. Dit levert een verscheidenheid aan unieke game-ervaringen op.<\/p>\n<ul>\n<li>Draagbaarheid van de game\n<ul>\n<li>Directe afspeelmogelijkheid bij het openen van de pagina; geen downloads of installaties nodig<\/li>\n<li>Werkt in mobiele browsers, dus er is geen software nodig voor opstarten<\/li>\n<\/ul>\n<p>\n<\/li>\n<li>Speelsessies kunnen op meerdere apparaten worden gedeeld en in de cloud worden opgeslagen voor de volgende aanmelding<\/li>\n<li>De game kan gestreamd worden en kan ook direct door meerdere gebruikers gespeeld worden:\n<ul>\n<li>Crowdplay \u00e0 la TwitchPlayPokemon, maar meer cross-platform en real-time<\/li>\n<li>Offline games online. Veel spelers kunnen spelen zonder netwerkconfiguratie. In Samurai Shodown kunnen nu 2 spelers via CloudRetro net werken.<\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/bdc715971755d669a026f830ce888520.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nDemo-versie van een multiplayer online game op verschillende apparaten<\/p>\n<h2>Infrastructuur<\/h2>\n<p><\/p>\n<h3>Vereisten en technologie-stack<\/h3>\n<p>\nHieronder volgt een lijst met vereisten die ik heb opgesteld voordat ik aan het project begon.<\/p>\n<p><b>1. E\u00e9n speler<\/b><br \/>\nDit vereiste lijkt misschien niet zo belangrijk en voor de hand liggend, maar het is een van mijn belangrijkste bevindingen; het stelt cloudgaming in staat om zich zoveel mogelijk te distanti\u00ebren van traditionele streamingdiensten. Als we ons richten op singleplayer-games, kunnen we afstand doen van een gecentraliseerde server of CDN, omdat we geen broadcast naar massa's hoeven te maken. In plaats van streams te uploaden naar een veeleisende server of pakketten naar een gecentraliseerde WebSocket-server te sturen, worden service-streams rechtstreeks aan de gebruiker geleverd via een peer-to-peer WebRTC-verbinding.<\/p>\n<p><b>2. Media-stream met lage latentie<\/b><br \/>\nBij het lezen over Stadia kom ik in sommige artikelen vaak de vermelding van WebRTC tegen. Ik besefte dat WebRTC een uitstekende technologie is en perfect geschikt voor gebruik in cloudgaming. WebRTC is een project dat web-browsers en mobiele applicaties real-time communicatie biedt via een eenvoudige API. Het zorgt voor een peer-to-peer-verbinding, geoptimaliseerd voor media, en heeft ingebouwde standaardcodecs zoals VP8 en H264.<\/p>\n<p>Ik heb de voorkeur gegeven aan het waarborgen van het maximale gebruiksgemak voor gebruikers boven het behoud van hoge grafische kwaliteit. In het algoritme zijn bepaalde verliezen aanvaardbaar. Google Stadia heeft een extra stap voor het verkleinen van de afbeeldingsgrootte op de server, en frames worden tot een hogere kwaliteit opgeschaald voordat ze worden doorgegeven aan peer-nodes.<\/p>\n<p><b>3. Gedistribueerde infrastructuur met geografische routering<\/b><br \/>\nOngeacht hoe geoptimaliseerd het compressie-algoritme en de code zijn, blijft het netwerk een doorslaggevende factor die het meest bijdraagt aan vertraging. De architectuur moet een mechanisme hebben voor het koppelen van de dichtstbijzijnde server aan de gebruiker om de round-trip-tijd (RTT) te verkorten. De architectuur moet 1 co\u00f6rdinator en verschillende streamingservers hebben die over de wereld zijn verdeeld: West-VS, Oost-VS, Europa, Singapore, China. Alle streamingservers moeten volledig ge\u00efsoleerd zijn. Het systeem kan zijn distributie aanpassen wanneer een server aan het netwerk wordt toegevoegd of eruit stapt. Zo maakt het toevoegen van extra servers bij hoge verkeersdruk horizontaal schalen mogelijk.<\/p>\n<p><b>4. Browsercompatibiliteit<\/b><br \/>\nCloud gaming komt het beste tot zijn recht als het gebruikers minimaal vereist. Dit betekent dat er mogelijkheden zijn om te starten in de browser. Browsers helpen om de speelervaring zo comfortabel mogelijk te maken voor gebruikers, waardoor ze geen software of hardware hoeven te installeren. Browsers helpen ook om de cross-platform functionaliteit voor mobiele en desktopversies te waarborgen. Gelukkig wordt WebRTC uitstekend ondersteund in verschillende browsers.<\/p>\n<p><b>5. Duidelijke scheiding van de game-interface en de service<\/b><br \/>\nIk beschouw de cloud gaming service als een platform. Iedereen moet in staat zijn om van alles aan het platform te koppelen. Momenteel heb ik <noindex><a rel=\"nofollow\" href=\"http:\/\/LibRetro\">LibRetro<\/a><\/noindex> ge\u00efntegreerd met de cloud gaming service, omdat LibRetro een prachtig interface voor game-emulators aanbiedt voor retro games zoals SNES, GBA, PS.<\/p>\n<p><b>6. Kamers voor multiplayer, crowd play en externe koppelingen (deep-link) met de game<\/b><br \/>\nCloudRetro ondersteunt verschillende nieuwe gameplay-opties, zoals CrowdPlay en Online MultiPlayer voor retro games. Als meerdere gebruikers dezelfde deep-link openen op verschillende computers, zullen ze dezelfde spelactiviteit zien en zelfs kunnen deelnemen.<\/p>\n<p>Bovendien worden de spelstatussen opgeslagen in cloudopslag. Dit stelt gebruikers in staat om hun spel op elk gewenst moment op elk ander apparaat voort te zetten.<\/p>\n<p><b>7. Horizontale schaalbaarheid<\/b><br \/>\nNet als elke SAAS tegenwoordig, moeten cloud games zo worden ontworpen dat ze horizontaal schaalbaar zijn. De 'co\u00f6rdinator-werknemer' constructie maakt het mogelijk om meer werknemers toe te voegen om meer verkeer te verwerken.<\/p>\n<p><b>8. Geen binding aan \u00e9\u00e9n cloud<\/b><br \/>\nDe infrastructuur van CloudRetro is ondergebracht bij verschillende cloudproviders (Digital Ocean, Alibaba, eigen provider) voor verschillende regio's. Ik activeer de uitvoering in een Docker-container voor de infrastructuur en configureer de netwerkinstellingen met een bash-script om afhankelijkheid van \u00e9\u00e9n cloudprovider te vermijden. Door dit te combineren met NAT Traversal in WebRTC, kunnen we flexibiliteit krijgen om CloudRetro op elke cloudplatform en zelfs op de machines van elke gebruiker uit te rollen.<\/p>\n<h3>Architectonisch ontwerp<\/h3>\n<p>\n<b>Werknemer:<\/b> (of de streamingserver genoemd hierboven) vermenigvuldigt games, start de codering pipeline en verzendt de gecodeerde media naar gebruikers. De worker-instanties zijn over de hele wereld verspreid, en elke worker kan meerdere gebruikerssessies tegelijkertijd verwerken.<\/p>\n<p><b>Co\u00f6rdinator:<\/b> verantwoordelijk voor het koppelen van een nieuwe gebruiker aan de meest geschikte worker voor streaming. De co\u00f6rdinator communiceert met de workers via WebSocket.<\/p>\n<p><b>Opslag van game-statussen:<\/b> een centraal extern opslag voor alle game-statussen. Deze opslag biedt belangrijke functies, zoals externe opslag\/laden.<\/p>\n<p><img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/985447b81350a640b0bd1344b5705113.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nHoog-niveau architectuur van CloudRetro<\/p>\n<h3>Gebruikersscenario<\/h3>\n<p>\nWanneer een nieuwe gebruiker CloudRetro opent in stappen 1 en 2, zoals weergegeven in de afbeelding hieronder, wordt de co\u00f6rdinator samen met de lijst van beschikbare workers op de eerste pagina opgevraagd. Vervolgens berekent de client in stap 3 de latenties voor alle kandidaten met behulp van een HTTP ping verzoek. Deze lijst van latenties wordt teruggestuurd naar de co\u00f6rdinator, zodat deze de meest geschikte worker voor de gebruiker kan bepalen. In stap 4 wordt het spel aangemaakt. Er wordt een streamingverbinding via WebRTC tot stand gebracht tussen de gebruiker en de toegewezen worker.<br \/>\n<img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/00199b5942e3e4314609ec0e70ea7162.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nGebruikersscenario na toegang<\/p>\n<h3>Wat er in de worker gebeurt<\/h3>\n<p>\nGame- en streaming pipelines worden ge\u00efsoleerd binnen de worker opgeslagen en communiceren daar via de interface. Momenteel gebeurt deze communicatie op basis van gegevensoverdracht in het geheugen via <noindex><a rel=\"nofollow\" href=\"https:\/\/tour.golang.org\/concurrency\/2\">Golang kanalen<\/a><\/noindex> in hetzelfde proces. De volgende stap is segmentatie, dat wil zeggen het onafhankelijk draaien van de game in een ander proces.<\/p>\n<p><img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/7a90ec2638344467a34604cd4322165c.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nInteractie van worker-componenten<\/p>\n<p>De belangrijkste componenten:<\/p>\n<ul>\n<li><b>WebRTC:<\/b> klantcomponent die gebruikersinvoer accepteert en gecodeerde media van de server uitvoert.\n<\/li>\n<li><b>Game-emulator:<\/b> de gamecomponent. Dankzij de Libretro-bibliotheek is het systeem in staat om de game binnen hetzelfde proces uit te voeren en intern media en invoerstream te onderscheppen.\n<\/li>\n<li>In-game frames worden vastgelegd en naar de encoder verzonden.\n<\/li>\n<li><b>Afbeelding\/audiocodec:<\/b> de coderingspipeline die mediakaders accepteert, deze op de achtergrond codeert en gecodeerde afbeeldingen\/audio uitvoert.\n<\/li>\n<\/ul>\n<p><\/p>\n<h2>Implementatie<\/h2>\n<p>\nCloudRetro vertrouwt op WebRTC als de kerntechnologie, dus voordat ik in detail inga op de implementatie in Golang, wilde ik iets vertellen over WebRTC zelf. Het is een fantastische technologie die me enorm heeft geholpen bij het bereiken van een datastreamingvertraging van slechts een fractie van een seconde.<\/p>\n<h3>WebRTC<\/h3>\n<p>\nWebRTC is ontworpen om hoogwaardige peer-to-peer verbindingen te bieden in native mobiele applicaties en in browsers met behulp van eenvoudige API's.<\/p>\n<h4>NAT Traversal <\/h4>\n<p>\nWebRTC staat bekend om zijn functionaliteit voor NAT Traversal. WebRTC is bedoeld voor peer-to-peer communicatie. Het doel is om de meest geschikte directe route te vinden, waarbij NAT-gateways en firewalls worden vermeden voor peer-to-peer communicatie via een proces dat wordt genoemd <noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/trickle-ice\/\">ICE<\/a><\/noindex>. In dit proces vinden de WebRTC API's uw openbare IP-adres met behulp van STUN-servers en sturen het door naar de relayserver (<noindex><a rel=\"nofollow\" href=\"https:\/\/webrtchacks.com\/?s=turn\">TURN<\/a><\/noindex>), wanneer een directe verbinding niet kan worden gemaakt.<\/p>\n<p>CloudRetro maakt echter niet volledig gebruik van deze mogelijkheid. De peer-to-peer verbindingen bestaan niet tussen gebruikers, maar tussen gebruikers en cloudservers. De serverzijde van het model heeft minder beperkingen op directe verbinding dan een gebruikelijk gebruikersapparaat. Dit maakt het mogelijk om inkomende poorten vooraf te openen of openbare IP-adressen direct te gebruiken, omdat de server niet achter NAT zit.<\/p>\n<p>Eerder wilde ik het project omvormen tot een game-distributieplatform voor Cloud Gaming. Het idee was om gameontwikkelaars in staat te stellen spellen en streamingsresources aan te bieden. Gebruikers zouden rechtstreeks met de providers interageren. Op deze gedecentraliseerde manier fungeert CloudRetro slechts als een omgeving voor het verbinden van externe streamingresources met gebruikers, wat het schaalbaarder maakt wanneer er geen hosting meer aan verbonden is. De rol van WebRTC NAT Traversal is hier cruciaal voor het vergemakkelijken van de initialisatie van peer-to-peer verbindingen op externe streamingresources, wat het makkelijker maakt om de maker met het netwerk te verbinden.<\/p>\n<h4>Videocompressie<\/h4>\n<p>\nVideocompressie is een essentieel onderdeel van de pipeline dat aanzienlijk bijdraagt aan de vloeiendheid van de stroom. Hoewel het niet nodig is om alle details van videocodec VP8\/H264 te kennen, helpt het begrijpen van het concept bij het begrijpen van de streaming video bitrate-instellingen, het oplossen van onverwacht gedrag en het afstemmen van vertraging.<\/p>\n<p>Videocompressie voor een streamingdienst is een complexe taak, omdat het algoritme moet garanderen dat de totale coderingstijd + netwerktijd + decodeertijd zo laag mogelijk is. Bovendien moet het coderingsproces consistent en continu zijn. Sommige wederzijdse concessies bij codering zijn niet van toepassing \u2013 bijvoorbeeld, we kunnen geen voorkeur geven aan langere coderingstijd voor een kleiner bestand en kortere decodeertijd, of gebruik maken van inconsistente compressie.<\/p>\n<p>Het idee achter videocompressie is om onnodige bits informatie te verwijderen, terwijl een acceptabel niveau van nauwkeurigheid voor gebruikers behouden blijft. Naast het coderen van afzonderlijke statische beelden, extrapoleert het algoritme de huidige frame uit de vorige en volgende, zodat alleen hun verschil wordt verzonden. Zoals te zien is in het voorbeeld met Pacman, worden alleen de differenti\u00eble punten verzonden.<\/p>\n<p><img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/e452c54c53ab7797b610620aefbba8d2.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nVergelijking van videoframes met het voorbeeld van Pacman<\/p>\n<h4>Audiocompressie<\/h4>\n<p>\nEvenzo laat het geluidcompressie-algoritme gegevens weg die niet door de mens kunnen worden waargenomen. Momenteel is Opus de audiocodec met de beste prestaties. Het is ontworpen voor het verzenden van audiogolven via een geordend datagramprotocol, zoals RTP (Real Time Transport Protocol). Het heeft minder vertraging dan mp3 en aac, terwijl de kwaliteit hoger is. De vertraging bedraagt meestal ongeveer 5~66,5 ms.<\/p>\n<h4>Pion, WebRTC in Golang<\/h4>\n<p>\n<noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pion\/webrtc\">Pion<\/a><\/noindex> is een open-source project dat WebRTC naar Golang brengt. In plaats van de gebruikelijke wrapper voor native C++ bibliotheken van WebRTC, is Pion een native Golang-implementatie van WebRTC met betere prestaties, integratie met Go en versiebeheer op WebRTC-protocollen.<\/p>\n<p>De bibliotheek biedt ook streaming met veel uitstekende ingebouwde modules met een vertraging van minder dan een seconde. Het heeft zijn eigen implementatie van STUN, DTLS, SCTP, enz. en enkele experimenten met QUIC en WebAssembly. Deze open-source bibliotheek is op zichzelf een echt goede leermiddelen met uitstekende documentatie, implementatie van netwerken en leuke voorbeelden.<\/p>\n<p>De Pion-community, geleid door een zeer gepassioneerde maker, is behoorlijk levendig, er zijn veel kwaliteitsdiscussies over WebRTC. Als je ge\u00efnteresseerd bent in deze technologie, sluit je aan bij <noindex><a rel=\"nofollow\" href=\"http:\/\/pion.ly\/slack\">http:\/\/pion.ly\/slack<\/a><\/noindex> \u2013 je zult veel nieuwe dingen leren.<\/p>\n<h3>Het schrijven van CloudRetro in Golang<\/h3>\n<p>\n<img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/f85f7b8ea579fab964d870aad698c7e7.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nImplementatie van een worker in Go<\/p>\n<h4>Go-kanalen in actie<\/h4>\n<p>\nDankzij het mooie ontwerp van Go-kanalen worden problemen met event-streaming en parallelisme aanzienlijk vereenvoudigd. Zoals weergegeven in het diagram, werken verschillende componenten parallel in verschillende GoRoutines. Elke component beheert zijn eigen toestand en communiceert via kanalen. De selectieve instructie van Golang zorgt ervoor dat er steeds \u00e9\u00e9n atomair event per moment in het spel (game tick) wordt verwerkt. Dit betekent dat voor dit ontwerp er geen locking nodig is. Bijvoorbeeld, wanneer een gebruiker wordt opgeslagen, is een volledige snapshot van de speltoestand vereist. Deze toestand moet continu blijven, terwijl de invoer plaatsvindt totdat de opslaan is voltooid. Tijdens elke game tick kan de backend slechts \u00e9\u00e9n van opslaan of invoer verwerken, wat het proces veilig maakt voor meerdere threads.<\/p>\n<pre><code class=\"go\">func (e *gameEmulator) gameUpdate() {\nfor {\n\tselect {\n\t\tcase &lt;-e.saveOperation:\n\t\t\te.saveGameState()\n\t\tcase key := &lt;-e.input:\n\t\t\te.updateGameState(key)\n\t\tcase &lt;-e.done:\n\t\t\te.close()\n\t\t\treturn\n\t}\n    }\n}<\/code><\/pre>\n<p><\/p>\n<h4>Fan-in \/ Fan-out<\/h4>\n<p>\nDit Golang-patroon is perfect voor mijn gebruiksscenario van CrowdPlay en Multiple Player. Door dit patroon worden alle gebruikersinvoer in \u00e9\u00e9n kamer ge\u00efntegreerd in een centrale invoerkanal. Spelmedia worden vervolgens verspreid naar alle gebruikers in \u00e9\u00e9n kamer. Op deze manier bereiken we het delen van de speltoestand tussen verschillende spelsessies van verschillende gebruikers.<\/p>\n<p><img decoding=\"async\" alt=\"Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency\" src=\"\/wp-content\/uploads\/2020\/07\/000a495d7f214246a8a396aab11a3ac5.png\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nSynchronisatie tussen verschillende sessies<\/p>\n<h4>Nadelen van Golang<\/h4>\n<p>\nGolang is not perfect. The channel is slow. Compared to lock-based channels, Go is simply a simpler way to handle concurrent and streaming events, but the channel does not offer the best performance. Beneath the channel lies complex locking logic. Therefore, I made some adjustments to the implementation by reapplying locks and atomic values when replacing channels to optimize performance.<\/p>\n<p>Moreover, the garbage collector in Golang is unmanaged, which sometimes leads to suspiciously long pauses. This significantly hampers the operation of real-time streaming applications.<\/p>\n<h4>CGO<\/h4>\n<p>\nThe project uses an existing open-source VP8\/H264 library in Golang for media compression and Libretro for game emulators. All these libraries are just wrappers around the C library in Go using <noindex><a rel=\"nofollow\" href=\"https:\/\/golang.org\/cmd\/cgo\/\">CGO<\/a><\/noindex>. Some of the drawbacks are listed in <noindex><a rel=\"nofollow\" href=\"https:\/\/dave.cheney.net\/2019\/10\/06\/use-internal-packages-to-reduce-your-public-api-surface\">this post by Dave Cheney<\/a><\/noindex>. The issues I encountered include:<\/p>\n<ul>\n<li>the inability to catch crashes in CGO, even with Golang RecoveryCrash;<\/li>\n<li>the inability to identify performance bottlenecks when we cannot detect detailed issues in CGO.<\/li>\n<\/ul>\n<p><\/p>\n<h2>Conclusie<\/h2>\n<p>\nI achieved my goal \u2013 I learned about cloud gaming services and created a platform that helps play nostalgic retro games with my friends online. Creating this project would have been impossible without the Pion library and the support of the Pion community. I am extremely grateful for its intensive development. The simple APIs provided by WebRTC and Pion facilitated smooth integration. My first proof of concept was released in the same week, even though I was unaware of peer-to-peer (P2P) connections in advance.<\/p>\n<p>Despite the ease of integration, P2P streaming is indeed a very complex area in computer science. It has to deal with the complexity of years of networking architectures, such as IP and NAT to establish a peer-to-peer session. During my time working on this project, I accumulated a lot of valuable knowledge about networking and performance optimization, so I recommend everyone try building P2P products with WebRTC.<\/p>\n<p>CloudRetro bedient alle gebruiksscenario's die ik als retro-gamer verwachtten. Toch denk ik dat er veel gebieden zijn in het project die ik kan verbeteren, zoals het betrouwbaarder en effici\u00ebnter maken van het netwerk, het bieden van een hogere grafische kwaliteit van games, of de mogelijkheid om games tussen gebruikers te delen. Ik werk er hard aan. Houd alsjeblieft de updates in de gaten. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/giongto35\/cloud-game\">project<\/a><\/noindex> en ondersteun het als je het leuk vindt.<\/li>\n<\/ul>\n<p>Bron: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/Voximplant\/blog\/511626\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041f\u041e \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u043e\u043d\u043d\u0430\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0432\u0438\u0434\u0435\u043e\u043a\u043e\u043d\u0444\u0435\u0440\u0435\u043d\u0446\u0438\u0438 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0430, \u0430 \u0447\u0442\u043e \u043d\u0430\u0441\u0447\u0435\u0442 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 \u043a\u0430\u043a \u0443\u0441\u043b\u0443\u0433\u0438? \u0423\u0436\u0435 \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u043f\u0440\u0438\u043d\u044f\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043f\u044b\u0442\u043e\u043a \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0445 \u0438\u0433\u0440 (Cloud Gaming), \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, Stadia, \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0435\u0439 Google. Stadia \u043d\u0435 \u043d\u043e\u0432\u0438\u0447\u043e\u043a \u0432 WebRTC, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c WebRTC \u0442\u0430\u043a \u0436\u0435? \u0422\u0445\u0430\u043d\u044c \u041d\u0433\u0443\u0435\u043d (Thanh [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":89304,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-89303","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"nl_NL\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0433\u0435\u0439\u043c\u0438\u043d\u0433 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u043d\u0430 WebRTC: p2p, \u043c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0435\u0435\u0440, zero latency | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-07-21T23:42:30+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-07-21T23:42:30+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Cloudgaming met open source op WebRTC: p2p, multiplayer, zero latency | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nl_NL","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0433\u0435\u0439\u043c\u0438\u043d\u0433 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u043d\u0430 WebRTC: p2p, \u043c\u0443\u043b\u044c\u0442\u0438\u043f\u043b\u0435\u0435\u0440, zero latency | ProHoster","og:url":"https:\/\/prohoster.info\/nl\/blog\/administrirovanie\/oblachnyj-gejming-s-otkrytym-ishodnym-kodom-na-webrtc-p2p-multipleer-zero-latency","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-07-21T23:42:30+00:00","article:modified_time":"2020-07-21T23:42:30+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"89303","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 13:12:27","updated":"2022-09-29 13:03:06","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/89303","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/comments?post=89303"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/posts\/89303\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media\/89304"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/media?parent=89303"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/categories?post=89303"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/nl\/wp-json\/wp\/v2\/tags?post=89303"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}