Olá Pessoal,
Tudo certo ?
Hoje eu conheci o Service Broker do Microsoft SQL Server e aprendi bastante lendo o blog do Júnior Galvão, de onde eu extraí esse post. Acho que não ia valer a pena escrever muito sobre esse tema, se ele já abordou (de forma bem didática) isso extensivamente. Então vamos lá conhecer esse importante recurso do MS SQL Server, que foi disponibilizado a partir da versão 2005.
Introduction
Lançado em conjunto com o Microsoft SQL Server 2005, o Service Broker foi um dos grandes destaques desta versão do SQL Server, sendo tratado como uma das principais inovações do produto em 2005.
Desde então, muito se falou deste recurso que foi mantido e evoluído nas versões e edições posteriores do Microsoft SQL Server. Existente como recurso e funcionalidade do Mecanismo de Banco de Dados (Database Engine), o Service Broker fornece aos desenvolvedores e profissionais de banco de dados criarem aplicativos de enfileiramento e mensagens confiáveis para troca de dados no SQL Server. Basicamente através deste serviço é possível que uma aplicação conectada a uma única instância do SQL Server possa realizar a distribuição de trabalho e mensagens entre várias outras instâncias de banco de dados.
Através desta capacidade de troca de informações, o Service Broker estabeleceu uma forma assíncrona de comunicação entre os aplicativos de banco de dados que fazem uso desta funcionalidade, desta forma, o tempo de resposta para troca de informações é bem menor, mais interativo e simplificado, o que torna o uso deste recurso mais confiável.
Além disso, o Service Broker fornece a troca de mensagens confiáveis entre instâncias de bancos de dados distribuídas em uma corporação, ajudando os desenvolvedores a compor aplicativos estruturados ou reconhecidos como serviços independentes, fazendo uso da mesma instância de comunicação.
Por padrão o Service Broker, utiliza o protocolo TCP/IP e seu conjunto de protocolos existentes para a troca de mensagens, contendo recursos que podem impedir a qualquer momento o acesso não autorizado a uma rede, estabelecendo padrões para criptografia de mensagens enviadas pelos aplicativos entre as instâncias do SQL Server.
Como funciona o Service Broker
Como seu objetivo é criar uma forma simplificada, segura e desacoplada de troca de mensagens, o Service Broker possui um conjunto de tarefas necessárias para se realizar este processo de mensageria, entre os aplicativos e instâncias de Servidores de Banco de Dados. A arquitetura do Service Broker é composta pelos seguintes componentes, tarefas e características:
- Conversações;
- Ordenação e coordenação de mensagens;
- Programação assíncrona transacional;
- Suporte para aplicativos acoplados de forma flexível; e
- Componentes do Service Broker.
A seguir descrevo esta arquitetura, destacando de forma resumida cada tarefa.
Conversação
Projetado como recurso básico para envio e recebimento de mensagens o Service Broker, apresenta uma tarefa chamada “Conversação” realizada durante o processo de troca de mensagens. Cada tarefa conversação é reconhecida e tratada como canal de comunicação confiável e persistente, as mensagens apresentam um tipo específico de conversa que tratada pelo Service Broker individualmente que possibilita reforçar e garantir a segurança na gravação dos dados trocados pelos aplicativos.
Durante esta troca de mensagens, a tarefa de “Conversação” permite que os aplicativos envolvidos neste processo estabelece este canal de comunicação dentro de uma “fila” que representa uma exibição de uma tabela interna relacionada com o banco de dados que o Service Broker esta fazendo uso.
Para cada conversação tratada pelo Service Broker é estabelecida uma sequência e ordenação das Mensagens através da tarefa “Ordenação e Coordenação de Mensagens”, isso garante que cada mensagem faça parte de uma única e exclusiva conversa, ou seja, a mesma mensagem trocada será tratada pela mesma tarefa e conversação.
Uma maior simples de se representar e ilustrar o funcionamento do Service Broker é pensar como funciona um serviço postal. Para manter uma conversação com um colega distante, você pode comunicar enviando cartas pelo serviço postal.
O serviço postal classifica e entrega as cartas. Você e seu colega então recuperam as cartas das caixas postais, lêem, escrevem as respostas e enviam novas cartas até que a conversação termine. A entrega da carta acontece de forma assíncrona enquanto você e seu colega lidam com outras tarefas.
A Figura 1 apresenta o processo de troca de mensagens, com base, em um Serviço Postal.
Figura 1: Representação do processo de troca de mensagens realizada pelo Service Broker.
Ao analisar o funcionamento do Service Broker, podemos entender que os programas envolvidos neste cenário, devem entender que este serviço terá a sua forma de atuação similar ao Serviço Postal ou Correios, dando total suporte as mensagens assíncronas trocadas entre os aplicativos.
As mensagens do Service Broker funcionam como cartas. O serviço Service Broker é tratado como o endereço onde a agência postal entrega as cartas. As filas são as caixas postais que mantêm as cartas depois que elas são entregues. Os aplicativos recebem as mensagens, agem nas mensagens e enviam as respostas.
Observation: Enquanto existir um processo de troca de mensagens através do Service Broker, o processo de fila estará sendo mantido e alimentado até que o aplicativo receptor dos dados seja capaz de tratar estas mensagens, enquanto isso não ocorrer à fila de mensagens terá o seu tamanho aumentado e seu processo de enfileiramento expandido.
Ordenação e Coordenação de Mensagens
Todo processo de controle e manutenção das filas de mensagem é realizada pelo Service Broker diretamente no Mecanismo de Banco de Dados (Database Engine), adotando um tratamento tradicional através de dois aspcetos:
- As filas gerenciadas pelo Service Broker são integradas diretamente com o banco de dados ao qual o serviço esta envolvido.
- As filas são responsáveis por coordenar e ordenar as mensagens que estão em transito.
Através do forte controle de envio e recebimento de mensagens, a tarefa de “Ordenação e Coordenação de mensagens” estabelece ao Service Broker garantias no fluxo de troca de mensagens, estabelecendo dois lados no processo de comunicação, denominados:
- Lado de inicio chamado de iniciador; e
- Lado de destino da mensagem chamado de receptor.
Um processo básico de troca de mensagens do Service Broker consiste em:
Abaixo, uma ilustração da troca de mensagens em um diálogo típico:
- No iniciador:
- Um programa começa a conversação.
- O programa cria uma mensagem que contém os dados necessários para executar uma tarefa.
- O programa envia a mensagem ao serviço de destino.
- No receptor:
- A mensagem é colocada na fila associada ao serviço de destino.
- Um programa recebe a mensagem da fila e executa o trabalho.
- O programa responde enviando uma mensagem ao serviço iniciador.
- No iniciador:
- A mensagem de resposta é colocada na fila associada ao serviço iniciador.
- Um programa recebe a resposta e a processa.
Até o final do envio e recebimento de mensagens este ciclo se repete de forma cíclica e continua.
Esse ciclo se repete até que o iniciador termine a conversação porque não tem mais solicitações a enviar ao destino.
Programação assíncrona transacional
O componente “Programação assíncrona transacional”, esta totalmente relacionada com a infraestrutura de funcionamento do Service Broker, servindo como uma área de transferência de mensagens, tratada cada processo de forma transacional, o que permite que a mesma seja revertida em qualquer momento.
Neste componente o Service Broker, realiza o controle dos dados que estão sendo trocados, estabelecendo um processo de escalabilidade, o que garante que o serviço possa ser automatizado e cresça de acordo com a situação, uma delas é a capacidade de ocorrer à inicialização automática dos processas que realizam o processamento de uma fila, com isso é possível que a aplicação que esteja fazendo uso do processo de envio/recebimento identificar o momento em que a mensagem encontra-se em execução ou na fila de processamento.
A programação assíncrona permite que os desenvolvedores elaborem soluções de software capazes de gravar dados em filas de mensagem, fazendo uso do próprio banco de dados através de uma ou mais tabelas como repositórios internos de filas de mensagens.
Suporte para aplicativos acoplados de forma flexível
Considerada como uma característica e não um componente ou tarefa, o “Suporte para aplicativos acoplados de forma fléxivel”, garante e possibilita ao Service Broker trabalhar com um conjunto bem distinto de aplicativos independentes que podem ser identificados como possíveis componentes de troca de mensagem. Estes aplicativos devem conter internamente a mesma estrutura e mecanismo para troca de mensagens existente no Service Broker, o que permite em algumas situações que este componente seja acoplado ao serviço de mensageria.
Componentes do Agente de Serviços
O Service Broker é composto por três componentes básicos, existentes de acordo com a tarefa que esta em execução:
- Componentes de conversação: Conhecido como diálogo, é qualquer conversação realizada através do Service Broker durante o processo de troca de mensagens, permitindo que grupos de conversões, conversas e mensagens possam ser tratadas por seus aplicativos estabelecendo os participantes.
- Componentes de definição de serviço: Responsável por estabelecer o fluxo da conversação, o armazenamento de dados em um banco de dados, este componente define a estrutura básica de conversação realizada entre o Service Broker e o aplicativo.
- Componentes de rede e segurança: Através deste componente o Service Broker permite aos administradores de banco de dados realizem o gerenciamento de seus ambientes sem gerar impactos no código fonte da aplicação, focando alterações ou mudanças de cenário, estabelecendo um canal de troca de mensagens de forma segura e confiável, para os aplicativos que estão consumindo o Service Broker.
Observation: Componentes de definição de serviço, componentes de rede e componentes de segurança são parte dos metadados do banco de dados e da instância do SQL Server. Grupos de conversação, conversações e mensagens fazem parte dos dados que o banco de dados contém.
Bom, após esta longa caminhada, vou colocar um pouco de pimenta neste molho, começando a criação do nosso ambiente de estudos, através do Codigo 1 apresentado abaixo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
–- Código 1 – Criando o Banco of Dados MyDatabaseServiceBroker Use Master Go /* 1 – Criação do banco de dados */ CREATE DATABASE MyDatabaseServiceBroker Go /* 2 – Ativação do recurso de Service Broker */ ALTER DATABASE MyDatabaseServiceBroker SET ENABLE_BROKER Go /* 3- Verificação do Status */ SELECT Name, is_broker_enabled FROM sys.databases WHERE Name = 'MyDatabaseServiceBroker' Go |
Observe que após criarmos o banco de dados, utilizamos o comando Alter Databaseatravés da diretiva Set Enable_Broker para ativar e indicar para o SQL Server que este banco de dados deverá permitir o uso do serviço de mensageria.
Observações:
- Para executar o ENABLE_BROKER o SQL Server solicita um bloqueio de banco de dados exclusivo. Se outras sessões bloquearam recursos no banco de dados, ENABLE_BROKER esperará até que as outras sessões liberem os bloqueios.
- Para habilitar o Service Broker em um banco de dados de usuário, verifique se nenhuma outra sessão está usando o banco de dados antes de executar a instrução ALTER DATABASE SET ENABLE_BROKER, por exemplo, colocando o banco de dados no modo de usuário único.
Em seguida executamos comando Select para validar o status da coluna Is_Broker_Enabled existente na System Table Sys.Databases, que deverá retornar o valor de 1 para esta coluna, o que garante que o Service Broker esta configurado de forma correta.
Tipos de Mensagens
Para que seja possível realizar a comunicação, os aplicativos que fazem uso do Service Broker utilizam o conceito de mensagens através da função de envio e recebimento, algo muito similar ao e-mail. Os envolvidos no processo de troca de mensagens, são os responsáveis por concordar com a troca de conteúdo, como também, no reconhecimento do nome de cada mensagem.
O objeto tipo de mensagem define um nome para o tipo de mensagem e o tipo de dados que a mensagem deverá conter. Os tipos de mensagem persistem nos bancos de dados em que são criados. Você pode criar um tipo de mensagem idêntico em cada banco de dados que participa de uma conversação.
Cada tipo de mensagem é responsável em especificar a validação que o SQL Server deve executar para as mensagens, de acordo com o tipo de dados. O SQL Server pode verificar se a mensagem contém XML válido, se contém XML em conformidade com um determinado esquema ou se simplesmente não contém dados.
A validação é executada quando o serviço de destino recebe a mensagem, caso o conteúdo da mensagem não corresponda à validação especificada, o Service Broker retornará uma mensagem de erro ao serviço que enviou a mensagem.
Pois bem, nosso cenário será composto basicamente por dois tipos de mensagens:
- mtEnvioMensagem; e
- mtRecebimentoMensagem.
Para criarmos nossos Tipos de Mensagens, vamos utilizar o Bloco de Código 1, apresentado abaixo:
1 2 3 4 5 6 7 8 9 10 11 |
/* Código 1 – Criando os Tipos de Mensagens */ Use MyDatabaseServiceBroker Go CREATE MESSAGE TYPE [mtEnvioMensagem] VALIDATION = WELL_FORMED_XML Go CREATE MESSAGE TYPE [mtRecebimentoMensagem] VALIDATION = WELL_FORMED_XML Go |
Note que estou especificando no argumento Validation, a opção =Well_FORMED_XML, isso vai indicar para o SQL Server que a nossa deverá conter em seu corpo um arquivo XML bem formatado como mecanismo de validação da mensagem.
A Tabela 1 apresentada abaixo, ilustra os tipos de mensagens existentes no Service Broker:
Argumentos |
Descrição |
NONE | Especifica que nenhuma validação é executada. O corpo da mensagem pode conter dados ou pode ser NULL. |
EMPTY | Especifica que o corpo da mensagem deve ser NULL. |
WELL_FORMED_XML | Especifica que o corpo da mensagem deve conter XML bem formado. |
VALID_XML WITH SCHEMA COLLECTION | Especifica que o corpo da mensagem deve conter XML que obedeça ao um esquema na coleção de esquemas especificada.O schema_collection_name deve ser o nome de uma coleção de esquema XML existente. |
Tabela 1 – Relação de argumentos existentes no comando Create Message Type.
Podemos observar a Figura 1 que ilustra a estrutura do nosso banco de dados, após a criação dos dois tipos de mensagens:
Caso você queria consultar a relação de mensagens criadas neste momento, utilize a System Table: Sys.Service_Message_Types
Nosso próximo passo é realizar a criação dos Contratos, vamos então conhecer um pouco sobre os Contratos e depois realizar a criação deste recurso.
Contratos
Um contrato define qual tipo de mensagem um aplicativo usa para realizar uma tarefa em particular. Um contrato é um acordo entre dois serviços sobre quais mensagens cada serviço visa realizar uma tarefa em particular.
O contrato especifica quais tipos de mensagem podem ser usados para realizar o trabalho desejado. O contrato também especifica qual participante na conversação pode usar cada tipo de mensagem.
O Service Broker também inclui um contrato interno denominado DEFAULT. Este contém somente o tipo de mensagem SENT BY ANY. Se nenhum contrato for especificado na instrução o Service Broker usará o contrato DEFAULT.
Para realizarmos a criação de um novo contrato, vamos utilizar o Bloco de Código 2apresentado abaixo, observe que iremos utilizar o comando Create Contract, especificando o Tipo de Mensagem que será o Target e qual será Initiator.
1 2 3 4 5 6 7 8 9 |
/* Código 2 – Criando contrato e definido o Target e Initiator */ Use MyDatabaseServiceBroker Go CREATE CONTRACT [cProcessaMensagens] ( [mtEnvioMensagem] SENT BY initiator, [mtRecebimentoMensagem] SENT BY target ); Go; |
Observe que defininos como initiator(inicializador) o mtEnvioMensagem e comoTarget(alvo) o mtRecebimentoMensagem, com isso, a partir do momento que dermos inicio o processo de diálogo, o Service Broker vai conseguir entender qual Tipo de Mensagem vai enviar e qual vai receber a mensagem.
A Figura 2 apresentada a seguir, ilustra a estrutura do nosso Banco de Dados MyDatabaseServiceBroker, após a criação do contrato cProcessaMensangens:
Figura 2 – Estrutura do Banco de Dados MyDatabaseServiceBroker, apresentando o contrato criado anteriormente.
Caso você queria consultar a relação de contratos criados neste momento, utilize a System Table: Sys.Service_Contracts
Neste momento, nosso banco de dados, apresenta em sua estrutura os seguintes componentes:
- Tipos de Mensagem: mtEnvioMensagem e mtRecebimentoMensagem; e
- Contrato: cProcessaMensagens.
Vamos evoluir mais um pouco na estrutura de nosso ambiente, fazendo agora a criação de outro recurso muito importante para que seja possível fazer uso do Service Broker, e de grande avalia para que as mensagens possam ser trocadas, este me referindo as QUEUE (Filas), mantendo a regra, vou apresentar os conceitos sobre Queue e em seguida o código que devemos utilizar para criar nossas filas.
QUEUE (Filas)
As Queues, ou filas, tem como função, possibilitar um canal de comunicação entre os envolvidos no processo de troca de mensagens, criando o chamado Enfileirador de mensagens.
Quando o Service Broker recebe uma mensagem de um serviço, ele a insere na fila desse serviço, desta forma, para receber as mensagens enviadas ao serviço, um aplicativo recebe mensagens da fila, possibilitando que o Service Broker gerencie e controle o fluxo de mensagens que esta sendo processadas em cada fila.
Durante o processamento das mensagens, as filas são preenchidas criando uma seqüência de linhas que representam as mensagens que estão sendo utilizadas.
A linha tem o conteúdo da mensagem e informações sobre o tipo de mensagem, o serviço pretendido pela mensagem, o contrato que a mensagem segue, a validação executada na mensagem, a conversação da qual a mensagem faz parte e as informações internas para a fila.
As filas não retornam mensagens em uma ordem restrita de primeiro a entrar, primeiro a sair; em vez disso, as filas retornam as mensagens para cada conversação na ordem em que as mensagens foram enviadas. Assim, um aplicativo não precisa incluir código para recuperar a ordem original das mensagens.
Seguindo em frente, vamos realizar a criação das filas que iremos utilizar em nosso ambiente, para isso criaremos duas filhas, denominadas: qOrigem e qDestino, utilizadas como canais de comunicação e enfileirados no processamento das mensagens, para tal, faremos uso do Bloco de Código 3, apresentado abaixo:
1 2 3 4 5 6 7 8 9 |
/* Código 3 – Criando as Filas qOrigem e qDestino */ Use MyDatabaseServiceBroker Go CREATE QUEUE [qOrigem] Go CREATE QUEUE [qDestino] Go |
Se observarmos o processo de criação de uma fila é muito simples e sem qualquer tipo de segredos, muito pelo contrário, uma das características mais peculiares do Service Broker esta relacionada ao seu processo de configuração, realizado de forma muito clara, tranqüila e muito simplificada.
Temos neste momento, mais um componente criado em nosso banco de dados, conforme apresenta a Figura 3, que desta a forma que o Management Studio apresenta as filas criadas para nosso Service Broker:
Figura 3: Estrutura do Banco de Dados, apresentando as filas qOrigem e qDestino criadas anteriormente.
Caso você queria consultar a relação de filas criadas neste momento, utilize a System Table:Sys.Service_Queues
Nosso último componente que será criado para compor a estrutura do nosso Banco de Dados MyDatabaseServiceBroker, conhecido como Serviço, e como sua própria descrição apresenta, o Serviço será o elemento envolvido no processo de troca de mensagens realizada pela Service Broker.
Services (Serviços)
Elemento que compõem a arquitetura do um Service Broker, os serviços são definidos e tratados como tarefas que possuem uma finalidade específica, possibilitar a ocorrência de conversações (diálogos) no Service Broker. Através dos serviços, o Service Broker consegui realizar a entrega das mensagens para as filas de forma correta dentro de um banco de dados, rotear mensagens, impor o contrato para uma conversação e determinar a segurança remota de uma nova conversação.
Cada serviço especifica uma fila para conter as mensagens de entrada, fazendo uso dos contratos associados ao serviço que definem as tarefas específicas para as que o serviço aceite conversações novas.
Continuando pelo esta longa estrada, vamos realizar a criação dos nossos serviços, da mesma forma que realizamos para Filas, estaremos criando dois serviços denominados: sOrigem e sDestino, conforme apresenta o Bloco de Código 4 a seguir:
1 2 3 4 5 6 7 8 9 |
/* Código 4 – Criação dos Serviços sOrigem e sDestino */ Use MyDatabaseServiceBroker Go CREATE SERVICE [sDestino] ON QUEUE [qDestino] ([cProcessaMensagens]) Go CREATE SERVICE [sOrigem] ON QUEUE [qOrigem] Go |
Importante destacar, que o serviço sDestino esta vinculado com a fila qDestino e para este mesmo serviço especificamos que será utilizado o contratocProcessaMensagens, desta maneira, ao fazer uso deste serviço o SQL Server deverá obrigatoriamente chamar o contrato cProcessaMensagens como elemente de validação e garantia do tipo de mensagem que esta sendo trocada.
A Figura 4, ilustra a estrutura do banco de dados MyDatabaseServiceBroker, após a criação dos nossos serviços:
Figura 4 – Estrutura do Banco de Dados MyDatabaseServiceBroker após a criação dos serviços sDestino e sOrigem.
Caso você queria consultar a relação de serviços configurado neste momento, utilize a System Table: Sys.Services.
Processo de Envio de Mensagens
Conforme apresentado na Parte I, o Processo de Comunicação (Conversação) entre o Service Broker e as aplicações que fazem uso do mesmo é algo muito similar ao funcionamento dos Correios, onde existe a Troca de Dados (mensagens) envolvendo o remetente e seu destinatário.
No Service Broker este processo de comunicação ocorre através do uso dos comandosBegin Dialog Conversation e Send, onde o processo se inicia através do uso do Begin Dialog e o Send vai ocorrer através do Send.
Comando Begin Dialog Conversation
O comando Begin Dialog Conversation basicamente orienta o SQL Server a iniciar um bloco de conversação entre um ou mais serviços, o que normalmente ocorre através da troca de mensagens com no mínimo dois serviços.
As informações especificadas na instrução BEGIN DIALOG CONVERSATION são semelhantes ao endereço em uma carta; o Service Broker usa as informações para entregar as mensagens ao serviço correto. Este comando apresenta um conjunto único de argumentos, para determinar da melhor forma possível o processo de conversação. A seguir apresento a relação de argumentos:
- @dialog_handle: Variável utilizada para armazenar o identificador do diálogo gerado retornada pela instrução BEGIN DIALOG CONVERSATION. Obrigatoriamente esta variável deve ser do tipo Uniqueidentifier.
- From Service initiator_service_name: Determina o serviço que inicia o diálogo. O nome especificado deve ser o nome de um serviço no banco de dados atual. A fila especificada para o serviço iniciador recebe mensagens retornadas pelo serviço de destino e mensagens criadas pelo Service Broker para essa conversa.
- To Service ‘target_service_name’: Especifica o serviço de destino com o qual será iniciado o diálogo. O target_service_name é do tipo nvarchar(256). O Service Broker usa uma comparação byte a byte do conjunto de caracteres existentes na mensagem. Esta comparação diferencia maiúsculas de minúsculas e não leva em conta o agrupamento atual.
- Service_broker_guid: Informa o banco de dados que hospeda o serviço de destino. O service_broker_guid é do tipo nvarchar(128). Através da System Table Sys.Databases é possível obter o service_broker_guid.
- ‘CURRENT DATABASE’: Apresenta que a conversa usa o service_broker_guid no banco de dados atual.
- ON CONTRACT contract name: Especifica o contrato que essa conversa deverá utilizar e envolver no processo de troca. Quando este argumento é omitido, a conversa utilizará o contrato chamado DEFAULT.
- RELATED_CONVERSATION = related_conversation_handle: Especifica o grupo de conversa existente ao qual um diálogo é adicionado. Quando esta cláusula estiver presente, o diálogo pertencerá ao mesmo grupo de conversa envolvido no diálogo especificado nos argumentos related_conversation_handle
- RELATED_CONVERSATION_GROUP =related_conversation_group_id: Determina o grupo de conversa existente ao qual a um novo diálogo é adicionado. Quando esta cláusula estiver presente, a nova caixa de diálogo será adicionada ao grupo de conversa especificado por related_conversation_group_id.
- LIFETIME = dialog_lifetime: Declara o limite máximo de tempo que o diálogo permanecerá aberto. Para o diálogo ser concluído com êxito, os pontos de extremidade devem finalizar explicitamente o diálogo antes que seu tempo de vida expire. O valor dialog_lifetime deve ser expresso em segundos. O tempo de vida é do tipo int. Quando nenhuma cláusula LIFETIME é especificada, o tempo de vida da caixa de diálogo é o valor máximo do tipo de dados int.
- ENCRYPTION: Especifica se as mensagens enviadas e recebidas no diálogo devem ou não ser criptografadas, quando forem enviadas para uma instância do Microsoft SQL Server. Quando ENCRYPTION = ON e os certificados necessários para oferecer suporte à criptografia não estão configurados, o Service Broker retorna uma mensagem de erro na conversa. Se ENCRYPTION = OFF, a criptografia será usada se uma associação de serviço remoto estiver configurada para o target_service_name; caso contrário, as mensagens serão enviadas descriptografadas. Se esta cláusula não estiver presente, o valor padrão será ON.
Important: Todas as mensagens fazem parte de uma conversa. Portanto, um serviço iniciador deve começar uma conversa com o serviço de destino antes de enviar-lhe uma mensagem.
O serviço especificado na cláusula TO SERVICE é o endereço para o qual as mensagens são enviadas. O serviço especificado na cláusula FROM SERVICE é o endereço de retorno usado para mensagens de resposta. O início de um diálogo cria um ponto de extremidade de conversa no banco de dados para o serviço iniciador, mas não cria uma conexão de rede à instância que hospeda o serviço de destino. O Service Broker não estabelece comunicação com o destino da caixa de diálogo até que a primeira mensagem seja enviada.
Após conhecermos um pouco sobre este comando, vamos então trabalhar no nosso primeiro bloco de código, denonimado Código 1, onde estaremos iniciando nosso processo de diálogo para posterior troca de mensagens.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* Código 1 – Iniciando o Diálogo entre os Serviços */ USE MyDatabaseServiceBroker GO Declare @MyConversationHandle Uniqueidentifier Begin Transaction -– Iniciando um novo diálogo entre os serviços da sOrigem e sDestino – BEGIN DIALOG @MyConversationHandle FROM SERVICE [sOrigem] TO SERVICE 'sDestino' ON CONTRACT [cOProcessaMensagens] WITH ENCRYPTION = OFF, LIFETIME = 600; |
Onde
– @MyConversationHandle: Variável utilizada para armazenar o Handle_id criado pelo SQL Server para ser utilizado neste diálogo;
– From Service: informamos o Serviço sOrigem como o nosso serviço de origem para troca de mensagens;
– To Service: Declarado o Serviço sDestino como serviço de destino envolvido na nossa troca de mensagens;
– On Contract: Declaramos o nosso do Contrato que utilizaremos neste Dialogo para os serviços envolvidos;
– Encryption = Off: Estamos informando para o SQL Server que nossa a mensagem que será trocada neste diálogo não necessita ser criptografada; e
– Lifetime = 600: Informa o Service Broker que este diálogo terá um tempo máximo de vida útil de 600 segundos, quando este tempo se esgotar e o diálogo ainda existir o mesmo deverá ser finalizado de forma obrigatória.
Nota: Ao executar este bloco de código você vai observar que o Microsoft SQL Server praticamente não estará realizando nenhum procedimento ou troca de mensagens. O objetivo do Código 1 é ilustrar e apresentar como podemos criar um novo diálogo, sendo que, este mesmo bloco será utilizado em posteriormente.
Legal nosso diálogo foi iniciado e agora o Service Broker começa a trabalhar aguardando posteriormente os dados que serão adicionados para fazer parte da mensagem que em seguida enviada.
Vamos então conhecer um pouco sobre o Comando Send, responsável direto no processo de envio de mensagens por parte do Service Broker.
Comando Send
Da mesma forma que o Comando Begin Dialog Conversation, o comando Send também esta envolvido no processo de troca de mensagens entre os serviços que estão ligados ao Service Broker.
O Send tem como principal função possibilitar o envio de mensagens entre uma ou mais conversas existentes. Através do Send o SQL Server é orientado a realizar o chamado PULL (Empurrar) empurrando os dados que estão armazenadas na estrutura que compõem a mensagem para serem deslocados entre os serviços de origem e destino, passando internamente na estrutura do banco de dados ao qual o mesmo esta relacionado.
Este comando também apresenta um conjunto único de argumentos que podem ser utilizados para determinar uma melhor forma de envio dos dados, conforme destaco a seguir:
- ON CONVERSATION conversation_handle: Especifica as conversas às quais a mensagem pertence. O conversation_handle deve conter um identificador de conversação válido. O mesma identificador de conversação não pode ser usado mais de uma vez.
- MESSAGE TYPE: Informa o tipo da mensagem enviada. Esse tipo de mensagem deve ser incluído nos contratos de serviço usado por essas conversas. Esses contratos devem permitir que o tipo de mensagem seja enviado desse lado da conversa. Se essa cláusula for omitida, a mensagem será do tipo DEFAULT.
- message_body_expression: Fornece uma expressão que representa o corpo de mensagem. A message_body_expression é opcional. Entretanto, se message_body_expression estiver presente, a expressão deverá se de um tipo que possa ser convertido em varbinary(max). A expressão não pode ser NULL. Se essa cláusula for omitida, o corpo de mensagem será vazio.
Agora já podemos realizar o processo de criação e envio da nossa mensagem, para isso vamos utilizar o Bloco de Código 2 apresentado abaixo.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/* Código 2 – Criando e Enviando a Mensagem */ USE MyDatabaseServiceBroker GO Declare @MyConversationHandle Uniqueidentifier Begin Transaction /* Inicia um diálogo entre os serviços da origem e destino */ BEGIN DIALOG @MyConversationHandle FROM SERVICE [sOrigem] TO SERVICE 'sDestino' ON CONTRACT [cProcessaMensagens] WITH ENCRYPTION = OFF, LIFETIME = 600; /* Declarando a Estrutura e Conteúdo da Mensagem */ Declare @MyMensagemServiceBroker XML SET @MyMensagemServiceBroker = N'<!--?xml version=”1.0″?--> Minha mensagem Olá esta é uma mensagem de teste no Service Broker'; /* Enviando uma mensagem no Diálogo */ SEND ON CONVERSATION @MyConversationHandle MESSAGE TYPE [mtEnvioMensagem] (@MyMensagemServiceBroker) Commit Transaction |
Observações:
– Note que para conseguirmos realizar todo processo de Diálogo e Envio da Mensagem somos obrigados a executar novamente o Bloco de Código 1 dentro do Bloco de Código 2.
– Outro ponto importante é o uso do comando Commit Transaction para forçar o SQL Server a realizar o processamento e confirmação das instruções que compõem este bloco de código, desta forma, estaremos garantindo que o envio da mensagem foi realizado e encerrando o bloco de transação.
Show de Bola, nossa mensagem foi enviada e agora aquela pergunta que não pode faltar. A onde foi parar nossa mensagem, é justamente esta resposta que eu vou apresentar no Bloco de Código 3, como se fosse um aperitivo que adicionamos ao nosso almoço e que será desvendado na próxima parte deste artigo.
1 2 |
/* Código 3 – Localizando – Mensagem */ Select Cast(message_body as xml) from qDestino |
Processando o Recebimento de Mensagens
O processo para recebimento de mensagens tratadas por aplicações que fazem uso do Service Broker, ou diretamente no Management Studio, é realizado basicamente através do uso do comando Receive, em conjunto com a cláusula Top.
A principal função do comando Receive é recuperar uma ou mais mensagens que possam existir na fila que o Serviço invocado pelo Service Broker esta utilizando no momento. Normalmente este comando deverá remover a mensagem da sua fila ou atualizar o seu Status, dependendo da forma de configuração que esta definição para a fila em uso.
Comando Receive
O comando Receive possui uma simples função realizar uma leitura na fila que esta sendo processada a fim de identificar o conjunto de mensagens que estão dentro deste repositório, passando uma ordem de atualização de status ou remoção da mensagem da fila. Para que este simples procedimento possa ser realizado, existe um conjunto de argumentos que podem ser utilizados em conjunto com o comando, os quais serão reconhecidos pelo SQL Server como orientadores da ação e tratamento que deve ser feito com a mensagem ou conjunto de mensagens capturada. A seguir apresento a relação de argumentos:
- Waitfor: Orienta a instrução RECEIVE para aguardar a chegada de uma mensagem na fila, se não houver nenhuma mensagem no momento.
- Top (n): Indica o número máximo de mensagens a serem obtidas e posteriormente retornadas. Se essa cláusula não estiver especificada, todas as mensagens que atenderem aos critérios da instrução serão retornadas. Para este argumento é permitido utilizar algumas opções: Column_Name, Expression ou Column_Alias, como possíveis filtros de dados.
- From: Informa à fila que deverá ser utilizada e conter o conjunto de mensagens capturadas. Em conjunto com este argumento, podemos utilizar as opções: Database_Name, Schema_Name e Queue_Name, como possíveis owners(responsáveis ou donos) da fila.
- Into table_variable: Indica para o SQL Server que o retorno das mensagens deverá ser armazenado possivelmente em uma variável do tipo tabela, onde a tabela deve ter o mesmo número de colunas que as mensagens. O tipo de dados de cada coluna na variável de tabela deve poder ser convertido implicitamente no tipo de dados da coluna correspondente nas mensagens. Caso esta opção venha a ser omitida, o SQL Server retornará as mensagens no formato padrão, identificado cada valor como um possível resultado.
- Where: Apresenta a conversa ou grupo de conversa das mensagens recebidas. Se omitido, as mensagens serão retornadas do próximo grupo de conversa disponível. Para este argumento, podemos utilizar as opções: Conversation_Handle e Conversation_Group_Id, para ajudar o Service Broker a identificar manipulador da mensagem ou grupo de conversa que estamos capturando dentro da fila. Vale destacar, que os valores passados para estas duas opções são tratados como Identificadores Únicos ouUniqueIdentifier.
- TimeOut: Determina o período de tempo, em milissegundos, durante o qual a instrução aguarda uma mensagem. Por padrão, esta cláusula pode ser usada apenas com a cláusula WAITFOR. Se essa cláusula não estiver especificada ou se o tempo limite for -1, o tempo de espera será ilimitado. Ao termino do tempo limite o RECEIVE retornará um conjunto de resultados vazio.
Important: A instrução RECEIVE lê mensagens de uma fila e retorna um conjunto de resultados. Este conjunto consiste em zero ou mais linhas, cada uma das quais contêm uma mensagem. Se a instrução INTO não for usada e column_specifier não atribuir os valores a variáveis locais, a instrução retornará um conjunto de resultados ao programa de chamada.
A instrução RECEIVE remove mensagens recebidas da fila a menos que a fila especifique retenção de mensagem. Quando a configuração de RETENTION da fila estiver ON, a instrução RECEIVE atualizará a coluna status para 0, e deixará as mensagens na fila. Quando uma transação que contém uma instrução RECEIVE é revertida, todas as alterações feitas na fila na transação também são revertidas, retornando mensagens para a fila.
Muito legal, já conhecemos um pouco do comando Receive, seus argumentos, opções e principalmente a maneira que este comando trabalho, podemos evoluir um pouco mais e começar a fazer o processo de recebimento das mensagens, iniciando pela identificação de quais mensagens estão em nossa Fila.
Mas como estamos no final desta caminhada, muito coisa já foi apresentada anteriormente e que como atualmente memória é algo que normalmente falta em nossas cabeças, vou refrescar nossas lembranças apresentando novamente o nosso cenário, com toda estrutura de recurso, através da Tabela 1 abaixo:
Nome do Recurso |
Funcionalidade |
MyDatabaseServiceBroker |
Database – Banco de Dados |
mtEnvioMensagem |
Message Type – Tipo de Mensagem |
mtRecebimentoMensagem |
Message Type – Tipo de Mensagem |
cProcessaMensagens |
Contract – Contrato |
qDestino |
Queue – Fila |
qOrigem |
Queue – Fila |
sDestino |
Service – Serviço |
sOrigem |
Service – Serviço |
AutoCreatedLocal |
Route – Rota |
Tabela 1 – Estrutura e Recursos – Service Broker.
Agora você não pode reclamar, acredito que já conseguiu se lembrar no nosso cenário, estrutura e principalmente dos recursos que estamos utilizando.
Um detalhe importante, você pode observar que a Tabela 1, apresenta um recurso do tipo Route (Rota), em nenhum momento este recurso foi abordado neste cenário, mas ele esta presente é possível uma grande importância.
Quando uma aplicação Service Broker é criada por padrão o Microsoft SQL Server, cria uma rota denominada AutoCreatedLocal, sendo esta, endereça como uma Rota Local e responsável por permitir o tráfego dos dados que o Service Broker esta processando. Caso você queria saber e conhecer mais sobre este elemento e sua funcionalidade, consulte os Manuais do Microsoft SQL Server (Books Online), procurando sobre Create Route.
Vamos então trabalhar com o nosso primeiro bloco de código, denonimado Código 1,procurando a relação de mensagens que possam existir em nossa fila, denominada qDestino, conforme apresentado abaixo:
1 2 3 4 5 6 |
/* Código 1 – Procurando a relação de Mensagens na Fila – qDestino */ USE MyDatabaseServiceBroker GO SelectCast(Message_Body asXml)from qDestino Go |
Note que após o Codigo 1 ser executado o Management Studio deverá apresentar a nossa relação de mensagens armazenadas na Fila qDestino, onde o resultado deverá ser no formato de XML, pois nossas mensagens foram criadas e enviadas neste formato. A Figura 1 apresentada abaixo ilustra este resultado:
Figura 1 – Relação de Mensagens armazenadas na Fila qDestino.
Já sabemos quais mensagens estão presentes neste fila, e agora o próximo passo é realizar a leitura e recebimento dos dados que estão contidos em nossa mensagem. Para isso, vamos utilizar o bloco de código 2, apresentado na seqüência:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* Código 2 – Realizando a Leitura e Recebimento de Dados */ USE MyDatabaseServiceBroker GO Declare @MyConversationHandle UniqueIdentifier, @MyMessage_Body XML, @MyMessage_Type_Name sysname; /* Iniciando o Bloco de Transação */ BeginTransaction; /* Realizando o Recebimento da Mensagem */ RECEIVETOP(1) @MyMessage_Type_Name = message_type_name, @MyConversationHandle = conversation_handle, @MyMessage_Body = message_body FROM [qDestino] /* Apresentando o Retorno da Mensagem */ SELECT @MyMessage_Body As MyMessage /* Confirmando o Bloco de Transação */ Commit |
Pois bem, você viu como foi simples e fácil obter os dados na nossa Mensagem que estava armazenada na Fila qDestino, em nenhum momento precisamos realizar qualquer tipo de configuração complexa ou necessitar de recursos externos.
O Service Broker é totalmente capaz de retornar os dados, o segredo esta no uso do comando Receive em conjunto com a cláusula Top, onde informamos a quantidade de mensagens que deveriam ser retornadas, em seguida através do comando Select apresentamos o conteúdo da variável @MyMessage_Body. Para ilustrar ainda mais, a Figura 2 apresenta o conteúdo da mensagem que acabamos de recuperar:
Figura 2 – Conteúdo da mensagem recuperado através do comando Receive.
Neste momento, se você quiser consultar o conteúdo existente na fila qDestino, poderá observar que esta mensagem já não esta mais presente.
Após tudo ter corrido normalmente e dentro do espero, o último passo que iremos realizar, consiste basicamente em analisar uma mensagem que iremos consultar dentro da nossa fila qDestino, com base, no seu retorno interagir com nosso diálogo e devolver uma mensagem para fila qOrigem, finalizando o processo de envio e recebimento de mensagens. Para tal finalidade vamos utilizar os Blocos de Código 3 e 4, apresentados a seguir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
/* Código 3 – Enviando Mensagem */ USE MyDatabaseServiceBroker GO Declare @MyConversationHandle Uniqueidentifier BeginTransaction /* Inicia um diálogo entre os serviços da origem e destino */ BEGIN DIALOG @MyConversationHandle FROMSERVICE [sOrigem] TOSERVICE 'sDestino' ONCONTRACT [cProcessaMensagens] WITHENCRYPTION=OFF, LIFETIME= 600; /* Declarando a Estrutura e Conteúdo da Mensagem */ Declare @MyMensagemServiceBroker XML SET @MyMensagemServiceBroker = N'<!--?xml version=”1.0″?--> Minha segunda mensagem Olá esta é a segunda mensagem de teste no Service Broker '; /* Enviando uma mensagem no Diálogo */ SENDONCONVERSATION @MyConversationHandle MESSAGETYPE [mtEnvioMensagem](@MyMensagemServiceBroker) Commit Transaction /* Código 4 – Respondendo a Mensagem – Interagindo com o Diálogo */ USE MyDatabaseServiceBroker GO Declare @MyConversationHandle UniqueIdentifier, @MyMessage_Body XML, @MyMessage_Type_Name sysname; /* Iniciando o Bloco de Transação */ BeginTransaction; /* Realizando o Recebimento da Mensagem */ RECEIVETOP(1) @MyMessage_Type_Name = message_type_name, @MyConversationHandle = conversation_handle, @MyMessage_Body = message_body FROM [qDestino] /* Verifica se a mensagem foi enviada através da Message Type – mtEnviomensagem */ if @MyMessage_Type_Name = N’mtEnvioMensagem’ Begin DECLARE @MySourceMessage XML SET @MySourceMessage = 'Retorno da Mensagem de Destino foi respondida para Origem.'; SENDONCONVERSATION @MyConversationHandle –- Interage no mesmo diálogo MESSAGETYPE [mtEnvioMensagem](@MySourceMessage) /* Finaliza o diálogo encerrando a conversação */ ENDCONVERSATION @MyConversationHandle End /* Finaliza o Bloco de Transação */ COMMITTransaction |
Ao executarmos estes dois blocos de códigos realizamos o processo completo de envio e recebimento de mensagens através dos recursos que configuramos para o Service Broker, nosso último passo é verificar as mensagem na Fila qOrigem, como forma, de garantir e ter certeza que a mensagem de retorno foi recebida, vamos então fazer uso do Bloco de Código 5, apresentado na seqüência.
1 2 3 4 5 6 7 8 9 |
/* Código 5 – Consultando as Mensagens de Retorno na Fila qOrigem */ USE MyDatabaseServiceBroker GO SELECT cast(message_body asXML) FROM [qOrigem]; Go RECEIVE Cast(message_body asxml) FROM [qOrigem]; Go |
Ao executar este bloco de código, você vai poder observar que não estamos fazendo nada de diferente, simplesmente utilizando o comando Select para consultar as informações na Fila qOrigem, em seguida recebendo os dados utilizando o comando Receive.
Feliz ano novo!!!
Obrigado pelo artigo. Muito Bom.
Uma dúvida, como podemos fazer o gerenciamento do uso de CPU no Service Broker. Eu vi que é possível usar o Ressource Governor, porém somente na versão Enterprise, que no momento não é intressante para minha empresa.
Existe outros métodos capazes de gerenciar o uso da CPU. Eu gostaria de “deixar o processamento de mensagens” mais lento para garantir que o uso da CPU ficasse dedicado as transações SQL que ocorre com a aplicação que temos. E quando o Servidor estiver “ocioso” eu gostaria de usar força máxima da CPU para processar as Mensagens na fila.
Portanto eu procuro uma forma de não usar muito a CPU para o service broker quando o uso da CPU já estiver alto em outros processos da máquina.
Há tecnicas para isto?
Obrigado.