Djangoとgevent-socketioを使用して、リアルタイムマルチプレイヤーゲームに取り組んでいます。私はいくつかの問題に直面しています:
X秒(〜4秒)ごとに接続されたプレーヤーにゲーム状態の更新を送信する必要があるので、基本的に、計算を実行して接続されたプレーヤーに新しいゲーム状態を送信する関数をx秒ごとに実行する必要があります。これを達成する最も簡単な方法は何ですか?ここではcronを使用するのが良い選択ですか、それともセロリや...などの他のツールを探す必要がありますか?
また、関数は一部のデータを操作する必要があります。関数が実行されるたびにデータベースにクエリを実行するのは良い考えではないようです。ゲームデータ(ゲーム中に頻繁に更新される)はどこに保存できますか?
最初の質問について:
ゲームの種類が許せば、ラウンドロビン戦略をアドバイスします。 更新間の最大時間を接続されているプレーヤーの数で割ることにより、取得した等間隔でゲームの状態を送信し、状態を単一の接続されたプレーヤーへの一連の更新。
@ Kolyunyaの回答へのコメントの一部で言及されているように、CPUスパイクによるパフォーマンスの問題を回避するように。
余談ですが、この戦略では次の最適化が可能です。
一定の時間に接続されているプレーヤー数に更新間の最大時間を適応させる:
プレーヤーの数が少ない場合は、最大更新時間も低く設定できるため、少数のプレーヤーがより高速に更新できます。
実装については、@ Brianの2番目のヒントで、これが strategy がニーズに合っているかどうかを確認します。
2番目の質問について:
ゲームの状態をメモリに保存する必要があります redis は当然の選択です。
#2に関して:ゲームの状態が変化するたびにデータベースにクエリを実行して更新することは、適切なデータベースを使用している限り、非常に良いアイデアです。
明らかに、MySQLのようなものは、そのような場合には潜在的である可能性があります(またはそうではないかもしれません。それは、ゲームの状態のサイズとモデルの複雑さに依存します)。時間のあるときにのみディスクにデータを格納する、オーバーヘッドの少ないNoSQLデータベースを使用すると、十分なパフォーマンスが得られます。ただし、耐久性は低下します。クラッシュすると状態が失われる可能性があります。
もちろん、状態が変化しなかった場合、クライアント要求ごとにゲーム状態全体を再計算するのはばかげたことです。 cache計算が難しい共通部分と、「戦場の霧」のようなクライアント依存部分のみを再計算できます。
これは、階層型データベースのアイデアにつながります。ユーザーの在庫や金銭的残高などの最も重要なものは、PostrgesやMongoDBなどの耐久性のあるデータベースに保存する必要があります。 (ところで、現代のPostgresの機能と、Mongoへの書き込みの速度は驚くべきものです。)戦場の霧、飛行中のミサイルの位置など、頻繁に変化するものは、Redisのようなキャッシュレイヤーに存在する必要があります。またはMemcachedであり、不可逆的なアクションが発生した場合(ミサイルがヒットした場合)にのみ永続ストアに保存されます。現在のゲームティックに関する最も重要な事実は、一度計算され、簡単なクエリとクライアントへの即時送信を可能にする形式で、キャッシュレイヤーに保存される必要があります。
キャッシングレイヤーの状態は、壊滅的な結果を招くことなくクラッシュによって失われる可能性があり、永続データから再計算できます。
もちろん、これはどういうわけか複雑です。原油のプロトタイプが機能するまでは、それを選択しないでください。パフォーマンスの問題が発生し始め、これらの問題がデータベースに関連していると特定されるまで、耐久性のあるストア(Postgresなど)のみを使用してください。次に、何をキャッシュするかが表示されます。
一般的な言語に依存しない考え方は、オブザーバーパターンを使用して接続されたある種の「Timer」オブジェクトと「GameStateSender」オブジェクトを持つことです。タイマーはx秒ごとにイベントを送信し、送信者はこれらのイベントをリッスンし、それらを受信するとデータを送信します。
*実装についてはSOで話し合う必要があります
プッシュテクノロジーの使用をお勧めします。たとえば、'long polling'
接続。これらの接続でクライアントがalways keep alive
そしてサーバーはそれを受け取ります。
これで、クライアントは応答を待ち続け、サーバー側では、サーバーはアクションを待ちます。サーバーがアクションを受信するとすぐに、クライアントの要求に応答し、クライアントがサーバーから応答を受信するとすぐに、サーバーに再度要求します。ループ。
したがって、この手法では、特定の時間にリクエストを送信する必要はなく、遅延も発生しません。
Use frameworks like
:Twisted