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事件处理过程中直接调用业务逻辑函数,否则将导致数据库访问超时错误。

原因如下:

  1. 数据表记录状态变化à
  2. 数据表的行update触发器启动à
  3. DB发送Http消息à
  4. EXE的Http服务端口接收到消息à
  5. EXE查询数据表统计信息à
  6. EXE更新业务信息à
  7. EXE的Http服务端口处理完毕à
  8. 数据表的行update触发器完成à
  9. 记录提交à

 

以上处理流程中第5步实际上无法完成,因为统计查询必须等待第9步完成才能实施。

此处关键是要将第9步记录提交放到第5步之前。

而第9步记录提交依赖于第7步的Http调用返回。

因此问题明确了,以上流程中第5、6步不应该在EXE的Http服务端口处理事件中执行,而是应该另开线程,以便让Http服务端口处理事件迅速返回,从而使数据表记录变更得以快速提交。

 

实际解决方案是,在EXE的Http服务端口处理事件中启动一个定时器事件,使统计和显示操作延后执行即可。