web-dev-qa-db-ja.com

バックグラウンドで実行されているコントローラーメソッドの進行状況を追跡するアルゴリズム

WindowsプラットフォームでPHP)にCodeigniterフレームワークを使用しています。私の問題は、バックグラウンドで実行されているコントローラーメソッドの進行状況を追跡しようとしていることです。コントローラーはデータベース(MySQL)からデータを抽出し、処理を行ってから、結果をデータベースに再度保存します。前述のプロセス全体を1つのタスクと見なすことができます。新しいタスクを割り当て、別のタスクを割り当てることができます。新しく割り当てられたタスクはキューに追加されます。コントローラの進行状況を追跡できれば、これらの各タスクのステータスを表示できます。キュー内のタスクの「保留中」ステータスを表示できるように、「実行中のタスクの場合は「進行状況」、完了したタスクの場合は「完了」。

主な問題:

今私が見つける必要がある最初のことは、コントローラメソッドが完了した実行の量の進捗状況を追跡するアルゴリズムです、そしてそれはどれだけの量を追跡することを意味しますメソッドの実行が完了しました。たとえば、 this PHPスクリプトは、カウントされている配列の進行状況を追跡します。ここでは、現在の状態と合計実行後の状態がわかっているため、進行状況を追跡できます。私の場合、それに似たものを考案することはできません。

たぶん私が達成しようとしていることはプログラム的に不可能です。それが不可能な場合は、回避策またはまったく新しいアプローチを提案してください。保留中の詳細がある場合は、それらについて言及できます。これが私の最初の投稿です。私の間違いを指摘することを歓迎します。

編集:

データベースの概要:

URLとキーワードは最初にユーザーによって入力され、link_masterと呼ばれるデータベーステーブルに保存され、keyword_masterそれぞれ。次に、このテーブルに存在するすべてのリンクからキーワードが抽出され、ユーザーが入力したキーワードと比較され、その頻度が計算されて最終結果になります。そして結果はlink_resultと呼ばれる別のテーブルに保存されます。これで、サブリンクがドメインリンクから抽出され、sub_link_masterというテーブルに保存されます。ここでも、これらのサブリンクからキーワードが抽出され、対応する結果がsub_link_resultというテーブルに格納されます。

Webページ上のリンクの数は異なる可能性があるため、レコードの数を事前に定義することはできません。 link_resultテーブルのカーディナリティのみを知ることができます。これは、キーワードとURLの数の乗算に相当します。

this resource を使用して、一度に複数のレコードを挿入します。

コントローラーの概要:

コントローラは、Webページからキーワードを抽出し、そのページに存在するすべてのリンクからキーワードを抽出します。 crawlLinkというメソッドがあります。 Rolling Curlを使用して、キーワードとWebページのコンテンツを抽出しました。結果の生成や有効なサブリンクの抽出とともにキーワードの抽出に使用したコールバック関数があります。 insertResultメソッドがあり、リンクとサブリンクの結果をそれぞれのテーブルに保存します。

はい、処理はレコード数に依存します。レコード数が多いほど、実行に時間がかかります。

このシナリオを考えてみましょう:

ドメインリンクの数= 1

キーワード数= 3

生成されたドメインリンク結果の数= 3(質問に記載されている3 x 1)

生成されたサブリンクの数= 41

サブリンクの数結果= 117(41 x 3 = 123ですが、一部のリンクは無効または検索できません)

上記のプロセスが完了するまでにかかるおおよその時間= 55秒。

上記の結果は、単一のリンクに対するものです。上記の結果がデータベースに保存されるまでの進行状況を追跡したいと思います。すべての結果が保存されると、タスクは完了します。結果が保存されている場合、タスクは進行中です。この進捗状況を追跡する方法がわかりません。

4
SilentAssassin

リンクとキーワードの数が未定であるため、完了率を正確に追跡することはほぼ不可能ですが、深さで大まかなステータスを表示することは可能です。たとえば、最初の深さはトップレベルから処理されたURLです。

(100 /合計ページ数)*処理されたページ数=%現在のステータス

総ページ数= master_linksからcount()を選択
処理されたページ= master_linksからcount(
)を選択します。ここでprocessed = trueです。ページを処理したら、データベースにフラグを設定するだけです。

