簡體   English   中英

在Web應用程序中排隊長時間運行的任務

[英]Queuing long running tasks in a web application

用戶可以在我們的Web應用程序上執行操作,該操作需要100毫秒到10秒,我希望立即將結果返回給瀏覽器,然后在任務完成處理后將結果顯示給用戶。 該操作正在同步來自第三方的數據,並實現為類庫(DLL)。

通常建議使用像RabbitMQ或MSMQ這樣的隊列,並讓一個工作人員將結果寫入數據庫,該數據庫由來自瀏覽器的AJAX請求輪詢以檢查更新。

然而,目標是減少延遲,使其盡可能地同步運行任務,同時能夠處理長時間運行的任務中的峰值,而不會影響網站的其余部分。

如何構建后端? 在我看來,過程將是:啟動任務,以最小延遲運行任務,通知最終用戶任務完成(ASAP)並最終在瀏覽器中顯示結果。

長期任務。致謝:海石。資料來源:<code> http://haishibai.blogspot.co.uk/2012/12/dealing-with-long-running-jobs.html </ code>

例子

使用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通知客戶端更新

這樣的事情(使用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將更新推送到客戶端)。

參考文獻:

SignalR 2入門

這可能有點簡單,但最簡單的方法可能是對客戶端進行長時間輪詢。

即:在GET查詢中發送工作請求,獲取令牌。 然后立即請求該令牌的結果,讓服務器阻止響應。 如果請求超時,請重新啟動它。 在服務器端,只需在等待任務完成時阻塞該線程。 即使是最具侵略性的負載平衡器也可以提供長達一分鍾的掛起時間。

通過在客戶端上控制隊列,您可以通過使用jQuery.ajaxPrefilter (或任何其他適合您的方法)禁用提交或人為限制未完成的服務器請求數量,從而更輕松地防止客戶端進行攻擊。

或者你可以投資一個websocket通信層,這樣服務器就可以主動ping客戶端,但是長輪詢是套接字的常見后備,這對於這個用例來說已經足夠了(我認為 ......取決於這些用戶的頻率/多少)你需要這樣的電話)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM