2014-10-28 70 views
2

問題

我的留言記錄,tbl_message_queue SQL表,每有一個釋放的時間戳字段(現在或將來)。新紀錄不斷被插入。計劃的.exe執行時間戳

當發佈時間戳到達時,合格記錄需要由控制檯應用程序.exe處理。處理完成後,相關記錄將從tbl_message_queue中刪除。

釋放時間戳和執行之間的滯後時間應該減少/消除。

選項#1:頻繁地輪詢

,我可以把我的.exe通過Windows Task Scheduler每隔10-15秒運行。這將包括這樣一個SQL語句:

SELECT * 
FROM tbl_message_queue 
WHERE qmsg_ts_release <= GETDATE() 

這感覺就像一個低效的,蠻力,滯後型解決方案。但這是我最熟悉的結構。

選項#2:重新計劃的SQL代理作業

我從來沒有嘗試過這一點,但似乎是它可以工作。這聽起來真的很糟糕,所以請原諒我,如果這是一個非常糟糕的主意。

我可以創建具有CmdExec Job Step一個SQL代理作業,並不斷重新安排工作:.exe文件的

  1. UPDATE qmsg_ts_release
  2. INSERT tbl_message_queue
  3. 完成下一次運行在MIN(qmsg_ts_release)

    ...我知道這聽起來真難看,但它不是積極投票,並有可能消除任何滯後。

    其他選項

    是否有任何其他選項,或者更好的解決方案,這種類型的問題?我不熟悉消息隊列體系結構中的最佳實踐。

    類似於MSMQSQL Server Service Broker這種類型的問題會更好嗎?我對其他選項很不熟悉,不確定從哪裏開始。

+0

爲什麼當您插入新記錄時,您無法創建REST服務並調用該服務。 – Steve 2014-10-28 19:05:27

+0

@聽起來好像OPs問題是記錄插入了將來的日期時間進行處理,例如,這並不是打算在插入後立即執行,而是立即在日期時間 – Kritner 2014-10-28 19:14:05

+0

@Kritner正確。 – 2014-10-28 19:51:43

回答

1

你選擇2應該工作,但你可能會得到意想不到的問題,因爲很可能是頻繁的重新安排不是SQL代理的通常用法,你必須在它無法控制。

根據您的基礎設施,您可以自己實施類似的方法。我將概述該算法。

要下手,想象與隊列你的表被填充,而不是由外部進程更改。

您的控制檯應用程序無法啓動和停止,但會一直運行。 它啓動後馬上運行查詢,以確定是在隊列前部的消息:

SELECT TOP(1) * 
FROM tbl_message_queue 
ORDER BY qmsg_ts_release 

應用程序檢查返回的消息的時間戳,看它是否是在過去還是在未來。如果是過去,應立即處理,消息「逾期」。如果有過期的消息,處理它,將其從隊列中刪除,然後重複查詢並查找隊列中可能過期的下一條消息,依此類推。

一旦所有逾期的消息處理完畢,循環停止。此時,您將來會收到該郵件的時間戳。所以,我們只需要等到將來的那一刻。發送線程睡這段時間。一旦它醒來,你就知道這是處理消息的正確時刻。然後重複整個過程。

如果計算機上的時鐘穩定且可能的等待時間不太長,則此方法運行良好。所有的時鐘和定時器都會漂移,等待的時間越長,累積的誤差就越多。

接下來要考慮的是當新項目添加到隊列中時要做什麼。向隊列中添加項目的過程/過程需要一種方法來通知處理應用程序可能需要比預期早喚醒的方法。但首先,做一個簡單的檢查。將項目添加到隊列時,可以檢查隊列中是否有任何項目具有較小的時間戳記。如果已經存在這樣的項目,您可以簡單地將新項目添加到隊列中,並且處理應用程序將照常進行。如果檢查顯示新項目的時間戳早於隊列中已有的所有其他時間戳,則意味着處理應用程序正在休眠,因此我們必須提前將其喚醒。

不幸的是,我不知道從存儲過程向外部應用程序發送信號的好方法是什麼。我想自己知道一個。在你的情況下,只要將這樣的項目添加到隊列中就簡單地重新啓動處理應用程序就足夠了。當處理應用程序重新啓動時,它會重新讀取隊列並繼續等待。

通常,將項目添加到隊列的進程/應用程序應該能夠通知工作應用程序該更改。

我剛剛發現另一個question,表示您可以使用SqlDependency來接收此類通知。

+0

感謝您的回覆。我最終採用了類似的模式。消息處理應用程序是用node.js編寫的,它有一個http端點,我將從存儲的proc或SQL觸發器中捲曲以通知已準備好的新消息。到目前爲止,它的工作非常漂亮 此外,節點應用程序將批量處理「過期」消息,而不是一個一個。看起來像一個好方法,並減少不必要的討厭。 – 2014-12-15 22:30:20

+0

另外,我選擇了node.js應用程序偶爾爲預定的消息ping SQL(而不是試圖追蹤下一次執行的時間)......當我們需要爲將來的某個點安排消息時,我們確定它不需要按時準確地完成......沒關係,如果它關閉一兩分鐘(不管頻繁輪詢是什麼)。另外,我不確定'setTimeout()'對於很長的超時/時間表有多可靠。 – 2014-12-15 22:33:12

+0

是的,這一切都取決於你的情況。長時間等待時,必須定期喚醒並調整等待時間,因爲時鐘漂移。當可靠性很重要時,我採用了混合方法。應用程序會監聽來自服務器的信號,並在接收到信號後儘快進行處理。它也很少輪詢服務器,以防信號在傳輸中丟失。因此在大多數情況下,信號立即被處理,如果信號丟失,仍然保證被處理,但有一些延遲。 – 2014-12-16 01:16:36