【问题标题】:About multiple conversations and/or queues关于多个对话和/或队列
【发布时间】:2017-05-19 13:28:31
【问题描述】:

我想知道对话的确切定义,MS 文档和教程对此并不十分准确。

首先...对话和对话有区别吗?

假设一个队列应该只包含相同的消息或等效的消息(即消息类型由激活的过程以类似于 CASE WHEN / SWITCH 场景的方式处理)

  • 每个对话都围绕一个独特的队列进行吗?

  • 如果过程 A 将消息发送到激活过程 B 的队列,该过程 B 处理消息然后发出答案,过程 A 可以等待答案还是应该使用过程 C?我是否正确假设我必须创建两个在同一个合同上运行的队列?但是有多少服务?在那种情况下,我将如何以及在何处使用 END CONVERSATION?

  • 如果过程 A 将消息发送到激活处理消息的过程 B 的队列,然后为另一个/某些其他过程 C 发出另一个/几条消息,那么所有这些队列/服务 / 等等。在同一个对话中?同一个对话组? (在 GET CONVERSATION GROUP 之后我会做什么以确保我的对话在同一个组中?)这是否意味着在发出 BEGIN TRANSACTION / BEGIN DIALOG 或使用时传递相同的对话句柄

    [与
    [ { RELATED_CONVERSATION = related_conversation_handle
    | RELATED_CONVERSATION_GROUP = related_conversation_group_id } ]

?而且...最后但并非最不重要的一点是,如果我使用多条消息来并行/分叉对具有不同参数的 C 的调用,在这种情况下,我会想要开始完全不同的对话/对话组做同样的事情还是总是更好有一个独特的“叙述”

  • 哦...另一件事...有没有一种最佳做法是使用多条消息来调用一些治疗,然后等待每个治疗完成后再开始另一个治疗?有没有一种方法可以让每个程序接收一条消息,发送一个答案,然后由答案激活的程序可以检查/计算其队列中的先前消息,并且只有当它们都在那里时才继续?是否需要检查对话 ID(或对话组 ID)以确保这些消息都是由同一组答案发出的?

    我希望这不会太令人困惑,但是 MS 教程……嗯……有点简单。

【问题讨论】:

    标签: sql-server stored-procedures service service-broker


    【解决方案1】:

    首先,据我所知,对话与对话相同。同一事物的两个名称。

    队列可以包含许多不同的消息类型。由处理消息的事物(无论是内部激活的存储过程还是外部应用程序)来区分类型并用它做“正确的事情”。一个服务只能有一个队列,但一个队列可以有很多服务(尽管我实际上并没有在实践中看到这一点)。服务定义了可以通过服务契约接受和产生的消息类型。

    关于您是否希望队列处理器响应同一对话或开始新对话的问题完全取决于您。我的建议是在同一个对话中做出回应,除非你知道你有充分的理由不这样做。至于如何使用同一个会话,可以在发出receive语句时获取会话句柄。当您在回复中发出后续的send 时,将其用作对话句柄。

    我对对话组的看法是,您可能需要就同一件事与不同的服务进行对话。这是一个人为的例子:

    假设我有一个新的招聘流程。它有以下步骤:

    • 创建登录名
    • 在工资系统中创建一个条目
    • 向您的保险公司注册

    不过,从逻辑上讲,它们都是针对同一事件的(即“我雇用了一名新员工”)。因此,您可以将所有对话捆绑在一个对话组中,并分别跟踪各个对话。像这样的:

    declare @handle uniqueidentifier, @group uniqueidentifier = NEWID(), 
    @message XML = '<employee name="Ben Thul" />';
    
    BEGIN TRAN
        begin dialog @handle
            from service [EmployeeService]
            to service 'LoginService'
            on contract [LoginContract]
            with related_conversation_group = @group;
    
        SEND ON CONVERSATION (@handle)
            MESSAGE TYPE [NewLoginRequest]
            (@message);
    
        INSERT INTO [dbo].[OpenRequests]
        (
            [GroupIdentifier],
            [ConversationIdentifier],
            [ServiceName],
            [Status],
            [date_modified]
        )
        VALUES
            (@group, @handle, 'LoginService', 'RequestSent', GETUTCDATE());
    
        BEGIN DIALOG @handle
            FROM SERVICE [EmployeeService]
            TO SERVICE 'PayrollService'
            ON CONTRACT [PayrollContract]
            WITH RELATED_CONVERSATION_GROUP = @group;
    
        SEND ON CONVERSATION (@handle)
            MESSAGE TYPE [NewPayrollRequest]
            (@message);
    
        INSERT INTO [dbo].[OpenRequests]
        (
            [GroupIdentifier],
            [ConversationIdentifier],
            [ServiceName],
            [Status],
            [date_modified]
        )
        VALUES
            (@group, @handle, 'PayrollService', 'RequestSent', GETUTCDATE());
    
        BEGIN DIALOG @handle
            FROM SERVICE [EmployeeService]
            TO SERVICE 'InsuranceService'
            ON CONTRACT [InsuranceContract]
            WITH RELATED_CONVERSATION_GROUP = @group;
    
        SEND ON CONVERSATION (@handle)
            MESSAGE TYPE [NewInsuranceRequest]
            (@message);
    
        INSERT INTO [dbo].[OpenRequests]
        (
            [GroupIdentifier],
            [ConversationIdentifier],
            [ServiceName],
            [Status],
            [date_modified]
        )
        VALUES
            (@group, @handle, 'InsuranceService', 'RequestSent', GETUTCDATE());
    COMMIT
    

    现在,您有一种方法可以分别跟踪每个请求一种将它们全部绑定到同一个逻辑操作的方法。当每个服务处理消息时,它会以成功、失败或“我需要其他东西”消息进行响应。此时您可以使用当前状态更新OpenRequests 表。

    服务代理可能会让人不知所措。我对您的建议是考虑需要将哪些消息从 传递到 的地方,并围绕这些开始设计服务、消息类型、合同等。您不太可能使用 SB 提供的所有功能。

    【讨论】:

    • 感谢您的回答。所以,我是否正确理解您对我最后一个问题的回答(启动流程,然后收集答案以了解一切何时完成并开始最后一个)宁愿使用跟踪表而不是计算/分析队列中的相关答案激活程序?
    • 我想是的,是的。在我设计的示例中,您知道三个实际操作源于雇用新员工的逻辑操作。这些实际操作中的每一个都可能是简单的“发送一条消息并接收回复”或复杂的来回操作。您可以根据要建模的交互的简单或复杂程度灵活地定义消息流。
    • 我收到错误 9610... FROM SERVICE 子句中的服务“”必须与 %s 引用的服务“”匹配= '%.*ls'。这是否意味着对话组必须引用基于相同合同的服务?
    • 如果需要了解更多关于您尝试过的内容,但看起来您尝试在同一个会话句柄上发送到两个不同的服务。我可以稍后验证,但我的理解是,您可以放置​​原本不相关的对话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    • 2013-01-05
    • 1970-01-01
    • 2020-11-23
    • 2012-08-01
    • 2012-10-28
    相关资源
    最近更新 更多