我需要任何部署了使用 Sql Server Service Broker 外部激活机制(通过 Feature Pack 中的 Service Broker External Activator)的实际生产应用程序的人的指导。
目前的心态:
我的规格相当简单(或者至少我是这么认为的),所以我正在考虑以下基本流程:
类似订单的实体被插入到状态为“已确认”的Table_Orders
SP_BeginOrder被执行并执行以下操作:
- 开始交易
- 启动一个从Service_HandleOrderState到Service_PreprocessOrder的 DIALOG
- 将对话句柄(从现在开始PreprocessingHandle )存储在Orders表 的特定列中
- 使用PreprocessingHandle发送包含订单 ID的Message_PreprocessOrder类型的 MESSAGE
- 结束交易
请注意,我不会结束对话,我不想“一劳永逸”
Queue_PreprocessOrder上的事件通知激活PreprocessOrder.exe的一个实例(最大并发 1),它执行以下操作:
- 开始一个 SqlTransaction
- 从Queue_PreprocessOrder接收前 1 个 MESSAGE
- 如果消息类型是Message_PreprocessOrder(格式 XML):
- 使用消息正文中的订单 ID 在Table_Orders中将订单状态设置为“预处理”
- 加载计算n 元 Carthesian 积的 n 个数据集合(通过 Linq,AFAIK,这在 T-SQL 中是不可能的)以确定订单项集合
- 将订单项行插入Table_OrderItems
- 使用PreprocessingHandle发送Message_PreprocessingDone类型的 MESSAGE ,包含相同的订单 ID
- 结束与PreprocessingHandle相关的对话
- 提交 SqlTransaction
- 以 Environment.Exit(0) 退出
- Queue_HandleOrderState上的内部激活执行一个 SP(最大并发 1):
- 开始交易
- 从Queue_InitiatePreprocessOrder接收前 1 个 MESSAGE
- 如果消息类型是Message_PreprocessingDone:
- 使用消息正文中的订单 ID 在Table_Orders中将订单状态设置为“处理中”
- 启动从Service_HandleOrderState到Service_ProcessOrderItem的 DIALOG
- 将对话句柄(从现在开始ProcessOrderItemsHandle )存储在Table_Orders的特定列中
- 为当前订单 ID 和每一行
的Table_OrderItems中的行创建一个游标:
- 使用ProcessOrderItemsHandle发送Message_ProcessOrderItem类型的 MESSAGE ,其中包含订单项目 ID
- 如果消息类型是Message_ProcessingDone:
- 使用消息正文中的订单 ID 在Table_Orders中将订单状态设置为“已处理”
- 如果消息类型是
http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog
(END DIALOG):- 结束与消息的对话句柄有关的对话
- 结束交易
- Queue_ProcessOrderItem上的事件通知激活ProcessOrderItem.exe的一个实例(最大并发 1),它执行以下操作:
- 开始一个 SqlTransaction
- 从Queue_ProcessOrderItem接收前 1 个 MESSAGE
- 如果消息类型是Message_ProcessOrderItem(格式 XML):
- 使用消息正文中的订单项目 ID 在
Table_OrdersItems中将订单项目状态设置为“处理中” ,然后:
- 加载订单项目参数的集合
- 使用参数向 URL 发出 HttpRequest
- 将 HttpResponse 作为 PDF 存储在文件系统上
- 如果上述子步骤中发生任何错误,则将订单项目状态设置为“错误”,否则设置为“正常”
- 在Table_OrdersItems中执行查找以确定是否所有订单项目都已处理(状态为“ok”或“error”)
- 如果处理了所有订单项目:
- 使用ProcessOrderItemsHandle发送Message_ProcessingDone类型的 MESSAGE ,包含订单 ID
- 结束与ProcessOrderItemsHandle相关的对话
- 使用消息正文中的订单项目 ID 在
Table_OrdersItems中将订单项目状态设置为“处理中” ,然后:
- 提交 SqlTransaction
- 以 Environment.Exit(0) 退出
笔记:
- 规范指定 MSSQL 兼容性 2005 到 2012,因此:
- 没有对话组
- 没有对话优先级
- 没有 POISON_MESSAGE_HANDLING ( STATUS = OFF )
- 我正在努力实现整体流程的完整性和连续性,而不是速度
- 鉴于表和 SP 驻留在DB1中,而 Service Broker 对象(消息、合同、队列、服务)驻留在DB2中,DB2是 SET TRUSTWORTHY
问题:
- 所描述的架构中是否存在任何重大设计缺陷?
- 订单完成状态跟踪似乎不正确。有没有更好的方法?也许使用 QUEUE RETENTION ?
- 我的直觉告诉我,在任何情况下,激活的外部 exe 都不应该以 0 以外的退出代码终止,所以应该
try{..}catch(Exception e){..} finally{ Environment.Exit(0) }
在 Main.exe 中。这个假设正确吗? - 您将如何组织 DB 代码中的错误处理?错误日志表是否足够?
- 您将如何组织外部 exe C# 代码中的错误处理?相同的错误记录表?
- 我已经看过SQL Server Service Broker Product Samples,但对于我看似简单的案例,Service Broker 接口似乎有点过头了。更简单的 Service Broker 对象模型的任何替代方案?
- 任何用于服务代理的跨版本“便携式”管理工具至少能够排出有害消息?
- 对于上述任何一个,你有什么像样的代码示例吗?