[英]Queuing long running tasks in a web application
用戶可以在我們的Web應用程序上執行操作,該操作需要100毫秒到10秒,我希望立即將結果返回給瀏覽器,然后在任務完成處理后將結果顯示給用戶。 該操作正在同步來自第三方的數據,並實現為類庫(DLL)。
通常建議使用像RabbitMQ或MSMQ這樣的隊列,並讓一個工作人員將結果寫入數據庫,該數據庫由來自瀏覽器的AJAX請求輪詢以檢查更新。
然而,目標是減少延遲,使其盡可能地同步運行任務,同時能夠處理長時間運行的任務中的峰值,而不會影響網站的其余部分。
如何構建后端? 在我看來,過程將是:啟動任務,以最小延遲運行任務,通知最終用戶任務完成(ASAP)並最終在瀏覽器中顯示結果。
例子
使用http://www.xml-sitemaps.com/生成站點地圖使用分塊傳輸編碼每秒發送一個<script>
標記來調用Javascript函數來更新具有最新狀態的頁面。
使用https://www.ssllabs.com/ssltest/檢查SSL證書似乎刷新了整個頁面的更新狀態。
這種情況比較簡單,我根本不建議投票。
考慮使用常規的Ajax方法:頁面的一部分能夠在沒有頁面其余部分的情況下刷新。 因此該部分(ajax部分)本身是同步的,但是從整個頁面的角度來看是異步的(因為它刷新而不重新加載整個頁面)。
因此,當需要計算該信息時,頁面的ajax部分將作為常規請求提交。 完成請求處理后,頁面的該部分可以立即訪問響應並顯示結果。
優點是您沒有輪詢開銷,並且結果會立即顯示在屏幕上(盡快 - 如您所知)。 此外,只有一個請求正在處理此問題,而不是輪詢時可能錯過的幾個請求。
您是否考慮過將WF4與SignalR結合使用?
我們使用WF4來處理后端處理,它的表現相當不錯。 我們將請求存儲在作業請求表中,工作流引擎(我們編寫的在后端運行wf4的服務)獲取請求,處理工作,然后將作業標記為已完成。
然后可以使用SignalR通知客戶端作業已完成。 擴展相對容易(因為我知道'簡單'總是充滿細節),因為你可以提供更多服務來處理請求。 每個引擎都會將請求標記為正在處理,以便其他引擎不會將其提取。
我在大型項目中使用了wf4,這些項目的服務負載均衡,我們能夠獲得非常不錯的吞吐量。
FWIW,如果您真的不想投資基於全規模隊列的解決方案,您可以利用TPL + SignalR (或任何此類Comet庫)來處理長時間運行的請求並向客戶端發送反饋。
所以這個想法是:
這樣的事情(使用TPL和SignalR):
//服務器
public class MyHub : Hub
{
public void Start()
{
var longRunningTask = Task.Factory.StartNew(() =>
{
var someService = new someService();
// do stuff
someService.doSomething();
Clients.All.longRunningTask(<data>);
}, TaskCreationOptions.LongRunning);
}
}
// initiating from your asp.net page (codebehind or via ajax or any which way)
new MyHub().Start();
//客戶
var hub = $.connection.myHub;
hub.client.longRunningTask = function (data) {
// do something with data
}
這是非常低的延遲,不涉及排隊,並允許您在它們出現時推送更新(只需調用Clients.All.longRunningTask
將更新推送到客戶端)。
參考文獻:
這可能有點簡單,但最簡單的方法可能是對客戶端進行長時間輪詢。
即:在GET查詢中發送工作請求,獲取令牌。 然后立即請求該令牌的結果,讓服務器阻止響應。 如果請求超時,請重新啟動它。 在服務器端,只需在等待任務完成時阻塞該線程。 即使是最具侵略性的負載平衡器也可以提供長達一分鍾的掛起時間。
通過在客戶端上控制隊列,您可以通過使用jQuery.ajaxPrefilter (或任何其他適合您的方法)禁用提交或人為限制未完成的服務器請求數量,從而更輕松地防止客戶端進行攻擊。
或者你可以投資一個websocket通信層,這樣服務器就可以主動ping客戶端,但是長輪詢是套接字的常見后備,這對於這個用例來說已經足夠了(我認為 ......取決於這些用戶的頻率/多少)你需要這樣的電話)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.