6

私は、Heroku上で動作するノードJSで書かれたWebサーバを持っています。サーバーにはWebサーバープロセスとワーカープロセスがあります。 Webサーバーは、RabbitMQキューを介して正常にワーカーにメッセージを送信します。ワーカーは処理されたデータをWebサーバーに正常に返します。ランダムに生成されたUuidを使用してメッセージを追跡し、適切なメッセージが正しい元のメッセージとペア設定されていることを確認します。メッセージキューアーキテクチャ(クライアントからWebサーバへのクライアントとバックへ)

別のプロジェクトでは、クライアント(ウェブサイト)がウェブサーバーと正常に通信しています。今、私は一緒に2つを置く必要があります。

は、どのように私はそれを行うことができます。

  1. クライアントは、HTTP POSTを送信します。
  2. Webサーバーは要求を受信し、要求をメッセージキューに渡します。
  3. ワーカーはリクエストを処理し、Webサーバーに戻ります。
  4. Webサーバーはクライアントに正しいデータを返し、クライアントはその応答を元の要求に関連付けることができます。

ステップ4はどこにいるのですか。クライアントがデータを準備するまでWebサーバーを継続的にポーリング(HTTP POST?)する必要があると私はどこか読んでいると思います。私はステップ1の後にクライアントに応答する必要があると思うので、要求はタイムアウトしません。任意のアイデアやアドバイスをいただきありがとう

ブロック図: enter image description here

+0

これは状態の更新が必要な長期実行プロセスですか?または、これは、バックエンドからの非常に迅速な応答です。元のHTTP要求では、そのバックエンドサービスからの応答を取得する必要がありますか? –

+0

私はそう思う状況の更新。場合によってはバックエンドは30秒+になります。 – user3320795

+1

ええ、1秒以上の間、状態の更新が必要です。私はまもなく答えを発表します。 –

答えて

5

あなたが何をする必要があるかの短いバージョンは、双方向メッセージングです。あなたのWebアプリケーションは、メッセージプロデューサとメッセージコンシューマである必要があります。バックエンドサービスにも同じことが言えます。

HTTPリクエストが到着すると、WebサーバーはRabbitMQを通じてメッセージを送信します。バックエンドは、将来、ある時点でそれをピックアップします。その間、ウェブサーバは何かが起こっていることをHTTPリクエストを介して返信し、後でユーザに通知する。

あなたは急行を使用している場合、それはこのようなものになります。


var router = express.Router(); 
router.post("/", postJob); 

function postJob(req, res, next){ 
    req.session.inProgress = true; 

    var msg = { 
    job: "do some work" 
    }; 

    jobSender.sendJobRequest(msg, function(err){ 
    if (err) { return next(err); } 
    res.render("some-response"); 
    }); 
} 

をこのコードは、jobSenderがRabbitMQの間でメッセージを送信する方法でカプセル化されたオブジェクトのいくつかの種類のもののように、仮定の多くを作ります。私はあなたがすでに言ったことに基づいて、メッセージを送信する詳細を記入できると確信しています。

重要なことは、HTTPリクエストハンドラがRabbitMQを介してメッセージを送信してから、HTTPレスポンスをWebブラウザに送信することです。

この時点で、ブラウザは必要な処理を行うことができます。

バックエンドには、他のサービスはそれが仕事だ完了したとき、それは2つのうちの1つ実行する必要があります。)

1をWebサーバーが持っているものの仕事を知っているように、どこかに共有データベースを更新RabbitMQの

オプション#1を介して、行われて(とステータス読むことができます)

または

2)バックWebサーバにメッセージを送信することは、常に様々な理由のために良いオプションではないかもしれません。あなたの質問から、あなたはオプション#2をとにかくしたい。

2番目のキュー(Webサーバーが待機しているキュー)が必要です。 Webサーバがこのキューからメッセージを受信すると、受信したステータスで自身のデータベースを更新します。

このステータスは、「完了」、「進行中」、「エラー」、またはそれ以外のものが表示されます。

たとえば、「ジョブステータス」というメッセージが表示されている場合は、ステータスメッセージを受け取るために「JobStatusReceiver」という抽象概念があるとします。

このような単純なモジュールは、ジョブ・ステータス・キューからメッセージを受信し、ステータスで、これはウェブサーバで何が起こってもよいことが


var JobStatusReceiver = require("./jobStatusReceiver"); 
var someDataObject = require("someDataObject"); 

var jobStatus = { 

    listen: function(){ 
    var receiver = new JobStatusReceiver(); 
    receiver.receive(function(statusMessage){ 

     someDataObject.status = statusMessage.status; 
     someDataObject.data = statusMessage.data; 


     someDataObject.save(); 
    }); 
    } 

}; 

module.exports = jobStatus; 

ノートをローカルデータベースを更新するが、それはの一部ではありませんでしたHTTPリクエスト。メッセージはRabbitMQを介してJobStatusReceiverとともに送信され、HTTP要求の一部ではありません。

someDataObjectオブジェクトは、yoruデータベースのオブジェクトである可能性が高いため、データベースに戻すことができます。

最後に、完了した操作をユーザーに通知する必要がある部分は、さまざまな方法で発生する可能性があります。

一般的に言えば、有効な応答を探すために、数秒ごとにWebサーバー上のHTTP APIへのAJAX呼び出しを行うのはかなり簡単です。ブラウザ側で

、これはのような単純なものでした:取り扱い、エクスプレスアプリで


var timer = setInterval(function(){ 

    $.ajax({ 
    url: "/api/check-status", 
    success: function(data){ 
     if (data.complete){ 
     clearInterval(timer); 
     doSomeOtherWork(data); 
     } 
    }) 
    }); 

}); 

し、再び「/ APIを/チェック状態」を、あなたは同じ「someDataObject」モデルを使用しますステータスを確認する:


var someDataObject = require("someDataObject"); 

var router = new express.Router(); 
router.get("/", checkStatus); 

function checkStatus(req, res, next){ 

    someDataObject.load(function(err, someData){ 
    if (err) { return next(err); } 

    res.json({ 
     complete: (someData.status === "complete"), 
     data: someData.data 
    }); 

    }); 

} 

これはうまくいけば正しいパスを取得します。私が残した細部はたくさんありますが、欠けている部分を埋めることができればうれしいです。

...

P.S:私は私のRabbitMQ 4 Devsトレーニングコースでは、タイマーのステータスの更新をチェックするブラウザを除いて、このすべてをカバーしています。これは、RabbitMQとNode.jsを起動して実行するための完全なパッケージです

+0

それは良いアプローチです、私はそれがプールの代わりにパブ/サブパターンと混在することができると思います。 – Sebastian

関連する問題