web-dev-qa-db-ja.com

Webアプリケーションバックエンドで時間ベースのイベントを処理する方法

私は現在、小規模なWebサービスの設計に取り組んでおり、次の機能があります(簡略化)。

一部のユーザーアクションの後、待機期間(30秒から40時間の範囲)があり、それが経過すると、ユーザーが待機期間中にキャンセルしない限り、サーバーはタスクのデータベースエントリを更新する必要があります。実行されるタスクは非常に単純で、計算はわずかですが、遅延させる必要があります。

そして、私はこれを行う方法がわかりません...

同じような状況が一部のブラウザーベースのゲームで発生することを知っています。建物をアップグレードして、建物が完成した後にボーナスを獲得することはできますが、この機能がどのように実現されるかはわかりませんでした。それで、私の質問は、バックエンドのそのような問題に対処する「最先端の」方法、またはまったく何か方法があるのですか?

6
Wikiii122

これにはいくつかの方法があります。最終的に何をするかは、サーバー側のスタック、サーバーに対する権限、および遅延イベントに必要な副作用の性質によって異なります。

私がそれらを見ると、あなたのオプションは:

  • 「埋め込まれた」スケジュールされたタスク。サービスのようなバックエンド技術(ノードサーバーのような)を使用している場合は、アプリケーションにタイムアウトを設定できます。また、場合によっては、ノードの場合と同様に、個々のイベントごとにタイムアウトをスケジュールすることもできます(ケースでイベントキューを処理するよりも効率的であることが判明した場合)。
  • 個別のcronジョブ、windowsタスク、またはバックグラウンドプロセス、デーモン、またはサービスcronジョブは、1分あたり最大1回実行できる必要があります。 Windowsタスクは最大5分ごとに実行できます。バックグラウンドジョブ、デーモン、またはサービスは、スリープ/待機/タイムアウトを使用して、さらに短い間隔で処理を実行できます。
  • クライアント主導のイベント処理。データがアクティブに使用されていないときに副作用が必要ない場合(たとえば、値を気にするすべてのユーザーがログアウトしている場合)、は、特定の値を計算したり、クライアント要求中に必要に応じてイベントを処理したりすることで、定期的な「維持」ジョブのオーバーヘッドと複雑さを回避できます。たとえば、各リクエストfromおよびaboutUserXに対して、「キュー」event_fire_time <= nowおよびevent_user = UserX、およびそれらのイベントを「完了」します。

すべてのシナリオで、イベントコードが処理しているレコードを必ずロックしてください(DBMSを使用している場合はトランザクションを使用)。

6
svidgen

タスクを、たとえば以下の情報とともに、dbテーブルに保存する必要があります。

  • time_to_execute:タスクが設定されたときのタイムスタンプ+秒単位の遅延
  • to_do:やるべきこと(これはバックエンドで理解できる必要があります)
  • executed:タスクがすでに実行されている場合は1、それ以外の場合は0(デフォルト)

次に、スケジューラが必要です。cronを使用できます。これにより、定期的に、たとえば毎分、バックエンドのエンドポイントにクエリが送信され、スケジュールされたタスクを含むdbテーブルにクエリが送信されます。このための疑似コードは次のようになります。

my_backend_endpoint_callback():
    for task in tasks:
        if not task.executed and time_to_execute > time.now():
            result = execute_my_task(task.to_do)
            if result == 0:
                # task was properly executed
                task.executed = 1

その後、トレースを保持するかどうかに応じて、実行されたすべてのタスクを削除する別のループを作成できます。

2
Jivan

簡単な方法は、データベースに保留中のタスクテーブルを置くことです。

タスクを作成するには、アクション時間と、タスクの処理に必要なその他のデータを含む行をテーブルに追加します。テーブルに定期的にクエリを行い、期限が到来したタスクをアクションし、完了したタスクをテーブルから削除するバックグラウンドスレッドがあります。

これを「最先端」とは言いませんが、必要なことを行うための比較的単純で信頼性の高い方法です。

タスクが完了したら、ユーザーに通知する必要がありますか?すべてのクライアントがサーバーへのWebSocket接続を維持する必要があり、プッシュ通知を行うことができるため、状況は多少複雑になります。

1
paj28