domingo, 28 de junio de 2009

Service Broker

Es una plataforma para construir servicios seguros, confiable y escalables. Utilizan mensajes para intercambiar información entre servicios por medio de TCP IP

Es útil cuando se necesita procesamiento asíncrono o distribuir trabajos en diferentes computadores

Para habilitarlo es necesario ejecutar la siguiente sentencia T-SQL

ALTER DATABASE AdventureWorks SET ENABLE_BROKER

Para configurar la arquitectura del Service Broker contamos con 4 objectos.

Message Type: Define el nombre del mensaje y el tipo de informacion que el mensaje contiene. Estos mensajes deben ser creados en ambas partes de la conversacion

CREATE MESSAGE TYPE message_type_name
[AUTHORIZATION owner_name]
[VALIDATION =
{NONE EMPTY WELL_FORMED_XML
VALID_XML WITH SCHEMA COLLECTION schema_collection_name}]


Los posibles valores para VALIDATION son:
NONE: no se realiza ninguna validación
EMPTY: El cuerpo del mensaje debe tener valor NULO
WELL_FORMED_XML: Debe contener un XML bien formado
VALID_XML WITH SCHEMA COLLECTION: El contenido del XML debe cumplir con el XML SCHEMA señalado

Para modificarlo necesitamos utiliza la sentecia ALTER

ALTER MESSAGE TYPE message_type_name
VALIDATION =
{NONE EMPTY WELL_FORMED_XML
VALID_XML WITH SCHEMA COLLECTION schema_collection_name}]

Y para eliminar

DROP MESSAGE TYPE message_type_name

Contract: Define los tipos de mensajes que un servicio puede utilizar en una conversación y la dirección en que los mensajes pueden ser enviados

CREATE CONTRACT contract_name
[ AUTHORIZATION owner_name ]
( { message_type_name SENT BY { INITIATOR TARGET ANY }
[ DEFAULT ] } [ ,...n] )


Los posibles valores para SENT BY son:
INITIATOR: indica que solo el iniciador puede enviar dicho tipo de mensaje
TARGET: Indica que solo el destino puede enviar dicho tipo de mensaje
ANY: Indica que tanto el iniciador y el destino pueden enviar dicho tipo de mensaje

Para eliminar un contrato la sintaxis es la siguiente:

DROP CONTRACT contract_name

Queue: Define la ubicación donde se almacenaran los mensajes hasta que un servicio este disponible para atender los mensajes

CREATE QUEUE [database_name.[schema_name].schema_name.] queue_name
[ WITH
[ STATUS = { ON OFF } [ , ] ]
[ RETENTION = { ON OFF } [ , ] ]
[ ACTIVATION (
[ STATUS = { ON OFF } , ]
PROCEDURE_NAME = stored_procedure_name,
MAX_QUEUE_READERS = max_readers ,
EXECUTE AS { SELF 'user_name' OWNER }
) ]
]
[ ON { filegroup [ DEFAULT ] } ]


STATUS: Especifica si la cola esta habilitada. Cuando esta en OFF ningún servicio podría retirar mensajes de la cola.

RETENTION:Indica si la cola debe mantener todos los mensajes hasta que la conversación finalice

ACTIVATION STATUS: Indica si se debe activar el procedimiento almacenado cuando llegue un mensaje a la cola

MAX_QUEUE_READERS: Indica la cantidad máxima de servicio que correrán simultáneamente

EXECUTE AS:
especifica la cuenta de usuario con que correrá el servicio

Para modificar esta es la sintaxis

ALTER QUEUE [database_name.[schema_name].schema_name.] queue_name
[ WITH
[ STATUS = { ON OFF } [ , ] ]
[ RETENTION = { ON OFF } [ , ] ]
[ ACTIVATION (
[ STATUS = { ON OFF } , ]
PROCEDURE_NAME = stored_procedure_name,
MAX_QUEUE_READERS = max_readers ,
EXECUTE AS { SELF 'user_name' OWNER }
] DROP })
]


Para eliminar una cola la sintaxis es:

DROP QUEUE [database_name.[schema_name].schema_name.] queue_name

SERVICE: Relaciona las colas con los contractos

CREATE SERVICE service_name
[ AUTHORIZATION owner_name ]
ON QUEUE [ schema_name. ]queue_name
[ ( contract_name [DEFAULT] [ ,...n ] ) ]


Para modificar el servicio utilice la siguiente sintaxis:

ALTER SERVICE service_name
[ON QUEUE [schema_name].queue_name]
[(ADD CONTRACT contract_nameDROP CONTRACT contract_name)]



ON QUEUE: Especifica la nueva cola para el servicio y mueve todos los mensajes de la cola vieja a la nueva

