3

Google App Engine を使用してチャット アプリケーションを作成しています。チャットをログに記録したい。残念ながら、Google App Engine データストアでは 1 秒に 1 回しか書き込みできません。この制限を回避するために、memcache を使用して書き込みをバッファすることを考えていました。データが失われないようにするために、定期的に memcache からデータ ストアにデータをプッシュする必要があります。

Google アプリでこのようなジョブをスケジュールする方法はありますか? エンジン?それとも、これについて完全に間違った方法で行っていますか?

私は API の Python バージョンを使用しているので、Python ソリューションが優先されますが、Java ソリューションを Python に変換できるほど十分に Java を知っています。

4

5 に答える 5

2

memcache でデータを失う危険があるため、間違った方法のように思えます。

1 秒に 1 回、1 つのエンティティ グループに書き込むことができます。

個別のエンティティ グループを非常に迅速に作成できます。したがって、データをどのように構造化するかによって大きく異なります。たとえば、チャット全体を 1 つのエンティティに保持した場合、そのチャットは 1 秒に 1 回しか書き込むことができません。そして、あなたは1MBに制限されます。

チャットのメッセージごとに個別のエンティティを作成する必要があります。非常に迅速に作成できますが、ログのために、すべてのメッセージをまとめる方法を考案する必要があります。

編集メッセージごとに 1 つのエンティティを使用するとコストがかかりすぎるという Peter Knego の意見に同意します。彼のバックエンドの提案も非常に優れていますが、アプリが人気がある場合、バックエンドはそれほどうまくスケーリングしません.

シャーディングを避けようとしていましたが、必要になると思います。シャーディングに慣れていない場合は、https ://developers.google.com/appengine/articles/sharding_counters を読んでください。

シャーディングは、会話内のすべてのメッセージに対して 1 つのエンティティを記述することと、メッセージごとに 1 つのエンティティを記述することの間の中間になります。メッセージを多数のエンティティ間でランダムに分割します。たとえば、メッセージを 3 つのエンティティに保存する場合、5x/sec と書くことができます (ほとんどの人間の会話はそれより速くなるとは思いません)。

取得時に、3 つのエンティティを取得し、メッセージを時系列でマージする必要があります。これにより、コストを大幅に節約できます。ただし、マージを行うにはコードを記述する必要があります。

もう 1 つの利点は、会話の制限が 1MB ではなく 3MB になることです。

于 2012-04-17T03:48:40.390 に答える
2

エンティティ グループの書き込み/更新の制限を回避するには (親のないエンティティは独自のエンティティ グループであることに注意してください)、すべてのチャット メッセージに対して新しいエンティティを作成し、エンティティが属するチャットを参照するプロパティを保持します。

次に、クエリを介してチャットに属するすべてのチャット メッセージを検索します。しかし、新しいメッセージごとにすべてのユーザーに対してクエリを実行する必要があるため、これは非常に非効率的です。

したがって、上記のアドバイスに従いますが、さらに次のことを行います。

  1. バックエンドを調べます。これは、チャット メッセージをメモリに集約できる (そしてすぐにまたは定期的にデータストアにフラッシュする) 常時オンのインスタンスです。ユーザーが最新のチャット メッセージをリクエストすると、それらはすでにメモリに保存されており、即座に提供されます(Datastore を使用する場合に比べて時間とコストを節約できます)。バックエンドは 100% 信頼できるわけではなく、時々ダウンする可能性があることに注意してください。それに応じて、データストアへのチャット メッセージのフラッシュを調整してください。

  2. Channels API を確認してください。これにより、新しいチャット メッセージがあるときにユーザーに通知できます。こうすることで、新しいチャット メッセージのポーリングを回避し、数やリクエストを抑えることができます。

于 2012-04-17T08:43:16.110 に答える
1

プル タスクを使用しないのはなぜですか? タスク キューに慣れていない方には、この Google ビデオを強くお勧めします。最初の 15 分間は、状況に当てはまる可能性があるプル キュー情報について説明します。メッセージごとの更新を伴うものは、非常に高価な re: database ops になる可能性があり、インデックスが含まれている場合、これは非常に悪化します。ビデオリンク: https://www.youtube.com/watch?v=AM0ZPO7-lcE&feature=player_embedded

ユーザーがオンライン ハンドラーでチャット エンティティを開始したときにチャット エンティティをセットアップし、チャット パーティにエンティティ ID を返すだけです。ID とメッセージをプル キューに送信し、チャット エンティティの TextProperty 内でメッセージをシリアル化します。プル キューの cron を 1 秒に 1 回以上スケジュールすることはほとんどないため、エンティティの更新の制限を回避できます。最も重要なことは、データベースの操作が大幅に削減されることです。

于 2012-04-17T16:06:45.957 に答える
0

チャットセッションをエンティティグループとして使用し、チャットメッセージを保存することで問題ないと思います。
この1秒に1回の制限は現実的ではありません。より高いレートで更新/保存でき、常に実行できます。問題はありません。memcacheは揮発性であり、実行したいことに対して間違った選択です。書き込み速度で問題が発生し始めた場合は、データを保存するためのタスクの設定を開始できます。

于 2012-04-17T12:42:28.747 に答える
0

I think you could create tasks which will persist the data. This has the advantage that, unlike memcached the tasks are persisted and so no chats would be lost.

when a new chat comes in, create a task to save the chat data. In the task handler do the persist. You could either configure the task queue to pull at 1 per second (or slightly slower) and save each bit of chat data held in the task persist the incoming chats in a temporary table (in different entity groups), and every have the tasks pull all unsaved chats from the temporary table, persist them to the chat entity then remove them from the temporary table.

于 2012-04-17T09:50:02.687 に答える