1,需求描述
某項目收集上千個設備的數據,前端程序采集數據后寫入數據庫。
當某些特定數據滿足觸發條件時,需要后端程序即時發起業務處理流程。
2,技術方案
2.1 定時掃描數據庫
顯然,可以采用后端程序定時掃描數據庫的辦法。此法簡單易行,但缺點也很明顯,不能滿足業務處理的即時性要求。
如果掃描周期過長,則響應延時差;如果掃描周期過短,則數據庫壓力加大,可能波及整個系統。
2.2 數據庫驅動業務
方案2.1是由后台程序主動發起,因此無法發起時機是隨機的,相當於在瞎猜。
本方案則采用由數據庫發起的思路,這也是很容易想到的。因為數據庫對於數據是否變化,以及變化是否滿足業務發起條件能在第一時間內加以判別。
采用表觸發器可以在數據提交后判斷是否需要后台程序處理。如果需要,就向后台程序發送消息,后台程序收到消息后,立即開始執行業務流程。這樣就實現了由數據驅動的業務流程。
該方案避免了數據掃描,對數據庫壓力最小,業務處理響應也是即時性的。
3,SQLServer+Delphi實現
以下以SQLServer2005和Delphi7為例,具體實現由數據驅動的業務流程。主要步驟包括:
數據庫表建立觸發器,在觸發器中發送消息
后台程序中接收消息,執行處理。
3.1 數據庫發送消息函數
首先,要在SQLServer2005數據庫中建立發送消息的函數SendHttpMsg。
create PROCEDURE [dbo].[SendHttpMsg] @Params varchar(30) = '' AS DECLARE @obj INT DECLARE @sUrl varchar(200) DECLARE @response INT SET @sUrl = 'http://www.xxx.net:30008/QA?' +@Params EXEC sp_OACreate 'MSXML2.ServerXMLHTTP', @obj OUT EXEC sp_OAMethod @obj,'open', NULL, 'GET', @sUrl, false EXEC sp_OAMethod @obj,'send', null RETURN
3.2 數據庫表觸發器
在要監控的表上創建觸發器,調用SendHttpMsg函數,發送101消息
CREATE TRIGGER [dbo].[tr_em_test_sendCmd] ON [dbo].[EM_Test] AFTER UPDATE AS BEGIN --狀態變化,更新顯示 if @parkingStatus2 <> @parkingStatus0 begin EXEC SendHttpMsg @Params='cmd=101' end END
3.3 后台程序監聽處理
Delphi7中可以使用TIdHTTPServer組件來監聽Http消息。 綁定30008端口。在其OnCommandGet事件處理過程中執行代碼:
procedure TfHttp.IdHTTPServer30008CommandGet(AThread: TIdPeerThread; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo); var cmd: string; begin try cmd := ARequestInfo.Params.Values['cmd']; if cmd='101' then begin self.Timer_ProcHttpMsg.Enabled := True; end; end;
然后,在Timer_ProcHttpMsg的定時器事件中執行相應的業務邏輯即可。
3.4 注意事項
注意不能在OnCommandGet事件處理過程中直接調用業務邏輯函數,否則將導致數據庫訪問超時錯誤。
原因如下:
- 數據表記錄狀態變化à
- 數據表的行update觸發器啟動à
- DB發送Http消息à
- EXE的Http服務端口接收到消息à
- EXE查詢數據表統計信息à
- EXE更新業務信息à
- EXE的Http服務端口處理完畢à
- 數據表的行update觸發器完成à
- 記錄提交à
以上處理流程中第5步實際上無法完成,因為統計查詢必須等待第9步完成才能實施。
此處關鍵是要將第9步記錄提交放到第5步之前。
而第9步記錄提交依賴於第7步的Http調用返回。
因此問題明確了,以上流程中第5、6步不應該在EXE的Http服務端口處理事件中執行,而是應該另開線程,以便讓Http服務端口處理事件迅速返回,從而使數據表記錄變更得以快速提交。
實際解決方案是,在EXE的Http服務端口處理事件中啟動一個定時器事件,使統計和顯示操作延后執行即可。