发行说明


|20.5 使用方案

|可在各种方案中使用“MQSeries 函数”。本节将复查一些较常见的方案,包括“基本消息传递”、“应用程序连通性”和“数据发布”。

|20.5.1 基本消息传递

|在所有数据库应用程序连接至同一 DB2 服务器时,会使用以“MQSeries DB2 函数”进行消息传递的最基本形式。客户机对于数据库服务器可以是本地的,也可以分布在网络环境中。

|在简单方案中,“客户机 A”调用 MQSEND |函数将用户定义字符串发送至缺省服务位置。然后,会在数据库服务器上的 DB2 |内执行 MQSeries 函数。稍后,“客户机 B”会调用 MQRECEIVE 函数来除去缺省服务定义的队列的顶部的消息,并将其返回至客户机。 DB2 会再一次地执行 MQSeries 函数以进行此工作。

|数据库客户机可以多种方式使用简单消息传递。消息传递的某些常见用法包括: |

|以下方案扩展上述简单方案以合并远程消息传递。即,在“机器 A”和“机器 B”之间发送消息。步骤的顺序如下所示: |

  1. |“DB2 客户机”执行 MQSEND 调用,指定已定义为在“机器 B”上表示远程队列的目标服务。
  2. |MQSeries DB2 函数执行实际的 MQSeries 工作以发送消息。“机器 A”上的 MQSeries |服务器接受该消息并保证它会将该消息发送至服务点定义和“机器 A”的当前配置定义的目的地。服务器确定这是“机器 B”上的队列。然后,它会尝试将该消息发送至“机器 B”上的 |MQSeries 服务器,在需要时显式重试。
  3. |“机器 B”上的 MQSeries 服务器从“机器 A”上的服务器接受该消息,并将其放在“机器 B”上的目标队列中。
  4. |“机器 B”上的 MQSeries 客户机请求队列顶部的消息。 |

|20.5.2 发送消息

|使用 MQSEND,DB2 用户或开发者选择要发送什么数据,要发送到哪里,以及何时发送。在业界,这通常称之为“发送并遗忘”,表示发送方只根据 MQSeries 的承诺发送协议发送消息,以确保该消息到达目的地。以下示例演示了此过程。

|示例 4:: 要将用户定义字符串发送至带有策略 highPriority 的服务点 myPlace:

|VALUES DB2MQ.MQSEND('myplace','highPriority','test')

|此处的策略 highPriority 指的是在“AMI 库”中定义的策略,它将 MQSeries 优先级设置为最高级别,并可能会调整其他服务质量,如持久性,等等。

|消息内容可能由 SQL 和用户指定数据的任何合法组合组成。这包括嵌套函数、运算符和强制转型。例如,假定有一个表 EMPLOYEE,带有 VARCHAR 列 LASTNAME、FIRSTNAME 和 DEPARTMENT,要对 DEPARTMENT 5LGA 中的每个雇员发送包含此信息的消息,应执行下列操作:

|示例 5:

|SELECT DB2MQ.MQSEND(LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT)  
|   FROM EMPLOYEE 
|      WHERE DEPARTMENT = '5LGA'

|如果此表还包含整数 AGE 列,还应包括下列各项:

|示例 6:

|SELECT DB2MQ.MQSEND
|      (LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT|| ' ' || char(AGE)) 
|   FROM EMPLOYEE
|   WHERE DEPARTMENT = '5LGA'

|如果表 EMPLOYEE 具有类型为 CLOB 的 RESUME 列而不是 AGE 列,则可以利用下列语句来发出包含 DEPARTMENT 5LGA 中的每个职员的信息的消息:

|示例 7:

|SELECT DB2MQ.MQSEND
|      (clob(LASTNAME) || ' ' || clob(FIRSTNAME) || ' ' || clob(DEPARTMENT) || ' ' || RESUME))
|   FROM EMPLOYEE
|   WHERE DEPARTMENT = '5LGA'

|示例 8:

|最后,以下示例显示如何使用任何有效的 SQL 表达式派生消息内容。 |假定有一个辅助表 DEPT 包含 VARCHAR 列 DEPT_NO 和 DEPT_NAME,可发送包含雇员 LASTNAME 和 DEPT_NAME 的消息:

|示例 8:

|SELECT DB2MQ.MQSEND(e.LASTNAME || ' ' || d.DEPTNAME) FROM EMPLOYEE e, DEPT d
|   WHERE e.DEPARTMENT = d.DEPTNAME

