Current .Net Version: 2.0.50727
Home
Articles
C# & .Net Framework Reference
Practice C# Online
XML Web Services
RSS Feeds
Code Snippets
T-SQL Scripts
Videos
Valuable Links
Contact Us
Mike's C#, VS.NET and SQL Blog




ROR XML Info.
Service Broker - Conversation Architecture
Author: Michael G.     Last Updated:12/17/2004 4:06:00 PM
Category(ies): SQL Server 2005
Description: An explanation of how Service Broker communicates.
  Add & View Comments About this Article

Tested with .Net 2.0.40607.42 and SQL Server 2005 9.00.852

  • Service Broker Architecture
  • Service Broker Conversation Architecture
  • Service Broker Message Types
  • Service Broker Contracts
  • Service Broker Links
  • Service Broker Queues
  • Service Broker Services
  • Service Broker Service Programs
  • Service Broker Dialogs
  • < Back | Next >



    Service Broker services communicate with each other with messages via Dialog: bidirectional conversations between two services, or, to use the proper term, Conversation Endpoints (Initiating Endpoint and Target Endpoint). Every Service Broker message belongs to a dialog. Every dialog is automatically assigned a conversation group: a logical grouping of related dialog conversations. Each dialog conversation agrees to a contract that specifies which service, or conversation endpoint, can send messages to one another as well as what Message Types can be used with each message. Message Types define what type of data the body of a message must contain (or not contain).

    When Service Broker delivers messages, it does so in an Exactly-Once-In-Order (EOIO) fashion. This means that exactly one conversation group worth of dialog conversation worth of messages is delivered to a receiving application at a time. When messages are retrieved from a receiving application, an entire conversation group worth of dialog conversations is delivered to it. Each message is marked with a message_sequence_number integer. The first message of each dialog sent has a message_sequence_number of 0. The second has a message_sequence_number of 1, and so forth. Dialogs, on the other hand, are marked with a send_sequence and receive_sequence integer. The first dialog of each conversation group has a send_sequence of 0. The second has a send_sequence of 1, and so forth. receive_sequence pertains to how dialogs are delivered to an application receiving messages from a queue.

    You don't need to concern yourself with conversation groups in most cases. By default, each dialog is assigned its own conversation group. This will only change if you manually move an existing dialog conversation from one conversation group to another. Dialogs and Conversation Groups are identified by UNIQUEIDENTIFIER values. This ensures that the probability of any two dialogs or conversation groups having the same identifier (called a handle) is very, very limited.

    Dialog conversations are made between two Service Broker services, or Conversation Endpoints. The Service that has begun a dialog conversation with another Service is called the Initiator. The receiving Service for that dialog conversation is called the Target. When you send messages to a Service Broker Service, you're said to be initiating a dialog conversation with it. The initiating Service is interchangeably termed the Initiator, or Initiating Endpoint, whereas, the Service where the messages are arriving is interchangeably termed the Target, or Target Endpoint. Because you can send and receive messages to and from the same Service Broker Service, it's more appropriate to call each end of a dialog conversation a Conversation Endpoint and not a Service. The Service is simply the interface through which Service Broker sends messages to and from different Conversation Endpoints. Initiating and Target Conversation Endpoints can exist in the same Service (same database) or completely different Services (different databases or even different instances of SQL Server). Dialog conversations between two services is uniquely tracked by means of a conversation_id - a UNIQUEIDENTIFIER value. This identifier exists at both Conversation Endpoints of a Dialog Conversation.

    When Services are created, they're assigned one or more Contracts. Contracts define who can send messages of a particular Message Type: the Initiator or the Target. Message Types, on the other hand, define what type of data the body of a message must contain (or not contain). When a dialog is created, it's attached to a Contract. This means that every message sent through that dialog must obey the rules of the Contract, and since each message is attached to exactly one Message Type, each message much obey the rules of its assigned Message Type. Each Service Broker Service created is assigned at least one Contract. The Service ensures that each messages it receives for delivery matches and obeys its assigned list of Contracts.

    Each Message is held in a Queue, which is essentially a table in the database. They're held there until they're retrieved or, if retention is on, the dialog conversations that they belong to are ended explicitly. When an application retrieves messages, it receives them one conversation group at a time. Every time a message is sent or received, the conversation group to which it (they) belongs is locked. During the lock, no other services can send or receive messages to and from the locked conversation group. This feature enforces concurrency.

    You start dialog conversations by using a T-SQL BEGIN DIALOG CONVERSATION statement.
    You send messages by using a T-SQL SEND statement.
    You end dialog conversations by using a T-SQL END CONVERSATION statement.
    You retrieve message by using a T-SQL RECEIVE statement.

    Example: Sending messages from one database service to another service in another database: -- Tested with SQL Server 2005 9.00.852 -- This example sends one message from a service -- on one database to another service in another -- database. USE DotNetFun; DECLARE @DialogHandle uniqueidentifier, @BrokerGUID uniqueidentifier; -- The Target service on another database: SELECT @BrokerGUID = service_broker_guid FROM sys.databases WHERE database_id = DB_ID('DotNetFun2'); BEGIN DIALOG CONVERSATION @DialogHandle FROM SERVICE DotNetFunService TO SERVICE 'DotNetFun2Service', @BrokerGUID ON CONTRACT DotNetFunContractSentByAny; SEND ON CONVERSATION @DialogHandle MESSAGE TYPE DotNetFunMessageTypeValidateNone ('HELLO!'); /* NOTE: MAKE SURE that the MESSAGE TYPE and CONTRACT for the initiating service also exist in the target service. If their names are different, the message will NOT be delivered and will be stored in the transmission queue: sys.transmission_queue */ -- End the conversation if you don't want any more -- messages to be added to this dialog conversation: END CONVERSATION @DialogHandle; As you can see, each message that's sent belongs to a dialog conversation, and each dialog conversation must use a predefined Contract. Contracts are rules that define who (the initiator, the target or both) can send messages to another service. Each contract must have at least one Message Type associated with it. Message Types define what type of data the body of a message can contain (or not contain). Message Types can be either well-formed XML, empty, valid XML with schema or any type. When messages are sent to a target service, they're validated for matching and compatible Contracts and Message Types. Not only must the Initiating Contracts and Message Type names be the same as that of the Target, but they must also be compatible. A message sent using a message type in one service must have the same name and type in the target service. Contracts and Message Types make up the rules that two services must adhere to when they send and receive messages to each another.

    Comments Click Here to Add your Comment
    No Comments Found.
     
    COPYRIGHT/DISCLAIMER | CONTACT US