您好,欢迎访问三七文档
当前位置:首页 > IT计算机/网络 > 数据库 > MQ 企业级方案设计,第 3 部分:企业级应用设计构架
细看MQ消息头(MQMD)的功能MQMD是每个消息都带有的消息头信息,它由若干字段组成,这些字段都是MQ设计人员根据总结的应用需求而设置的。应用程序构建消息时应该对这些字段填入恰当的值,对于没有填入的字段,MQ会用默认值填充。开发应用程序时,充分理解并利用这些字段是十分必要的,这里逐一为大家进行介绍,并针对每个字段指明它在实际编程中一般会用来实现什么样的功能:StrucId:消息头结构名,固定为MQMD四个字符。根据这个字段,我们就能够在应用程序数据包中识别出MQMD的位置。Version:MQMD版本号。Report:消息的报告选项,默认值为MQRO_NONE。发送方程序通过设置此字段值以指定在消息传递出现意外、消息超时、消息到达、消息递出事件时是否需要报告消息和报告消息要包含什么内容。对于需要消息报告的程序,需要对这个字段与下面介绍的ReplyToQ和ReplyToQMgr字段一起进行设置,以对这些消息事件作出反应。Expiry:超时字段,单位是0.1秒,默认值是MQEI_UNLIMITED,表示永不过期。消息放到目标队列里以后,如果超过这个指定时间还没有被程序读走,MQ系统就会丢弃这个消息。如果这个消息设置了Report字段要求超时报告,系统会按照Report字段指定的方式返回一个超时报告。应用中通常要进行必要的消息超时机制设计,比如实现SOA框架下为保持交易一致性而广泛使用的Compensation机制,就可以用超时处理实现。Feedback:反馈字段,此字段与Report字段一起使用以指示报告的性质。Encoding:消息中数值数据(binaryinteger、packed-decimalintegers、floating-pointnumbers等)的编码方式,默认值是MQENC_NATIVE,因平台而异,此值不适用于MQMD结构本身的数字数据。实际应用中,为减少复杂性,要尽量少使用二进制的数值数据,这时就不必考虑此字段。CodedCharSetId:指定消息使用的字符集编码的CCSID,默认值是MQCCSI_Q_MGR,随平台不同而不同。MQ在需要转码时根据这个字段的值来识别消息内容的编码方式,在主机上一般使用包含GBK字符集的CCSID1388,对应的UNIX和WINDOWS系统下的CCSID是1386。Format:给出描述消息体所符合的数据格式名称,格式名可以自己定义,默认值是MQFMT_NONE。应用程序可以使用这个字段来指定发送消息的格式名,接收方根据这个名字对消息体做出不同解释。Priority:消息的优先级,最低优先级是0,默认值是MQPRI_PRIORITY_AS_Q_DEF。Persistence:消息持久性值,默认值为MQPER_PERSISTENCE_AS_Q_DEF。如果消息是持久的,所有操作会记入MQLOG;如果消息不是持久的则不记LOG,MQ系统中断或重启意味着还没被处理的消息将丢失。应用程序设计时要对是否使用持久性消息进行深入的考虑,虽然持久性消息比较可靠,但它的性能比非持久消息有很大的落后,如果可以使用应用逻辑来保证数据一致性,尽量少使用持久性消息。MsgId:消息标识,它用来区分消息,由MQ自动生成,任意两个消息的MsgId都不同。程序执行MQPUT后能从MsgId字段得到发出消息的ID。MsgId在某个QMGR里是唯一的,但理论上两个QMGR可能产生相同的MsgId,虽然这种情况实际上极少会出现。编程上要注意,不要把两个QMGR产生的MsgId进行比较。CorrelId:消息相关标识,应用程序可使用它来将一个消息与另一个消息相关,或将一个消息与应用程序正在执行的其它工作相关,默认值全为空。在通常的做法中,发送请求消息的程序记录下请求消息的MsgId,服务程序读到请求消息,拿出它的MsgId放到回复信息的CorrelId字段中,发送程序在MQGET得到回复消息前,先把记录的MsgId填到消息头的CorrelId中,这样它就能GET到那条特定的回复消息。CorrelId也可以用来设计更复杂的消息传递/识别机制。BackoutCount:记载消息被回滚的次数。具体介绍参见有害的消息处理。ReplyToQ:这是回复消息队列的名称。本字段和下面的ReplyToQMgr一起,构成了消息返回目的地信息。通常消息请求程序在发送请求时,就填好这些字段,消息处理程序只简单地根据要求进行回复,通过这种方式实现动态的消息回送机制。ReplyToQMgr:这是回复消息队列所在队列管理器的名称,其默认值全为空,表示返回消息时到本地队列管理器中去找ReplyToQ。UserIdentifier:它属于MQMD的identitycontext字段,是发起消息的应用程序的用户标识。其默认值为空。AccountingToken:它属于MQMD的identitycontext字段,允许应用程序计算由消息引起的工作量的信息。其默认值为空。ApplIdentityData:它属于MQMD的identitycontext字段,是由应用程序定义的信息,可用来提供有关消息或其发起方的信息。其默认值为空。应用的请求和服务端可以进行协商,规定这个字段的一些专门用途,通过这个字段,来实现一定的自动化处理。PutApplType:它属于MQMD的origincontext字段,是放入消息的应用程序类型,标志在一个消息传递串中最近的对消息进行处理的程序的信息。例如CICS、IMS、BROKER等。其默认值为MQAT_NO_CONTEXT。通过本字段和下面的PutApplName字段,消息接收程序可以识别某条消息是谁发送过来的,并根据情况进行特殊的处理。PutApplName:它属于MQMD的origincontext字段,是放入消息的应用程序的名称。其默认值为空。GroupId:消息组标识,MQforz/OS不支持消息分组。MsgSeqNumber:组中逻辑消息的顺序号。MQforz/OS不支持消息分组。Offset:数据的偏移量,MQforz/OS不支持消息分组技术。MsgFlags:主要是与消息分组相关的一些状态信息。OriginalLength:分段消息的原始长度。MQMD的这些字段为我们应用程序的开发提供了很好的设施,例如当应用程序请求方需要一种方法确定哪些返回信息是针对哪条请求时,典型的做法有两种,一种是为每个请求动态创建一个临时队列,把队列名填入ReplyToQ字段,响应程序根据ReplyToQ里的值确定每条消息返回到哪个队列里去;另一种方法是响应方把原始请求的MsgId字段拷贝到它所发回的消息的CorrelId字段里去,发送方用MsgId搜索返回信息。又如MQ发送消息的消息头里包含了所谓的消息上下文(messagecontext)信息,这些字段描述了消息发送者的一些情况,消息上下文又包括两部分:身份鉴别上下文(Identitycontext)和发送者上下文(Origincontext)。身份鉴别上下文(Identitycontext)描述了消息最初是由谁产生的,包括MQMD的UserIdentifier、AccountingToken和ApplIdentityData字段;发送者上下文(Origincontext)描述了把消息放到队列上的应用程序的情况,包括MQMD的PutApplType,PutApplName,PutDate,PutTime,ApplOriginData字段。当应用程序把一个消息进行转发时,可以选择是重新生成这些上下文还是从原消息里继承上下文。通常的做法是最初的消息发送程序由系统根据用户信息生成所有消息上下文,对消息做修改或者转发的应用,只新生成发送者上下文(Origincontext),而身份鉴别上下文(identitycontext)最好传递从原始消息得到的上下文信息,这样在消息处理中的任意环节,都能够了解到最初发动者的用户信息。根据实际业务需求,灵活地运用这些字段,可以方便地实现复杂的系统功能。消息类型与传输控制企业中通过MQ传输的消息有多种不同的类型,不同类型的消息有不同的处理方式。通常消息可以分为以下几类:数据报(datagram)消息一种典型的异步消息传递形式,其中应用程序发送消息但不需要响应。这种消息类型是结构最简单、效率最高的类型,应用设计时要尽量可能地使用这种模式,通过MQ提供的可靠的消息传输确保消息能够得到处理,对于要求较高的环境,可以设置错误报告机制。报告消息(reportmessage)给出另一个消息相关信息的消息。报告消息能够表明消息已发送、已到达目标、已到期或由于某种原因无法处理。部分报告信息可以通过适当的设置,由系统在需要的情况下自动发送,另一些可以由应用程序根据特定的情况发送。得到报告的程序,通常需要设置发出消息的Report、ReplyToQ、ReplyToQMgr字段来设置希望的报告类型、返回队列名和返回队列管理器。在应用设计中,把业务需求和报告消息的功能结合起来,能够解决很多种实际需求。同步的请求/应答消息(request/replymessage)通过MQ实现同步的请求/应答机制:一个程序发送请求消息,通过MQ传送给消息处理方,然后到特定队列上去守听应答消息。消息处理程序从MQ获取输入后,进行特定的处理,然后把应答消息写入返回队列。请求程序得到应答后继续完成后续处理。这是与前两种方式相比效率较低的一种模式,它是在异步通信的基础上实现的同步应用需求。这时请求/应答程序间要通过上述的动态队列、MsgId、CorrelId等手段完成消息的识别。这时还需要进行数据完整性的一些考虑,见下面的分析。应用的交易一致性控制MQ事务支持特性和传统的交易处理系统一样,MQ把应用程序分成若干工作单元(UOW),每个工作单元内部对数据做的更新通常是逻辑相关的,必须同时成功或回滚以保持数据完整性。为此,MQ提供了专门的API:MQBEGIN、MQCMIT和MQBACK,分别表示工作单元的开始、提交和回滚。MQ不但可以提供队列数据操作上的一致性,而且通过全局事务协调器(RRS)的协调下,MQ可以实现全局的数据一致性,例如一个程序不但处理了MQ消息,而且同时处理了DB2数据库数据、CICS的VSAM文件,这些操作可以通过统一的一个确认或回滚得到一致。要注意在CICS中的MQ程序,工作单元的控制将使用CICS的EXECCICSSYNCPOINT或SYNCPOINTROLLBACK,而不是MQI的命令。程序通过每个MQGET和MQPUT操作数据时,可以选择这次操作是放在UOW之内还是UOW之外,通过对读、写时的选项参数进行设置。如果某个操作放在UOW之外,它的操作将不能回滚。对于在工作单元之内的MQPUT操作,由于交易隔离机制,在COMMIT之前,其他程序是看不到这条消息的,这点在编程中需要注意。有害消息的处理由于MQ消息处理有事务特性,如果队列里某条消息数据结构存在问题,程序处理它时会发生失败,这条消息会被自动回滚到队列中,下次当它再被读出时,又可能发生失败,这种情况如果没有被意识到,可能会引发严重的错误循环。为防止这种情况的发生,MQ在消息头MQMD里设计了BackoutCount字段,如果某个消息是在同步点控制之下读取的,并且由于某种原因消息被回滚,消息描述符中的BackoutCount字段的值将被加1,良好的程序设计需要判断该数值,如果它大于某个阈值,则需要使用其它手段来处理该消息,比如不再对数据进行分析直接放到某个问题队列里去。在处理该消息的应用中,可以将其与设定的阈值做比较,这时,阈值会被写死在程序中,为了提高其灵活性,还可以使用队列的BOTHRESH和BOQNAME属性。这样,在例外处理中,利用MQINQ查询得到阈值BOTHRESH的大小,如果超出,可以将消息转发到BOQNAME指定的队列中,继而对该队列进行相应的处理。这种方法大大增强了应用程序的灵活性。异步通信下保持数据一致性的设计在使用MQ进行同步通讯的程序设计时,会碰到原来可能会做单一UOW的应用,在MQ的
本文标题:MQ 企业级方案设计,第 3 部分:企业级应用设计构架
链接地址:https://www.777doc.com/doc-6108660 .html