|20.5.3 检索消息

|“MQSeries DB2 函数”允许接收或读取消息。读取和接收的区别在于读取会在队列顶部返回该消息而不会从队列中除去它,而接收操作会从队列中除去该消息。使用接收操作检索的消息只能被检索一次,而使用读取操作检索的消息允许同一消息被检索多次。以下示例演示了此过程:

|示例 8:

|VALUES DB2MQ.MQREAD()

|此示例在由缺省服务使用缺省服务质量策略定义的队列顶部返回包含该消息的 |VARCHAR 字符串。非常重要的一点就是要注意,如果没有任何消息可供读取,将返回空值。此操作不会更改队列。

|示例 9:

|VALUES DB2MQ.MQRECEIVE('Employee_Changes')

|上述示例显示如何从由 Employee_Changes 服务使用缺省策略定义的队列顶部除去消息。

|DB2 有一个非常强大的功能部件能够通过用户定义(或 DB2 提供的)函数生成表。可使用此表函数功能部件来允许队列的内容具体化为一个 |DB2 表。以下示例演示了此过程的最简单形式:

|示例 10:

|SELECT t.* FROM table ( DB2MQ.MQREADALL()) t 

|此查询返回由缺省服务定义的队列中的所有消息和有关这些消息的元数据组成的表。虽然返回的表结构的完整定义是在“附录”中定义的,但第一列仍然会返回该消息的内容和包含元数据的其余列。要想只返回这些消息,示例应重写为:

|示例 11:

|SELECT t.MSG FROM table (DB2MQ.MQREADALL()) t

|表函数返回的表与从数据库直接检索的表完全相同。这表示可以各种各样的方式来使用此表。例如,可将一个表的内容与另一个表连在一起或计算队列中消息的数目:

|示例 12:

|SELECT t.MSG, e.LASTNAME
|   FROM table (DB2MQ.MQREADALL() ) t, EMPLOYEE e
|      WHERE t.MSG = e.LASTNAME

|示例 13:

|SELECT COUNT(*) FROM table (DB2MQ.MQREADALL()) t

|还可隐藏表的源是根据表函数创建视图的队列的事实。例如,以下示例根据服务 NEW_EMPLOYEES 引用的队列创建称为 NEW_EMP 的视图:

|示例 14:

|CREATE VIEW NEW_EMP (msg) AS
|   SELECT t.msg FROM table (DB2MQ.MQREADALL()) t

|在此示例中,视图是使用包含整条消息的单个列定义的。如果只是简单组织了消息(例如包含两个固定长度的字段),它会直接使用 DB2 内置函数来将该消息分为两列。例如,如果知道发送至特定队列的消息总是包含一个 |18 字符的姓,且后跟 18 字符的名,则可定义一个视图,将每个字段作为单独的列来包含,如下所示:

|示例 15:

|CREATE VIEW NEW_EMP2 AS
|   SELECT left(t.msg,18) AS LNAME, right(t.msg,18) AS FNAME
|   FROM table(DB2MQ.MQREADALL()) t

|“DB2 存储过程构建器”的新功能部件“MQSeries 辅助程序向导”可用来创建新的 DB2 表函数和视图,它们会将定界消息结构映射为列。

|最后,将一条或多条消息的内容存储到数据库中通常是最好的。这可通过使用 SQL |全权处理并存储消息内容来完成。此过程的可能的最简单示例为:

|示例 16:

|INSERT INTO MESSAGES
|   SELECT t.msg FROM table (DB2MQ.MQRECEIVEALL()) t

|假定有一个表 MESSAGES,带有一列 VARCHAR(2000),上述语句会将这些消息从缺省服务队列插入表。可利用此技术来应付各种各样的情况。

|20.5.4 应用程序间的连通性

|应用程序集成是许多解决方案中的一个常见元素。无论是将购买的应用程序集成到现有基本设施中,还是仅将新开发的应用程序集成到现有环境中,我们通常会面对的任务是将不同集合的子系统连接到一起以作为一个整体来运作。MQSeries |通常被视作集成应用程序的基本工具。在大部分硬件、软件和语言环境中都可使用 |MQSeries,它提供了非常不同的集合的应用程序互连的方式。

|本节将讨论某些应用程序集成方案以及它们如何与 DB2 配合使用。因为主题非常广泛,所以“应用程序集成”的完善处理超出了此工作的范围之外。因此,重点只放在两个简单的主题上:“请求/应答通信”,以及“MQSeries 集成器和发布/预订”。

