What's the best way to make a real-time multiplayer web game API in Go? A dedicated newbie wants to know...

agolangf · · 428 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>You know how people say that to learn a programming language you should just jump into it with a project? So, I&#39;m doing that. Having reached my first milestone, I&#39;m coming here seeking advice about how to make my next step -- how to make a modern real-time API for a multiplayer game. Please read on if that&#39;s interesting to you<sup><sup>.</sup></sup></p> <p>Starting with no knowledge of Go (or pointers), I&#39;ve now built a console-based 54 playing card game, a variant of &#34;<a href="https://en.wikipedia.org/wiki/One-card">One-Card</a>,&#34; with a quite complex set of rules for a card game, and despite being pretty hacky, it actually works. </p> <p>&#34;It works&#34; means: you can add players, a chat asks you what you&#39;d like to do -- just fmt.Println() and bufio.NewReader(os.Stdin) printing and input type of stuff --, play as if you were controlling all of the players from the one console by typing players&#39; moves into the console (like &#34;jh jd&#34; for Jack of Hearts, Jack of Diamonds), and so on. So the basic game logic for a single game at a time is working and it comes in at around 900 lines of (comment-ridden) code. It&#39;s been fun to write!</p> <p>My next steps planned are:</p> <ul> <li>Turn it into a web/mobile real-time API.</li> <li>Add a Reactjs client.</li> <li>After those: Add the ability to make multiple tables with multiple decks. Persist player data. Add a few levels of &#34;AI&#34; so you can play against the computer (just simple rule sets, no machine learning or neural nets). Add auth (maybe AWS Cognito), and host it somewhere like AWS.</li> </ul> <p>My biggest question now seems to be, <em>what should I use to make a real-time API?</em> </p> <ul> <li><a href="https://grpc.io/">gPRC</a> and no framework? Could gRPC replace both websockets and an HTTP / JSON API? </li> <li>A web framework like Revel? </li> <li>Websockets and no framework? </li> </ul> <p>I really don&#39;t know how to go about this, so any knowledgeable advice would be extrafabulishiously appreciated!</p> <p>Ah, I&#39;d ideally like to be able to scale to thousands of users without totally blowing my wallet, and for reasons I haven&#39;t gotten into yet, a p2p-only setup like purely using webrtc won&#39;t work. It needs to go through a server / service of some sort, connected to a database, because I hope the game to be the first step in the game layer of a broader app.</p> <p>Thanks for reading and thanks in advance for any good input.</p> <hr/>**评论:**<br/><br/>Isaluteyou: <pre><p>There is not an easy way to do streaming gRPC between a JS web client and Go server (edit: this may be wrong - see below.)</p> <p>You might start by assuming you only have a single server, not a replicated game server. Once that is working, you can expand to many servers (ideally as needed).</p> <p>To get your feet wet with the server aspect, send input through a form or plain URL parameter and return output in the body of the response. Check out this tutorial for using the vanilla Go HTTP server to create a simple site: <a href="https://golang.org/doc/articles/wiki/">https://golang.org/doc/articles/wiki/</a>. Note, this essentially uses the filesystem as the database.</p> <p>Ideally, the I/O should be isolated from your game logic (by functions and/or packages). This is good design in general, but would let you keep both versions of your game.</p> <p>Once this is setup, you can switch to using websockets to make updates for clients in real time. If you&#39;re feeling impatient, you could go straight for this option. The gorilla websocket library is nice to use.</p></pre>tclineks: <pre><p>grpc-websocket-proxy can stream to browser clients. </p></pre>sOundsoFpErsistence: <pre><p>Somewhat related; Out of curiosity, why do we still use standard JSON APIs? Would an RPC library be more efficient than REST/etc JSON APIs?</p> <p>I&#39;ve never tried replacing any of the user facing <em>(read, browser facing)</em> JSON APIs I write with RPC, but I&#39;m quite curious if it would be more efficient. Ie, less data transferred, more robust for security, or ... whatever.</p> <p>Thoughts?</p></pre>nk2580: <pre><p>there would be some limitation in terms of browser support. I have a hard time believing that IE or Edge would support a high performance GRPC client. Http/2 doesn’t necessarily mean we can throw ourselves into GRPC on the client side.</p> <p>That being said. I completely agree, why should we use JSON if we don’t need it?</p></pre>chrisdefourire: <pre><p><em>I completely agree, why should we use JSON if we don’t need it?</em></p> <p>If super high performance isn&#39;t required, simplicity wins. JSON is easy to handle in both JS and Go. JSON is the simplest serialization format from the JS standpoint, and the simplest common denominator between JS and Go. And human-readable serialization really helps sometimes...</p> <p>So I&#39;d definitely start with JSON if possible</p></pre>MonkeeSage: <pre><p>Also, when going from protobuf (the format underlying gRPC) to javascript, and assuming you are serving your JSON with gzip compression like a responsible adult, you only get a 10ms speedup with a 10kb size saving over JSON (<a href="https://auth0.com/blog/beating-json-performance-with-protobuf/" rel="nofollow">source</a>). So it definitely feels like a premature optimization.</p></pre>mallory-erik: <pre><p>Thank you! Your answer and habarman&#39;s do sound, um, like sound advice. The tip about keeping game logic and I/O isolated is something I&#39;ll keep in mind.</p></pre>habarnam: <pre><p>I think your first step is to define how your network communiction would work. Are the clients communicating among each-other, is there a central server that dispatches to every client?</p> <p>And regarding the communication protocol, I feel like for such a simple use case, anything not hand baked would be overkill. Of course YMMV. :)</p></pre>mallory-erik: <pre><p>Thanks. Clients should be able to communicate between each other, in a moderated, semi-chat fashion, but yes, through a central server or service who dispatches to clients whose one to seven players are in the same game, at the same &#34;table&#34; or room.</p> <p>So it sounds to me like you&#39;re pretty much recommending the same course as Isaluteyou. Start at the simplest possible solution, even though it&#39;s not real-time at first, and then upgrade to websockets soon after that.</p></pre>habarnam: <pre><p>I&#39;m not sure what you mean by &#34;not real time&#34; ... Do you want to have a connection permanently open between server and client? From what you mention as your use case, I&#39;m not seeing why you&#39;d need that.</p></pre>mallory-erik: <pre><p>Well, I&#39;d want to push the players moves and the game state to the clients as soon as possible, without them having to do any refresh. Wouldn&#39;t that require something like websockets or else some kind of streaming?</p></pre>habarnam: <pre><p>I don&#39;t think so. Some hand baked messages encapsulation over HTTP would be enough, at least to get you to start prototyping. </p> <p>If you find it too slow then you can move to passing messages over UDP, which doesn&#39;t have all the overhead of waiting for TCP handshake and all that. But my personal opinion is that that&#39;s in the realm of FPS games more than what you have in mind.</p></pre>Dwood15: <pre><p>You might want to check out websockets. Setting them up and using them couldn&#39;t be easier. </p></pre>FZambia: <pre><p>Not an answer to OPs question yet but hopefully can be an option in future. I am working on <a href="https://github.com/centrifugal/centrifuge" rel="nofollow">https://github.com/centrifugal/centrifuge</a> library which is an abstraction over several bidirectional streaming transports - GRPC, Websocket, SockJS. So theoretically one can combine transports in a way that is appropriate in certain situation – Websocket in browser, GRPC from mobile device for example. Also it&#39;s supposed to work with JSON and binary (Protobuf protocol) payloads, though SockJS obviously does not support binary. It&#39;s not ready for production at moment as the work simply not finished but most things already implemented and working. The difficult part is clever public API – still working on it, review and feedback are very valuable at this stage. It can be a bit distinctive in some aspects as its original purpose is to be a core of <a href="https://github.com/centrifugal/centrifugo" rel="nofollow">Centrifugo</a> v2. The sad thing is that server requires client for each platform and transport. Personally I can implement browser and Go clients, but can&#39;t develop for mobile. I can only believe in open-source in this aspect.</p></pre>Mattho: <pre><p>I&#39;m using go-kit now, and it forces the separation from protocols reasonably well. So it should be rather easy to change http/json for grpc. Maybe.</p></pre>zemo: <pre><p>don&#39;t use gRPC. Officially gRPC runs over HTTP 2, which can be a headache since not everything supports it yet. Unofficially there are ways to expose a gRPC server over HTTP 1.1 and ways to create a bridge that auto-generates a REST API over a gRPC api but err it doesn&#39;t really work with streams. Save yourself the headache. gRPC is absolutely incredibly great if you&#39;re in control of the client, but in the case of a web client, you&#39;re not. gRPC is a fantastic tool but it&#39;s not suited for the thing you&#39;re asking about. </p> <p>make a regular web app with <a href="https://github.com/gorilla/mux" rel="nofollow">gorilla/mux</a>. There are faster routers out there but this one is widely used (so there&#39;s a lot of discussion about it), it&#39;s well documented, and it&#39;s pretty easy to figure out. </p> <p>once you&#39;re rendering pages and serving up the javascripts, add websocket support with <a href="https://github.com/gorilla/websocket" rel="nofollow">gorilla/websocket</a>. Don&#39;t use socket.io. </p> <p>If you want a primer on writing web applications, do the <a href="https://golang.org/doc/articles/wiki/" rel="nofollow">writing web applications</a> tutorial on the Go site. There are other ways to write applications, some would say easier ways, but many of them obscure rather than illuminate why net/http is written the way it is. </p> <p>and ignore Revel. Now and forever. Never, ever, ever use Revel.</p></pre>etherealflaim: <pre><p>I would consider using eventsource or websockets, and I&#39;d do so without a framework but possibly with one of the libraries that implement these if you don&#39;t want to have the fun of learning how they work by implementing them yourself. I&#39;d also encourage you to look at AppEngine standard Go runtime for hosting, as it has super easy datastore, authentication, and channels support and has a lot of free quota.</p></pre>jackmott2: <pre><p>websockets. you don&#39;t want any kind of overhead or limitation that some framework on top of that might add.</p></pre>chrisdefourire: <pre><p>You&#39;ll have 2 different things to handle:</p> <ul> <li>match making (find a table/room to play) by asking a match making service</li> <li>the game itself, in the room</li> </ul> <p>Ideally, you want many room servers (as many as needed) for a few match making service... and the two types of service need to communicate too (so that the match making service knows which tables are available, how many players are already inside, etc) Match making may not require a real time interface (HTTPS REST api) while the room API should probably use real time interface</p> <p>Design that architecture carefully...</p> <p>As for the tech stack, I&#39;d recommend going with Websockets and JSON. Websockets are native to the web, well supported in JS and with Gorilla Websockets. JSON is easy to deal with.</p> <p>Make progress fast, make perfect later.</p></pre>beowulf_71: <pre><p>I would love to see websockets/rest apis/json rpc handle this nicely.. and in slower not-quite-real-time games they may suffice. If you want almost instant communication between say two players (lets say Clash Royale style or other mobile person to person 2 player game that requires almost instant updates), I am not sure any of these will work well enough. If you want near real time, you might take a look at <a href="https://api.unrealengine.com/udk/Three/NetworkingOverview.html#Unreal%20networking%20architecture" rel="nofollow">this</a></p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

428 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传