Amazon has announced Amazon GameLift Streams to allow developers to stream their games to virtually any device with a web browser.
seen from Germany

seen from Netherlands
seen from China

seen from United Kingdom
seen from Kazakhstan
seen from United Kingdom
seen from Norway
seen from China

seen from Singapore

seen from Ireland

seen from Poland
seen from China
seen from Germany

seen from Ireland
seen from United States

seen from United States

seen from Israel
seen from China
seen from Philippines

seen from China
Amazon has announced Amazon GameLift Streams to allow developers to stream their games to virtually any device with a web browser.
GameLiftのGo用Server SDKを作ってみた
その名もGomeLift。https://github.com/neguse/gomelift
GomeLiftを使うと、Goを使って開発したサーバをGameLiftにデプロイできるようになります。これにより、例えばリアルタイムに通信してゲームの状態を管理するサーバをGoで開発しているケースでは、サーバのスケーリングやマッチメイキングをGameLiftにお任せできるようになります。
現状は、とりあえず公式のServer SDKの機能をほぼまるまる移植して、サンプルが一応動いたという程度の状態です。もし使ってみた方がいましたら、お気軽に感想や要望など、GitHubのIssueや twitter:neguse までご連絡ください。
開発の動機、履歴を追いたい方は以下のログを参照ください。たぶん最初の記事が一番くわしいです。
https://www.neguse.dev/post/190754792208/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%841
https://www.neguse.dev/post/190858174313/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%842
https://www.neguse.dev/post/190965430813/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%843
https://www.neguse.dev/post/612563897674809344/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%844
https://www.neguse.dev/post/613280040330854400/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%845
https://www.neguse.dev/post/613911685911248896/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%846
https://www.neguse.dev/post/614570811455651840/gamelift%E3%81%AEgo%E7%94%A8server-sdk%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%81%9F%E3%81%847
なんだかんだで2ヶ月かかってしまったけど、これでようやく次の作業にとりかかれる…
GameLiftのGo用Server SDKを作ってみたい(7)
AWSにBuildとしてGomeLift https://github.com/neguse/gomelift を組み込んだサーババイナリをデプロイしてみて、セッション(GameSession, PlayerSession)の管理ができることを確認できた。長かった~~
あとはBackfillだけ試して機能的には一通り完了として、テストに使ったサーバなどのプログラムをサンプルコードとしてコミットして、ドキュメント書けばひとまず完了とできそう
一方、GameLiftにアップデートが来ていて、「GameLift FleetIQ with game server groups 」という機能がプレビュー公開されていたhttps://twitter.com/neguse/status/1245943776893255680
これを使うとServer SDKなしでサーバプロセスをGameLiftに登録できるっぽくて、つまり自分の今までやっていたことは一体…という気分になったりした
GameLiftのGo用Server SDKを作ってみたい(6)
前回からの引き続き https://github.com/neguse/gomelift 通信をWebSocketに切り替えて、GameLiftLocal(ローカル環境で動くGameLiftエミュレータ)では一通り動くような気がしてきた。切り替えはもっと手間がかかるかと思っていたけど、Engine.IOのレイヤーにしか影響がなかったのであまり手間がかからなかった。あとは本物のGameLiftに載せて動くことが確認できれば完了とできそう。
そろそろGameLift上でどんなゲームを動かしたいか考えてみる必要がありそう。とりあえずボンバーマン的な何かを動かしてはどうか。
GameLiftのGo用Server SDKを作ってみたい(5)
前回から引き続き。https://github.com/neguse/gomelift
クライアントから送ったメッセージに対してのAckを受け取るところは、思ったよりあっさり作れた。送信時にchannelを作成してmessage idをキーにしたmapにchannelを格納してchannelをreceive、受信時にmapからchannelを取り出して送信したら後続の処理が行われるという方法。
GameLiftServerSDKに付属しているGameLiftLocalサーバを使ってテストしているのだけど、1分強接続すると勝手に切断する問題が出てて、どのレイヤー(engine.io, socket.io, gameliftクライアント)が問題なのかわからないので詰まっている。たぶんengine.ioなんじゃないかという気がするのだけど、でもping/pongはできてるはずで、node用のsocket.ioサーバに接続した場合は問題なく接続が維持できてるっぽい。なぜ…
公式SDKでも同様のクライアントを組んでみて、パケットキャプチャして比較してみるとかかなぁ。でもそれだとWebSocketが使われそうなので(GomeLiftでは手抜きのためHTTP Pollingを使っている)、同じ方式を使うためにまずTransportをWebSocketに置き換えてみるのが良いかもしれない。
なかなか完成しない…
GameLiftのGo用Server SDKを作ってみたい(4)
未完成だけど、リポジトリを作った。https://github.com/neguse/gomelift
前回からSocket.IOの実装を行って、ライブラリとしての形ができつつある。結局Ackを返すためにはgomasioは使えず、自前で Socket.IOを実装している。だいぶ手抜きではあるが、一応StartGameSessionに対してAckを返して、ゲームセッションの作成が完了するところまで確認できている。
ある程度形になったあと、他にもSocket.IOクライアントのGo実装をしていた方を見かけた。 https://github.com/graarh/golang-socketio 一旦見なかったことにしてすすめる。メンテ放置されてそうだし…
サーバから来たメッセージに対するAckを返すのは割と簡単にできたが、クライアントから送信したメッセージに対するサーバのAckを再度クライアントで受け取れるようにするところがちょっと難しそう。メッセージのIDをもとにどこに返すかを覚えておく必要があるが、Goだとチャンネルを使うのがいいのだろうか。インタフェースいじらないと難しいかも。
また、受信したメッセージをデシリアライズするところがあまりきれいに書けていない。こちらももう少しインタフェースを考えないといけなそう。
だいぶ先が見えてきたので、もうひとがんばりではありそう。
GameLiftのGo用Server SDKを作ってみたい(3)
引き続き、engine.ioのクライアント実装を書いてみる。
https://gist.github.com/neguse/05a497f651c99455caa1410282caf049
実際に書いてみると理解が間違っていたところがあった。
XHRの場合、Client→Serverのデータ送信はClientからのPOSTリクエストに載っているのだけど、このPOSTのレスポンスにServer→Clientのデータ送信も(バッファに溜まっている場合)含まれるものだと思っていた。これは違っていて実際にはPOSTレスポンスには”ok”という文字だけが入っていて、Server→Clientのデータ送信はClientからのGETリクエストのレスポンスにのみ含まれる。
タイムアウト周りとかwebsocketへのupgradeとかいろいろ足りてないところはありそうな気がするけど、いったん動きそうな気持ちになってきたので引き続きsocket.ioを調べて実装していく。
GameLiftのGo用Server SDKを作ってみたい(2)
ということで、まずEngine.IOを調査してみた。 websocketだけの実装ではだめっぽいので、少なくともpolling/xhrは必要そう。
XHRクライアントに限定したら簡単に実装できそうかなあという印象。 upgrade周り含めるとちょっと面倒そう。 あと、AckはEngine.IOには含まれてないのでSocket.IOまで見る必要がありそう。
次は、簡易でいいのでEngine.IOのGoクライアントを用意してみる。
以下メモ。
https://github.com/socketio/engine.io-protocol https://github.com/socketio/engine.io-parser https://github.com/socketio/engine.io-client
TransportはEngine.IOのURLに対して接続を確立する サーバはopenに対してsid, upgrades, pingTImeout, pingIntervalを含む返信をする サーバはpingに対してpongしなければならない クライアントとサーバはmessageパケットを自由に交換する(おそらくRequest-Responseのように対になることなくそれぞれ勝手に、という意味) PollingしているTransportはソケットを閉じるためcloseを送ることができる?since they're expected to be "opening" and "closing" all the time.がよくわからん
URLは/engine.io/[?<query string>] という形式。 queryはオプショナルで、transport, j, sid, b64の4つが予約されている。 transportはTransport名で、デフォルトではpollingかwebsocket jはtransportがpollingでJSONP responseが要求されている時、JSONP response indexが設定される sidはセッションID。クライアントがセッションIDを与えられたら指定する必要あり b64はクライアントがXHR2をサポートしていない時b64=1となって、バイナリはbase64エンコードされて送られる
エンコーディング
packetとpayloadがある
packetはUTF8文字列かバイナリデータ 文字列の場合、以下のフォーマット
<packet type id>[<data>]
バイナリでも同じだけど、packet type idのところが最初の1バイトになる
パケットタイプは以下のものがある
0 open 新しいTransportが開いた時サーバからクライアントに送られる
1 close Transportを閉じる要求だが、自身のコネクションは閉じない? (TransportとConnectionの違いがわからん?)
2 ping 3 pong Pingに来たデータをそのままPongする必要ある
4 message データをコールバックに渡して呼ぶ必要がある(プロトコルというよりライブラリの話)
5 upgrade Transportを切り替える前に新しい接続方法でいけるかテストする。テスト成功したらクライアントはupgradeを送って、新しいTransportに切り替わる。
6 noop poll cycleを強制するためincoming websocket connectionを受け取った場合に使われる? (よくわからん)
payload
いくつかのパケットをつなげたもの
<length1>:<packet1>[<length2>:<packet2>[...]] つまり長さとパケットが交互に来る形 lengthは文字数で表現する packetは上で説明した通り
XHR2がサポートされていない時はbase64エンコードされた文字列として送信する それを示すためにbという文字がくっつく
<length of base64 representation of the data + 1>:b<packet1 type><packet1 data in b64>
XHR2がサポートされている時はこれ
<0 for string data, 1 for binary data><Any number of numbers between 0 and 9><the number 255><packet1 first type, then data>[...]
UTF8文字列とバイナリデータの組み合わせが送信される時は、各文字の文字コードが1バイトずつ書き込まれる?
Payloadはframingをサポートしていないtransportで使われる。pollingとか
Transport
websocket, pollingがある pollingにはjsonpとxhrがある
pollingは、クライアントからサーバに対する定期的なGETと、データ送信時のPOSTからなる
xhrではCORSレスポンスをサポートする必要がある jsonpではサーバは正しいJavaScriptを返信するよう実装する必要がある websocketではフレーミングをサポートしているためpayloadは使ってはならない
connectionは常にpolling(xhrかjsonp)で開始する WebSocketはprobeを送信するところでテストされ、probeが返ればupgradeされる