|As Funções do MQSeries podem ser utilizadas em uma grande variedade de |cenários. Essa seção reexibirá alguns dos cenários mais comuns, |incluindo as Mensagens Básicas, a Conectividade do Aplicativo e a Publicação |de Dados.
|A forma mais básica de mensagens com as Funções do MQSeries DB2 ocorre |quando todos os aplicativos do banco de dados conectam-se ao mesmo servidor do |DB2. Os cientes podem ser locais para o servidor do banco de dados ou |distribuídos em um ambiente de rede.
|Em um cenário simples, o Cliente A invoca a função MQSEND para enviar uma |cadeia definida pelo usuário para a localização de serviço padrão. As |funções do MQSeries são executadas dentro do DB2 no servidor do banco de |dados. Em algum momento posterior, o Cliente B invoca a função |MQRECEIVE para remover a mensagem na cabeça da fila definida pelo serviço |padrão e retorna-a para o cliente. Novamente, as funções do MQSeries |para executar esse trabalho são executadas pelo DB2.
|Os clientes do banco de dados podem utilizar mensagens simples de várias |maneiras. Alguns usos comuns para as mensagens são: |
|O cenário a seguir estende o cenário simples descrito acima, para |incorporar mensagens remotas. Isto é, uma mensagem é enviada entre a |Máquina A e a Máquina B. A seqüência de etapas é a seguinte: |
|Utilizando MQSEND, um usuário ou um desenvolvedor do DB2 escolhe quais |dados enviar, para onde enviá-los e quando ele será enviado. Na |indústria, este é comumentemente chamado "Enviar e Esquecer," significando que |o emissor apenas envia uma mensagem, confiando nos protocolos de entrega |garantidos do MQSeries para assegurar-se de que a mensagem atinge seu |destino. Os exemplos a seguir ilustram isso.
|Exemplo 4: Para enviar uma cadeia definida pelo usuário para o ponto |de serviço myPlace com a política highPriority:
|VALUES DB2MQ.MQSEND('myplace','highPriority','test')
|Aqui, a política highPriority refere-se a uma política definida no |Repositório da AMI que define a prioridade do MQSeries para o nível mais alto |e talvez ajusta melhor outras qualidades de serviço, tal como |persistência.
|O conteúdo da mensagem pode ser composto de qualquer combinação legal de |dados do SQL e especificados pelo usuário. Isso inclui funções |aninhadas, operadores e coletas. Por exemplo, determinado uma tabela |EMPLOYEE, com VARCHAR colunas LASTNAME, FIRSTNAME e DEPARTMENT, para enviar |uma mensagem que contém essas informações para cada empregado no DEPARTMENT |5LGA você fará o seguinte:
|Exemplo 5:
|SELECT DB2MQ.MQSEND(LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT) | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Se esta tabela também tiver uma coluna AGE inteira, ela poderá ser incluída |como segue:
|Exemplo 6:
|SELECT DB2MQ.MQSEND | (LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT|| ' ' || char(AGE)) | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Se a tabela EMPLOYEE tivesse uma coluna RESUME do tipo CLOB em vez de uma |coluna AGE, uma mensagem contendo as informações de cada funcionário no |DEPARTMENT 5LGA poderia ser emitida com o seguinte:
|Exemplo 7:
| SELECT DB2MQ.MQSEND | (clob(LASTNAME) || ' ' || clob(FIRSTNAME) || ' ' || | clob(DEPARTMENT) || ' ' || RESUME)) | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Exemplo 8:
|Finalmente, o exemplo a seguir mostra como o conteúdo da mensagem pode ser |derivado utilizando qualquer expressão de SQL válida. Dada uma segunda |tabela DEPT com as colunas VARCHAR DEPT_NO e DEPT_NAME, é possível enviar |mensagens contendo o LASTNAME e o DEPT_NAME do funcionário:
|Exemplo 8:
|SELECT DB2MQ.MQSEND(e.LASTNAME || ' ' || d.DEPTNAME) FROM EMPLOYEE e, DEPT d | WHERE e.DEPARTMENT = d.DEPTNAME
|As Funções do MQSeries DB2 permitem que as mensagens sejam recebidas ou |lidas. A diferença entre a leitura e o recebimento é que a leitura |retorna a mensagem na cabeça de uma fila sem removê-la da fila, enquanto que |as operações de recebimento fazem com que a mensagem seja removida da |fila. Uma mensagem recuperada utilizando uma operação de recebimento |pode apenas ser recuperada uma vez, enquanto que uma mensagem recuperada |utilizando a operação de leitura permite que a mesma mensagem seja recuperada |muitas vezes. Os exemplos a seguir demonstram isto:
|Exemplo 8:
|VALUES DB2MQ.MQREAD()
|Esse exemplo retorna uma cadeia VARCHAR contendo a mensagem na cabeça da |fila definida pelo serviço padrão que utiliza a qualidade de política de |serviço padrão. É importante observar que se nenhuma mensagem estiver |disponível para ser lida, um valor nulo será retornado. A fila não é |alterada por esta operação.
|Exemplo 9:
|VALUES DB2MQ.MQRECEIVE('Employee_Changes')
|O exemplo acima mostra como uma mensagem pode ser removida da cabeça da |fila definida pelo serviço Employee_Changes que utiliza a política |padrão.
|Um recurso muito poderoso do DB2 é a capacidade de gerar uma tabela de uma |função definida pelo usuário (ou fornecida pelo DB2-). Você pode |explorar esse recurso de função da tabela para permitir que o conteúdo de uma |fila seja materializado como uma tabela do DB2. O exemplo a seguir |demonstra a forma mais simples disso:
|Exemplo 10:
|SELECT t.* FROM tabela ( DB2MQ.MQREADALL()) t
|Essa consulta retorna uma tabela que consiste em todas as mensagens na fila |definidas pelo serviço padrão e os metadados sobre estas mensagens. |Enquanto o destino completo da estrutura da tabela retornada é definido no |Apêndice, a primeira coluna reflete o conteúdo da mensagem e as colunas |restantes contêm os metadados. Para retornar apenas as mensagens, o |exemplo pode ser regravado:
|Exemplo 11:
|SELECT t.MSG FROM tabela (DB2MQ.MQREADALL()) t
|A tabela retornada por uma função da tabela não é diferente de uma tabela |recuperada diretamente do banco de dados. Isso significa que você pode |utilizar essa tabela em uma grande variedade de maneiras. Por exemplo, |você pode unir o conteúdo da tabela com outra tabela ou contar o número de |mensagens em uma fila:
|Exemplo 12:
|SELECT t.MSG, e.LASTNAME | FROM tabela (DB2MQ.MQREADALL() ) t, EMPLOYEE e | WHERE t.MSG = e.LASTNAME
|Exemplo 13:
|SELECT COUNT(*) FROM tabela (DB2MQ.MQREADALL()) t
|Você também pode ocultar o fato de que a origem da tabela é uma fila, |através da criação de uma exibição em uma função da tabela. Por |exemplo, o exemplo a seguir cria uma exibição chamada NEW_EMP na fila referida |pelo serviço nomeado NEW_EMPLOYEES:
|Exemplo 14:
|CREATE VIEW NEW_EMP (msg) AS | SELECT t.msg FROM tabela (DB2MQ.MQREADALL()) t
|Nesse caso, a exibição é definida apenas com uma única coluna que contém |uma mensagem inteira. Se as mensagens são apenas estruturadas, para a |instância que contém dois campos de comprimento fixo, é correto utilizar as |funções incorporadas do DB2 para analisar a mensagem nas duas colunas. |Por exemplo, se você souber que as mensagens enviadas para uma fila específica |sempre contêm um sobrenome de 18 caracteres seguido de um primeiro nome de 18 |caracteres, você poderá definir uma exibição que contém cada campo como uma |coluna separada como segue:
|Exemplo 15:
|CREATE VIEW NEW_EMP2 AS | SELECT left(t.msg,18) AS LNAME, right(t.msg,18) AS FNAME | FROM tabela(DB2MQ.MQREADALL()) t
|Um novo recurso do DB2 Stored Procedure Builder, o Assistente Assist do |MQSeries, pode ser utilizado para criar novas funções e exibições da tabela do |DB2 que irão mapear estruturas de mensagens delimitadas para as |colunas.
|Finalmente é desejável armazenar o conteúdo de uma ou mais mensagens no |banco de dados. Isso pode ser feito utilizando a energia completa do |SQL para manipular e armazenar o conteúdo da mensagem. Talvez o exemplo |mais simples disso é:
|Exemplo 16:
|INSERT INTO MESSAGES | SELECT t.msg FROM tabela (DB2MQ.MQRECEIVEALL()) t
|Determinado uma tabela MESSAGES, com uma única coluna VARCHAR(2000), a |instrução acima irá inserir as mensagens da fila de serviços padrão na |tabela. Essa técnica pode ser aprimorada para abranger uma grande |variedade de circunstâncias.
|A integração de aplicativos é um elemento comum em muitas soluções. |Se integrar um aplicativo comprado em uma infra-estrutura existente ou apenas |integrar um aplicativo recentemente desenvolvido em um ambiente existente, |muitas vezes, estaremos voltados com a tarefa de unir uma coleta heterogênea |de subsistemas juntos para formar todo um trabalho. O MQSeries é |comumentemente exibido como uma ferramenta essencial de integrar |aplicativos. Acessível na maioria dos ambientes de hardware, software e |de linguagem, o MQSeries fornece o meio de interconectar uma coleção muito |heterogênea de aplicativos.
|Essa seção discutirá alguns cenários de integração do aplicativo e como |eles podem ser utilizados com o DB2. Como o tópico é muito abrangente, |um tratamento compreensivo de Integração do Aplicativo vai além do escopo |desse trabalho. Entretanto, o foco está exatamente em dois tópicos |simples: comunicação de Pedido/Resposta e MQSeries Integrator e |Publish/Subscribe.
|O método de comunicações de Pedido/Resposta (P/R) é uma técnica muito comum |para um ID de aplicativo solicitar os serviços de outro. Uma maneira de |fazer isso é para o solicitador enviar uma mensagem para o provedor de serviço |solicitando o mesmo trabalho a ser executado. Quando o trabalho foi |concluído, o provedor pode decidir enviar os resultados (ou apenas uma |confirmação de conclusão) de volta para o solicitador. Mas utilizar as |técnicas de mensagens básicas descritas acima, não há nada que conecta o |pedido do emissor à resposta do provedor de serviço. A menos que o |solicitador aguarde uma resposta antes de continuar, algum mecanismo deve ser |utilizado para associar cada resposta a seu pedido. Em vez de forçar o |desenvolvedor a criar esse mecanismo, o MQSeries fornece um identificador de |correlação que permite a correlação de mensagens em uma troca.
|Enquanto existe um número de maneiras no qual esse mecanismo pode ser |utilizado, o mais simples é para o solicitador marcar uma mensagem com um |identificador de correlação conhecido utilizando, por exemplo, o |seguinte:
|Exemplo 17:
|DB2MQ.MQSEND ('myRequester','myPolicy','SendStatus:cust1','Req1')
|Essa instrução inclui um parâmetro final Req1 na instrução MQSEND acima, |para indicar o identificador de correlação do pedido.
|Para receber uma resposta a esse pedido específico, utilize a instrução |MQRECEIVE correspondente para recuperar seletivamente a primeira mensagem |definida pelo serviço indicado que corresponda a esse identificador de |correlação, como a seguir:
|Exemplo 18:
|DB2MQ.MQRECEIVE('myReceiver','myPolicy','Req1')
|Se o aplicativo que atende o pedido estiver ocupado e o solicitador emitir |o MQRECEIVE acima antes da resposta ser enviada, nenhuma mensagem que |corresponda a esse identificador de correlação será encontrada.
|Para receber o pedido de serviço e o identificador de correlação, uma |instrução como a seguinte é utilizada:
|Exemplo 19:
|SELECT msg, correlid FROM | table (DB2MQ.MQRECEIVEALL('aServiceProvider','myPolicy',1)) t
|Isso retorna a mensagem e o identificador de correlação do primeiro pedido |do aServiceProvider de serviço.
|Quando o serviço foi executado, ele envia a mensagem de resposta para a |fila descrita pelo aRequester. Entretanto, o solicitador de serviço |pode ter realizado outro trabalho. De fato, não existe nenhuma garantia |que o pedido de serviço inicial será respondido dentro do tempo |definido. Os tempos limites do nível de aplicativo tais como este, |devem ser gerenciado pelo desenvolvedor; o solicitador deve ser |controlado para detectar a presença da resposta.
|A vantagem de tal processamento assíncrono independente de tempo é que o |solicitador e o provedor de serviço são executados completamente independentes |um do outro. Estes podem ser utilizados para acomodar os ambientes nos |quais os aplicativos são conectados apenas intermitentemente e mais ambientes |orientados em batch nos quais vários pedidos ou respostas são agregados antes |do processamento. Esse tipo de agregação é freqüentemente utilizado em |ambientes de warehouse de dados, para atualizar periodicamente um warehouse de |dados ou armazenamento de dados operacional.
|Outro cenário comum na integração de aplicativos é para um aplicativo |notificar outros aplicativos sobre os eventos de interesse. Isso é |facilmente feito enviando uma mensagem para uma fila monitorada por outro |aplicativo. O conteúdo da mensagem pode ser uma cadeia definida pelo |usuário ou pode ser composto de colunas do banco de dados. Muitas |vezes, uma mensagem simples é tudo o que precisa para ser enviada utilizando a |função MQSEND. Quando tais mensagens precisam ser enviadas |concorrentemente para vários destinatários, o recurso da Lista de Distribuição |da MQSeries AMI pode ser utilizado.
|Uma lista de distribuição é definida utilizando a ferramenta AMI |Administration. Uma lista de distribuição abrange uma lista de serviços |individuais. Uma mensagem enviada para uma lista de distribuição é |encaminhada para cada serviço definido dentro da lista. Isso é, |especialmente, útil quando sabe-se que poucos serviços sempre estarão |interessados em toda mensagem. O exemplo a seguir mostra o envio de uma |mensagem para a lista de distribuição interestedParties:
|Exemplo 20:
|DB2MQ.MQSEND('interestedParties','informações de interesse geral');
|Quando é requerido mais controle sobre as mensagens que os serviços |específicos devem receber, uma capacidade de Publicar/Associar é |necessária. Os sistemas de publicação/associação fornecem, tipicamente, |um ambiente escalável e seguro no qual muitos assinantes podem ser registrados |para receberem mensagens de vários publicadores. Para suportar essa |capacidade da interface MQPublish poder ser utilizada, em conjunto com o |recurso MQSeries Integrator ou MQSeries Publish/Subscribe.
|O MQPublish permite que os usuários especifiquem, opcionalmente, um tópico |a ser associado a uma mensagem. Os tópicos permitem um assinante para |especificar mais claramente as mensagens a serem aceitas. A seqüência |de etapas é a seguinte: |
|Para publicar esses dados utilizando todos os padrões e um tópico nulo, |você utilizará a seguinte instrução:
|Exemplo 21:
|SELECT DB2MQ.MQPUBLISH | (LASTNAME || ' ' || FIRSTNAME || ' ' || | DEPARTMENT|| ' ' ||char(AGE)) | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Especificar completamente todos os parâmetros e simplificar a mensagem para |conter apenas o LASTNAME, a instrução se parecerá:
|Exemplo 22:
|SELECT DB2MQ.MQPUBLISH('HR_INFO_PUB', 'SPECIAL_POLICY', LASTNAME, | 'ALL_EMP:5LGA', 'MANAGER') | FROM EMPLOYEE | WHERE DEPARTMENT = '5LGA'
|Essa instrução publica mensagens para o serviço de publicação HR_INFO_PUB, |utilizando o serviço SPECIAL_POLICY. As mensagens indicam que o emissor |é o tópico MANAGER. A cadeia de tópicos demonstra que vários tópicos, |concatenados utilizando um ':' podem ser especificados. |Nesse exemplo, o uso de dois tópicos permite que os assinantes sejam |registrados para ALL_EMP ou apenas 5LGA para receber essas mensagens.
|Para receber mensagens publicadas, primeiro você deve registrar seu |interesse em mensagens que contêm um determinado tópico e indicar o nome do |serviço do assinante para o qual as mensagens devem ser enviadas. É |importante observar que um serviço do assinantes da AMI define um serviço |intermediário e um serviço do receptor. O serviço intermediário é como |o assinante que se comunica com o intermediário de publicar/associar e o |serviço do receptor está onde as mensagens que correspondem ao pedido de |assinatura serão enviadas. A instrução a seguir registra um interesse |no tópico ALL_EMP.
|Exemplo 23:
|DB2MQ.MQSUBSCRIBE('aSubscriber', 'ALL_EMP')
|Quando um aplicativo é associado, as mensagens publicadas com o tópico |ALL_EMP serão enviadas para o serviço do receptor definido pelo serviço do |assinante. Um aplicativo pode ter várias assinaturas |concorrentes. Para obter as mensagens que atendem sua assinatura, |qualquer uma das funções de recuperação de mensagem padrão podem ser |utilizadas. Por exemplo, se o aSubscriber de serviço do assinante |definir o serviço do receptor para ser aSubscriberReceiver, a instrução a |seguir lerá não-destrutivamente a primeira mensagem:
|Exemplo 24:
|DB2MQ.MQREAD('aSubscriberReceiver')
|Para determinar as mensagens e os tópicos em que eles foram publicados, |você utilizará uma das funções da tabela. A instrução a seguir receberá |as cinco primeiras mensagens do aSubscriberReceiver e exibirá a mensagem e o |tópico:
|Exemplo 25:
|SELECT t.msg, t.topic | FROM table (DB2MQ.MQRECEIVEALL('aSubscriberReceiver',5)) t
|Para ler todas as mensagens com o tópico ALL_EMP, você pode atuar sobre a |energia do SQL para emitir:
|Exemplo 26:
|SELECT t.msg FROM tabela (DB2MQ.MQREADALL('aSubscriberReceiver')) t | WHERE t.topic = 'ALL_EMP'
|Quando você não estiver mais interessado em associar um tópico específico, |é necessário desassociar explicitamente utilizando uma instrução tal |como:
|Exemplo 27:
|DB2MQ.MQUNSUBSCRIBE('aSubscriber', 'ALL_EMP')
|Quando essa instrução é emitida o intermediário de publicação/associação |não entregará mais as mensagens correspondentes a essa assinatura.
|Outra técnica importante no sistema de mensagens do banco de dados é a |publicação automatizada. Utilizando o recurso de disparo dentro do DB2, |você pode, opcionalmente, publicar mensagens como parte de uma invocação de |disparo. Enquanto existem outras técnicas para publicação de dados |automatizada, a abordagem baseada em disparo permite aos administradores ou |aos desenvolvedores grande liberdade na construção do conteúdo e da |flexibilidade da mensagem na definição das ações de disparo. Como com |qualquer uso de disparos, deve ser prestar atenção na freqüência e no custo da |execução. Os exemplos a seguir demonstram como os disparos podem ser |utilizados com as Funções do MQSeries DB2.
|O exemplo abaixo mostra como é fácil publicar uma mensagem todas vez que um |novo empregado é contratado. Todos os usuários e aplicativos associados |ao serviço HR_INFO_PUB comum interesse registrado em NEW_EMP, receberão uma |mensagem contendo a data, o nome e o departamento de cada novo |empregado.
|Exemplo 28:
|CREATE TRIGGER new_employee AFTER INSERT ON employee REFERENCING NEW AS n | FOR EACH ROW MODE DB2SQL | VALUES DB2MQ.MQPUBLISH('HR_INFO_PUB&', 'NEW_EMP', | current date || ' ' || LASTNAME || ' ' || DEPARTMENT)