3

私は appengine のジョブ ディスパッチャに取り組んでいます。デフォルトのスケジューラは常に、すべての作業を実行する 3 ~ 4 個のインスタンス、数千のタスクを実行するオーバーフロー インスタンス、またはほんの数個のタスクを実行し、そこに座って CPU を燃焼させます。何もしない。

私のタスクには、さまざまなサイズのドメインのジョブを処理することが含まれます。スループットが非常に高い場合もあれば、1 人のユーザーが 10,000 モデルを更新する場合もあります。通常の appengine タスク スケジューラを緩くすると、次の 2 つの方法で失敗します。1) バックエンドがシャットダウンしません。メモリが上限に達すると、Java gc がインスタンスをスラッシュさせ、ほとんどゾンビのように振る舞いますが、シャットダウンすることはありません。 2) 多くのドメインには、処理に他のすべてのユーザーよりもはるかに時間がかかる単一のユーザーがいて、これにより、ドメインの残りの部分が終了した後もバックエンドが存続し続けます。

これらのタスクは 1 日を通して実行する必要があり、ファンアウトを処理するには複数のバックエンドが必要です。そのため、すべてを B8 にダンプして 1 日とは言えません。そのため、タスクがバックエンドにどのように割り当てられるかを管理するディスパッチャーが必要です。

ここで、CPU 時間を数分間節約するためだけにすべてのタスクでデータストアの操作にお金を払いたくないので、私の攻撃計画は {批判してください} RAM で静的な ConcurrentHashMap を使用し、各 run() を試しに開始することです、すべての延期されたタスクに、起動時に [hashcode, startTime] を入れ、最後に remove(hashcode) を入れます。メソッド BackendCounter.addToLiveMap(this); にラップされた、ジョブを実行しているバックエンド インスタンスごとに 1 つのそのようなマップがあります。.size() は、そのバックエンドで実行中のジョブ数の現在の合計として機能します {10 分以上実行されるゾンビ ジョブを検出するためのタイムスタンプ付き}。ジョブ ディスパッチャーは、インスタンスごとにワーカー スレッドを起動して、そのインスタンスで実行されているジョブ (それ自体を除く) の数を監視し、memcache にランク付けされたリストを保持して、どのインスタンスでいくつのタスクが実行されているかを確認できます。1 つのインスタンスが X 個のライブ タスクのしきい値を下回った場合、延期するオーバーフロー インスタンスを選択し、メソッド BackendCounter.addToLiveMap(this) に例外をスローさせて、ジョブに新しいインスタンスにスケジュールするように指示することができます {ChangeInstanceException# getNewTarget()}. このようにして、ほとんど使用されていないインスタンスが新しいジョブを取得するのを防ぐことができるため、シャットダウンする機会があり、一部の memcache op に対してのみ支払いが行われ、ファンアウトは静的マップへの書き込みと削除のみが支払われます。

これにより、インスタンス時間のキラーである問題 2 が解決されます。1 つのインスタンス (通常はインスタンス 0 と 1) がメモリのピークに達してダークサイドに向かうのを防ぐ方法の問題については、2 つの選択肢の間で迷っています。

一方では、予想される BackendCounter.addToLiveMap(this) throws ChangeInstanceException への呼び出しを使用して、単純にメモリをチェックできます。

if (((float)Runtime.getRuntime().freeMemory() / Runtime.getRuntime().totalMemory())<0.9) throw new ChangeInstanceException(getOverflowInstance()); この素朴なアプローチは、メモリの制限に近づいているインスタンスに、すべての新しい作業を別の場所に送信するように指示するだけです。

一方、オーバーフローを処理するためにインスタンス 0 と 1 を保持できます {そして、シャットダウンする機会を与えるために 2 つのうちどちらが新しいジョブを取得するかを切り替えます}。その後、ファンアウトをインスタンス 2+ に送信します。つまり、10 個または 15 個のジョブを並行して処理します。ファンアウトは非常に一貫しており、数分しかかからないため、インスタンス 2、3、および多くても 4 をオンにする必要があり、別のインスタンスがより多くの負荷を受けている間にオフにする時間が与えられます。私が恐れている唯一のことは、ジョブがあるインスタンスから別のインスタンスにバウンスし始めた場合です。これはおそらく、ChangeInstanceException のスローをスキップするリダイレクト ヘッダー制限で克服できます。

どんな考えやアドバイスも大歓迎です。

4

0 に答える 0