|20.5.4.1 请求/应答通信

|对于一个应用程序请求另一个应用程序的服务,“请求/应答”(R/R)通信方法是非常常见的技术。完成此任务的一个方法就是让请求者向服务提供程序发送一条消息,请求执行一些工作。一旦工作完成,提供程序可能会决定将结果(或只是完成的确认信息)发送回请求者。但使用上述的基本消息传递技术,并非是将发送方的请求与服务提供程序的响应连接在一起。除非请求者要等到应答才继续进行,否则必须使用一些机制来将每个应答与其请求相关联。MQSeries |并不强制开发者创建这些机制,它提供了相关标识符,允许交换中的消息相关。

|虽然可以多种方法来使用此机制,但最简单的方法是让请求者以使用如下所示的已知相关标识符来标记消息:

|示例 17:

|DB2MQ.MQSEND ('myRequester','myPolicy','SendStatus:cust1','Req1')

|此语句将最终参数 Req1 添加至以上的 MQSEND 语句,以指示请求的相关标识符。

|要接收对此特定请求的应答,使用相应的 MQRECEIVE 语句来有选择地检索指示服务定义的,与此相关标识符相匹配的第一条消息,如下所示:

|示例 18:

|DB2MQ.MQRECEIVE('myReceiver','myPolicy','Req1')

|如果响应请求的应用程序正忙,且请求者在应答送出之前发出了上述 MQRECEIVE,则表明找不到与此相关标识符匹配的任何消息。

|要接收服务请求和相关标识符,使用类似如下的语句:

|示例 19:

|SELECT msg, correlid FROM table (DB2MQ.MQRECEIVEALL('aServiceProvider','myPolicy',1)) t

|这会返回来自服务 aServiceProvider 的第一个请求的消息和相关标识符。

|一旦执行了服务,它就会将应答消息发送至 aRequester 所描述的队列。其间,服务请求者可能正进行其他工作。实际上,并不能保证会在设置时间内响应服务请求。这种应用程序级别超时必须由开发者管理;请求者必须进行轮询以检测是否有应答。

|这种与时间无关的异步处理的优点就在于请求者和服务供应商在执行时是完全独立的。它可用来配合仅间歇连接应用程序的环境以及在聚集多个请求或应答之后才进行处理的多个面向批处理的环境。通常在数据仓库环境中使用这种聚合以定期更新数据仓库或操作性数据仓库。

|20.5.4.2 发布/预订

|简单数据发布

|应用程序集成的另一常见方案是让一个应用程序通知其他应用程序所关心的事件。可通过将一条消息发送至由另一应用程序监视的队列很容易地完成此操作。消息的内容可以是用户定义字符串,或者,可由数据库列组成。通常,只需要使用 MQSEND 函数发送简单的消息。如果需要将这种消息并行发送至多个收件人,可使用 MQSeries AMI 的“分发列表”设施。

|分发列表是使用“AMI 管理”工具定义的。“分发列表”包含个别服务的列表。发送至分发列表的消息被转发至列表内定义的每个服务。这在已知几个服务始终对每条消息都有兴趣的情况下特别有用。以下示例显示了将消息发送至分发列表 |interestedParties 的过程:

|示例 20:

|DB2MQ.MQSEND('interestedParties','information of general interest');

|如果需要对特定服务应接收的消息进行更多的控制,则需要“发布/预订”功能。“发布/预订”系统通常会提供可伸缩的安全的环境,许多订户都可在其中进行注册以从多个发布者接收消息。要支持此功能,可将 MQPublish 接口与“MQSeries 集成器”或“MQSeries 发布/预订”设施配合使用。

|MQPublish 允许用户选择指定要与消息相关联的主题。主题允许订户更明确地指定要接受的消息。步骤序列如下所示:

  1. |MQSeries 管理员配置“MQSeries 集成器”发布/预订功能。
  2. |感兴趣的应用程序预订至 MQSI 配置定义的预订点,可选择对其感兴趣的主题。每个订户选择相关主题,还可利用“MQSeries 集成器 V2”的基于内容的预订技术。很重要的一点就是要注意到,队列(由服务名表示)定义订户。
  3. |DB2 应用程序将消息发布至服务点“天气”。该消息指示天气是“雨加雪”(带有主题 Austin),并从而通知感兴趣的订户 Austin 的天气是“雨加雪”。
  4. |实际发布消息的机制是由 DB2 提供的 MQSeries 函数处理的。使用服务“天气”将该消息发送至“MQSeries 集成器”。
  5. |MQSI 从“天气”服务接受该消息,执行 MQSI 配置定义的任何处理,并确定它满足哪些预订。然后,MQSI 将该消息转发至它满足其标准的订户队列。
  6. |已预订至“天气”服务且注册为对 Austin 有兴趣的应用程序将在其接收服务中接收消息雨加雪|