ADD CONTRACT: Añade un contrato a la colección de contratos asociados a este servicio

DROP CONTRACT: Especifica los contratos que se eliminaran del servicio. En caso de que alguno se este ejecutando mostrara un mensaje de error.

Para comenzar a usar los servicios se deben establecer una conversación. Estos son los pasos para establecer una conversación.

Crear la variable que identificara de manera única la conversación.

DECLARE @dialog_handle uniqueidentifier

Iniciar la conversación

BEGIN DIALOG [ CONVERSATION ] @dialog_handle
FROM SERVICE initiator_service_name
TO SERVICE 'target_service_name'
[ , { 'service_broker_guid' 'CURRENT DATABASE' } ]
[ ON CONTRACT contract_name ]
[ WITH
[ { RELATED_CONVERSATION = related_conversation_handle
RELATED_CONVERSATION_GROUP = related_conversation_group_id } ]
[ [ , ] LIFETIME = dialog_lifetime ]
[ [ , ] ENCRYPTION = { ON OFF } ] ]


RELATED_CONVERSATION o RELATED_CONVERSATION_GROUP relaciona un nuevo dialogo con una conversacion existente

LIFETIME= tiempo en segundo en la que será valido el dialogo

Enviar mensaje

SEND
ON CONVERSATION conversation_handle
[ MESSAGE TYPE message_type_name ]
[ ( message_body_expression ) ]

El destino recibe el mensaje

[ WAITFOR ( ]
RECEIVE [ TOP ( n ) ]
[ ,...n ]
FROM
[ INTO table_variable ]
[ WHERE { conversation_handle = conversation_handle
conversation_group_id = conversation_group_id } ]
[ ) ] [ , TIMEOUT timeout ]


WAITFOR: especifica que la clausula RECEIVE espera un mensaje

RECEIVE: lee los mensajes de la cola y los elimina en caso de que la opción RETENTION de la cola este desactivada.

TOP: Indica cuantos mensajes se van a leer de la cola, sino se especifica se leerán todos los mensajes

INTO: Ingresa todos los mensajes en una tabla para ser tratados después

WHERE: especifica la conversación o grupo de conversaciones para los mensajes leídos

TIMEOUT: Especifica el tiempo en milisegundos en que la instrucción espera un mensaje.

Para terminar la conversación

END CONVERSATION conversation_handle
[ [ WITH ERROR = failure_code DESCRIPTION = 'failure_text' ]
[ WITH CLEANUP ]


Ejemplo de todo el proceso

CREATE MESSAGE TYPE TicketRequest AUTHORIZATION dbo
VALIDATION = WELL_FORMED_XML

CREATE MESSAGE TYPE TicketStatus AUTHORIZATION dbo
VALIDATION = WELL_FORMED_XML

CREATE QUEUE SenderQUEUE

CREATE QUEUE ReceiverQUEUE

CREATE CONTRACT Ticketservicescontract
(TicketRequest SENT BY INITIATOR,
TicketStatus SENT BY TARGET)

CREATE SERVICE SendTicketingService ON
Queue SenderQUEUE
(Ticketservicescontract)

CREATE SERVICE ReceiveTicketingService ON
Queue ReceiverQUEUE
(Ticketservicescontract)

declare @message xml
declare @conversationhandle UNIQUEIDENTIFIER
set @message =
'
dandy@ilikesql.com
5
Sybex SQLTraining
' '

BEGIN DIALOG CONVERSATION @conversationHandle
FROM SERVICE SendTicketingService
TO SERVICE 'ReceiveTicketingService'
ON CONTRACT Ticketservicescontract
WITH ENCRYPTION = OFF;

SEND ON CONVERSATION @conversationHandle
MESSAGE TYPE TicketRequest
(@message);
END CONVERSATION @conversationHandle

CREATE PROCEDURE STP_ProcessQueue
AS
BEGIN
DECLARE @conversation_handle UNIQUEIDENTIFIER,
@message_body XML,
@message_type_name NVARCHAR(128);
RECEIVE TOP(1)
@conversation_handle = conversation_handle,
@message_type_name = message_type_name,
@message_body = message_body
FROM [dbo].[ReceiverQUEUE]
-- DO SOMETHING with the message
if @message_type_name = 'TicketRequest'
BEGIN
-- EXEC stp_processticketrequest @message_body
SELECT @message_body
END
END CONVERSATION @conversation_handle ;
END
GO

ALTER QUEUE ReceiverQUEUE
WITH ACTIVATION (STATUS = ON,
PROCEDURE_NAME = STP_ProcessQUEUE,
EXECUTE AS OWNER)
GO

EXEC STP_ProcessQUEUE

No hay comentarios:

Publicar un comentario