2013-08-22 42 views
4

我们有一些运行时间非常长的ETL包(有些需要运行几个小时),需要由NServiceBus端点启动。我们不需要为整个流程保留单个事务,并且可以将其分解为更小的事务。由于NServiceBus处理程序将整个事务包装在一个事务中,所以我们不希望在单个事务中处理它,因为它会超时 - 更不用说在锁定DBMS时产生问题。完成任务后,SQL Server 2012(或SSIS)如何通知NServiceBus?

我目前的想法是,我们可以异步产生另一个进程,立即从处理程序返回,并在完成(成功或失败)时发布事件。我还没有找到关于如何将新的NServiceBus 4.0 SQL Server Broker支持与传统MSMQ传输集成的大量文档。这甚至有可能吗?

SQL Server 2012(或SSIS包)中的长时间运行进程以异步方式完成时通知NServiceBus订户的首选方式是什么?

+0

nservicebus什么都不知道,有什么能阻止你的SSIS包在完成时调用方法/将消息放入队列吗? – billinkc

+0

不是我所知道的,我只是问最简单的方法是什么。最糟糕的情况是,您可以手动在SSIS中编写代码(或者SQL Server中的CLR中的一些托管代码),以便将消息放入MSMQ队列中 - 但是,然后,您失去了NServiceBus中的一些功能,可帮助您管理这些功能队列。 –

回答

5

它看起来是可以做到从SSIS一个HTTP请求,看到How to make an HTTP request from SSIS?

考虑到这一点,你可以使用通过网关发送消息到NServiceBus(网关只是一个HttpListener)向您的发布告诉它发布一条消息,通知所有订阅者长期运行的ETL包已经完成。

要发送一个消息,你需要做的是这样的网关:

var webRequest = (HttpWebRequest)WebRequest.Create("http://localhost:25898/Headquarters/"); 
webRequest.Method = "POST"; 
webRequest.ContentType = "text/xml; charset=utf-8"; 
webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"; 

webRequest.Headers.Add("Content-Encoding", "utf-8"); 
webRequest.Headers.Add("NServiceBus.CallType", "Submit"); 
webRequest.Headers.Add("NServiceBus.AutoAck", "true"); 
webRequest.Headers.Add("NServiceBus.Id", Guid.NewGuid().ToString("N")); 

const string message = "<?xml version=\"1.0\" ?><Messages xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://tempuri.net/NServiceBus.AcceptanceTests.Gateway\"><MyRequest></MyRequest></Messages>"; 

using (var messagePayload = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(message))) 
{ 
    webRequest.Headers.Add(HttpRequestHeader.ContentMd5, HttpUtility.UrlEncode(Hasher.Hash(messagePayload))); //Need to specify MD5 hash of the payload 
    webRequest.ContentLength = messagePayload.Length; 

    using (var requestStream = webRequest.GetRequestStream()) 
    { 
     messagePayload.CopyTo(requestStream); 
    } 
} 

using (var myWebResponse = (HttpWebResponse) webRequest.GetResponse()) 
{ 
    if (myWebResponse.StatusCode == HttpStatusCode.OK) 
    { 
     //success 
    } 
} 

希望这有助于!

+0

我在概念验证中使用了这个解决方案,并且运行良好。我将发布一些我需要对此代码进行的更改,以使其作为C#CLR过程正常工作并接受此答案。 –

+0

很高兴听到:) –

2

SSIS 2012中实际上有一项任务是将消息放入MSMQ Message Queue Task中。您只需将它指向您的MSMQ连接,并使用表达式自定义您的消息,包名称,成功/失败次数,行数等。

取决于我们讨论的包的数量以及您想要的定制方式消息是,你最好的选择是编写一个独立的工具,以你想要的任何格式创建消息,然后使用一个执行进程任务来调用该实用程序,使用你想要传入的包中的任何参数进行格式化信息。

你也可以使用相同的代码,只是创建一个自定义SSIS任务(轻松了许多比它的声音。)

1

我想过帮坚持DRY原则是使用一个主SSIS包。

在我看来,它看起来像是一个执行包任务,连接到X。将程序包配置为包名称参数。配置执行包任务以使用参数来确定要调用的包。

X可能是一个脚本任务,但也许@凯尔黑尔指出,它可能是Message Queue Task。我把这个决定留给那些更熟悉NServiceBus的人。

在我看来,重要的是不要将这个逻辑添加到每个软件包中,因为这将成为维护的噩梦。

相关问题