|要使用所有缺省值和空主题发布此数据,应使用以下语句:

|示例 21:

|SELECT DB2MQ.MQPUBLISH(LASTNAME || ' ' || FIRSTNAME || ' ' || DEPARTMENT|| ' ' ||char(AGE))
|   FROM EMPLOYEE
|      WHERE DEPARTMENT = '5LGA'

|完整指定所有参数,并将该消息简化为只包含 LASTNAME,该语句将类似如下所示:

|示例 22:

|SELECT DB2MQ.MQPUBLISH('HR_INFO_PUB', 'SPECIAL_POLICY', LASTNAME,
|   'ALL_EMP:5LGA', 'MANAGER')
|   FROM EMPLOYEE
|      WHERE DEPARTMENT = '5LGA'

|此语句将使用 SPECIAL_POLICY 服务将消息发布至 HR_INFO_PUB 发布服务。这些消息指示发送方是 |MANAGER 主题。主题字符串演示多个主题,可指定使用 ':' 将它们连接起来。在此示例中,使用两个主题允许订户向 ALL_EMP 注册或仅向 5LGA 注册以接收这些消息。

|要接收发布的消息,必须首先注册对包含给定主题的消息的兴趣,并指示应将消息发送至的订户服务的名称。很重要的一点就是要注意到,AMI 订户服务定义代理服务和接收方服务。代理服务是订户与“发布/预订”代理进行通信的方式,而接收方服务是要将与预订请求相匹配的消息发送至的位置。以下语句注册对主题 ALL_EMP 的兴趣。

|示例 23:

|DB2MQ.MQSUBSCRIBE('aSubscriber', 'ALL_EMP')

|一旦应用程序已预订,使用主题 ALL_EMP 发布的消息将转发至由订户服务定义的接收方服务。应用程序可有多个并行预订。要获取满足预订的消息,可使用任何标准消息检索函数。例如,如果订户服务 aSubscriber 将接收方服务定义为 aSubscriberReceiver,则以下语句将以非破坏的形式读取第一条消息:

|示例 24:

|DB2MQ.MQREAD('aSubscriberReceiver')

|要确定消息和在其中发布这些消息的主题,应使用其中一个表函数。以下语句将从 |aSubscriberReceiver 接收头五条消息,并显示消息和主题:

|示例 25:

|SELECT t.msg, t.topic FROM table (DB2MQ.MQRECEIVEALL('aSubscriberReceiver',5)) t

|要读取带有主题 ALL_EMP 的所有消息,可利用 SQL 的功能来发出:

|示例 26:

|SELECT t.msg FROM table (DB2MQ.MQREADALL('aSubscriberReceiver')) t 
|   WHERE t.topic = 'ALL_EMP'
|注意:
很重要的一点就是要认识到,如果 MQRECEIVEALL 在使用时带有约束,则会影响整个队列,而不仅仅是那些使用主题 ALL_EMP 发布的消息。这是因为先执行了表函数,再才应用约束。 |

|如果不再对预订至特定主题感兴趣,则必须使用如下语句显式取消预订:

|示例 27:

|DB2MQ.MQUNSUBSCRIBE('aSubscriber', 'ALL_EMP')

|一旦发出了此语句,发布/预订代理就不再发送与此预订相匹配的消息。

|自动发布

|数据库消息传递的另一重要技术就是自动发布。在 DB2 |内使用触发器设施,可作为触发器调用的一部分来自动发布消息。虽然对于自动数据发布还存在其他技术,但基于触发器的方法允许管理员或开发者在构造消息内容方面有极大的自由,且在触发器操作方面有着很高的灵活性。就象使用任何触发器一样,必须注意执行的频率和成本。下列示例演示了如何将触发器与“MQSeries DB2 函数”配合使用。

|以下示例显示每次雇用一个新员工时发布一条消息是很容易的。预订至 HR_INFO_PUB 服务且注册了对 |NEW_EMP 的兴趣的任何用户或应用程序都将接收包含每个新员工的日期、名称和部门的消息。

|示例 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)


[ 页的顶部 | 上一页 | 下一页 | 目录 | 索引 ]