(これは、配列にdb値を入力し、ページを処理するときにインデックス値を使用することで、同様に行うことができます)

注:各レベルのステータスのみを取得できます。すべてのmaster_linksがクロールされるまで、sub_linksのクロールを開始しないでください。これにより、URLクロールの重複を回避でき、合計時間への影響を最小限に抑えることができます。

下の図の四角は、処理が必要なページを表しています。各ボックスの中には、左から右に処理した場合の完了率が表示されます。これは説明のためであり、パーセンテージはこれに基づいています。

Interative image

出力には、そのレベルの完了率が表示されます。
例えば。マスターリンク40%完了
または
例えば。マスターリンク100%
サブリンク49.8%

これでも、キーワードとリンクの実際の密度を推測できないので、進行状況を示すのに十分な情報が得られます...

1
afxdesign

バックグラウンドプロセスがそれまでの場所を知っているので、ループサイクルごとに1回データベースにレポートできることを提案したのは、怠惰なプログラマーですか?

私がそれを尋ねる理由は、私がかつて他のデータベースからレコードをインポートすることを仕事とするバックグラウンドプロセスを書いたからです。データベース、必要なテーブルは、command_queueと呼ばれるテーブルに記載されていて、バックグラウンドタスクが新しいトランザクションを開始するcommand_queueに追加された古いシステムの行ID、処理対象のコマンドを表す行をロックし、システムに指定されたID番号(これは別のテーブルに登録することで取得しました)、作業を開始し、新しいテーブルを更新して古いIDを新しい行データに追加し、command_queue行を完全にドロップしてトランザクションをコミットします。

そうすれば、一度に複数のスレッドを実行し、停電に対処し(万が一発生した場合)、あらゆるレベルの大惨事から回復することができます。同様に、やるべきことがたくさんある場合、特に家に帰ってサーバーがアイドル状態のときに、たくさんのスレッドでボックスを独占することができました。

コードイグナイターでは、実行するために残っているコマンドの数と、コマンドリストに記載されているデータベース内のテーブルのサイズを出力するビューがありました。 (各ワーカースレッドに停止コマンドもありました)。

いくつかのJavaScriptの良さを使用すると、速度計や円グラフなどでビューが非常に印象的に見えました。マネージャーはそのようなものを見たいと思っていました。

プロセスが非常に詳細に教えてくれたので、彼らが何をしているかを理解する必要はありませんでした。各プロセスで(切り離された)画面インスタンスを使用しているように見え、出力を確認できましたが。毎秒数千人のユーザーがいる場合でも、危機、データ損失、中断がまったくないプロジェクトを作成する最初のコーダーになりたいと思ったのは助かりました。

編集 screenを使用したくない場合、PHP --enable-pcntlを使用してコンパイルした場合、pcntl_forkを使用してバックグラウンドプロセスを作成し、setproctitleを使用して進行状況を記録します。次に、プロセスリストを表示すると、プロセスの名前が変更されて手がかりが得られます。

サーバーで実行中のPHPタスクの進行状況を監視するには3つの方法があります。

WebSocketを使用してリアルタイムで監視する

55秒のタスクではやり過ぎの可能性があります。

Ratchet を使用すると、Javascriptを介して接続できるソケットサービスを作成し、PHPデータをリアルタイムでブラウザに送信することができます。ソケット接続は維持されます。 JavaScriptソケットが接続されている限り存続します。

時限AJAX呼び出し

定期的にプルサーバーを呼び出して、現在のタスクのプロセスに関するデータを受信します(これは私がいつも行っていることです)。リクエストは、現在の進行状況を含むJSON応答を返します。

$.ajax({url: "/monitor_task?task_id=3"}).done(function(data) { alert(data); });

進捗データの共有

サーバー側で進行状況をタスクに共有させる方法は2つあります。

  1. 進行状況をデータベーステーブルに書き込み、monitor_taskアクションはその値を読み取ります。
  2. 共有メモリオブジェクト (ファイルのように)を使用し、monitor_taskそのファイルを読み取ります。

現在のページを更新する

現在の進行状況を示すビューを作成し、間隔を空けて メタリフレッシュ を配置します。これにより、ブラウザは常にその間隔でページを更新するようになります。

<meta http-equiv="refresh" content="5" />
0
Reactgular