MQ配置和编程最佳实践

  • MQ配置和编程最佳实践
  • 第一部分:有关MQ对象配置的最佳实践

    对于MQ系统配置,我们要规划MQ通讯网络,确定系统的拓扑结构,确定各种对象的属性和命名规则并创建所需的各种对象等,首先,我们谈一谈在系统建设之初,如何设计和定义MQ的各种对象。

    1、有关队列管理器:

    创建队列管理器时,应考虑的因素主要有:

    1) 队列管理器的日志类型以及日志文件的大小和个数,要根据用户数据量的大小、各个队列上的消息总容量,来计算日志的总容量,以免在系统运行过程中出现日志写满的情况;

    2) 应该为队列管理器指定和建立死信队列;

    3)对最多打开句柄数MAXHANDS(缺省为256,如果您需要多于256个应用程序同时连接队列管理器,应增大该值),最大消息长度MAXMSGL,最多的未提交的消息个数MAXUMSGS属性(缺省为10000,如果您使用了消息分段或分组,某个大消息的分段个数超过了10000,应增大该值)的考虑;

    4) 创建完队列管理器之后,应修改队列管理器的配置文件,考虑有关TCP和通道有关的参数的配置,举例如下:

    
    
    TCP:
    
    KeepAlive=Yes
    
    Channels:
    
    AdoptNewMCA=ALL
    
    PipeLineLength=2
    
    MaxActiveChannels=200
    
    


    2、有关队列:

    对于队列的属性,应该考虑的因素主要有:

    1) 永久性和非永久性设置:尤其要注意的是DEFPSIST属性的缺省值为No,若要保证消息的安全可靠,必须将其设置为Yes;

    2) 对于本地队列和传输队列,要考虑队列的最大深度MAXDEPTH(缺省为5000,应根据实际情况计算该值),队列中每个消息的最大字节数MAXMSGL的配置。

    3、有关通道:

    对于通道的属性,应该考虑的因素主要有:

    1) 确定通道的运行方式采用长连接的方式还是触发的方式,通常,对于需要频繁启动的通道,不适宜采用触发的方式。若采用触发方式启动通道,触发类型应为FIRST;

    2) 对于发送类型的通道,要考虑通道的断开间隔(DISCINT)、短重试次数(SHORTRTY)、短重试间隔(SHORTTMR)、长重试次数(LONGRTY)、长重试间隔(LONGTMR)、批处理大小(BATCHSZ)的配置。

    第二部分:有关MQ程序开发的最佳实践

    通常大家在使用MQ时,一般在系统设计之初只考虑MQ的系统配置,而很少提前考虑应用程序编写的指导原则,往往是边写边想,边想边写,边写边改,使得开发效率和质量都比较低,为了使大家更快、更好地开发出MQ应用程序,在该部分我们给出与MQ程序开发相关的一些最佳实践,供大家参考。这里我们无法做到面面俱到,并且由于每个用户的具体需求不同,每条原则都不能一概而论,但是从普遍意义上可以作为您的参考。

    为了更好地掌握和了解MQ编程的技巧,我们首先要熟悉MQ的消息通讯模式,这将帮助你更好地理解MQ编程的最佳实践。通常,MQ有两种通讯模式,即数据报 (Datagram) 方式和请求/应答(Request/Reply) 方式:其中,Datagram方式通常又被称为"Send And Forget"(发送/忽略),是最简单的通讯模式,应用程序只需在创建完消息之后,利用MQ的API将消息发送到队列中,它充分利用了MQ确保消息传输,并且传一次且仅传一次(once and once only)的优势,发送端应用程序无需关心消息何时被处理。

    Request/Reply(请求/应答)方式相对复杂一些,在消息发出之后,你需要等待对方的处理结果,在这种情况下,你通常需要考虑其他一些问题,如:

    等待应答的时间是多少? 

    如果没有收到应答,是否再次发出请求? 

    应答发出之前是否会有数据库操作或其他交易被执行? 

    本次请求/应答过程的会话(session)信息是否需要被保留?

    通常,我们要根据用户的需求来决定采用何种通讯模式,不同的通讯模式之下对应用程序的考虑将会有所不同,使用的MQ API的参数和选项也将不同。

    为了使你的MQ应用能够更加健壮,并且具有更强的可维护性,我们要学会灵活高效地使用MQ的一些特性以及相关的API选项,从而提到应用程序的质量、灵活性、可靠性和性能。这里,我们将给出一些较典型的建议。

    1. 在每一个MQ API调用之后,必须检查完成码(completion code)和原因码(reason code),对于非零的返回码,必须进行相应的处理,必要时,最好将返回码记录错误日志,从而在应用程序出现运行故障时便于检查和处理。

    在MQ 中,所有的API调用都会得到其完成码和原因码,完成码有MQCC_OK、MQCC_WARNING、MQCC_FAILED等,MQCC_OK表示调用成功,当得到MQCC_WARNING、MQCC_FAILED返回码时,表示API执行不完全成功,你需要进一步检查原因码,通过不同的原因码分析失败原因。如:原因码2033代表队列已空,没有消息可取;2080代表消息的实际长度超过了你在程序代码中设置的缓冲区长度等等。

    2. 对MQCONN, MQOPEN,MQCLOSE, MQDISC的使用

    由于MQCONN, MQOPEN,MQCLOSE, MQDISC相对于MQGET和MQPUT来说是比较消耗资源的几个函数,在一个应用中,即使你需要对某个队列进行多次读写操作,也不要对每一次读写都调用一次MQCONN, MQOPEN,MQCLOSE, MQDISC函数,正确的做法应该是,调用一次MQCONN, MQOPEN就可以对队列进行多次读写操作,另外,一定别忘记对称地使用MQCLOSE, MQDISC函数将相关资源释放掉。

    3. 读取消息时,等待时间间隔的设置

    对队列的读取操作,可以有两种方式,即轮巡方式和触发方式(利用MQ的触发功能动态调起应用程序)。在采用轮巡方式读取队列时,在MQGET时,我们需要设置消息读取选项MQGMO_WAIT,同时指定等待时间间隔。不少用户将时间间隔设定为MQWI_UNLIMITED以实现轮巡的目的,这样做的弊端在于在没有消息到达时应用程序陷入无限的等待,无法接收来自外部系统的相关信号,MQCLOSE,MQDISC调用也无法被执行,因此,我们建议避免采用这种方式,推荐的做法是设置特定的等待时间间隔,然后再循环发出MQGET调用。

    4. 如果在同步点控制之下使用MQGET,在所有MQGET调用之后,必须检查消息的回滚次数(Backout Count)。

    如果某个消息是在同步点控制之下读取的,并且由于某种原因消息被回滚,消息描述符中(Message Descriptor)的BackoutCount字段的值将被加1,你需要判断该数值,如果它大于某个阈值,你需要使用其它手段来处理该消息。否则,在某些情况下会导致读取消息-消息被回滚-再读取消息-消息再被回滚的死循环。

    例如:你使用了触发机制设定当队列中消息到达时,触发某个应用程序,该应用程序在MQ XA Resource Manager的控制之下,读取消息,并且利用其数据对数据库进行更新,假设数据库出现问题,无法成功进行数据库操作,消息将被回滚;这时,又满足了触发条件,又会触发起该应用程序,周而复始,陷入死循环。在这种情况下,你必须在程序中加入对BackoutCount的判断。

    5. 当处理backout消息时,可以使用队列的BOTHRESH 和 BOQNAME属性。

    如4 中所言,如果某个消息是在同步点控制之下读取的,并且由于某种原因消息被回滚,消息描述符中的BackoutCount字段的值将被加1,你需要判断该数值,如果它大于某个阈值,你需要使用其它手段来处理该消息。在处理该消息的应用中,你可以将其与设定的阈值做比较,这时,阈值会被写死在程序中,为了提高其灵活性,你可以使用队列的BOTHRESH 和 BOQNAME属性。这样,你可以在例外处理中,利用MQINQ查询得到阈值的大小,如果超出,可以将消息转发到BOQNAME指定的队列中,继而对该队列进行相应的处理。这种方法大大增强了应用程序的灵活性。

    6. 在使用MQOPEN, MQPUT 和 MQGET调用时,要使用FAIL_IF_ QUIESCING的选项。

    MQ 系统本身和使用它提供的服务的用户应用程序之间是互相独立的,必要时,我们可能要停止MQ系统,这时,我们不但希望新的应用不能连接,并且希望所有已连接的应用能够立即停止。为了使所有的应用程序能够快速得知MQ系统正在停止的信号,在上述MQ API中,必须设置FAIL_IF_ QUIESCING的选项。

    如果不设置FAIL_IF_ QUIESCING的选项,当MQ系统停止时,所有应用将继续运行,这样会影响MQ系统的停止,从而导致MQ停止需要很长时间,同时可能导致我们必须手工杀掉那些没有设置该选项的应用程序。

    7. 消息描述符的不同字段的使用方法

    在MQ 的消息描述符MQMD中包含了很多字段,这些字段大部分是一些保留字段,例如:MsgID表示消息的唯一标识,如果你不指定,MQ系统会为你自动产生一个,并保证其唯一性;PutAppType, PutAppName, PutDate, PutTime是系统自动产生的,表示哪个应用何时将消息发送到队列中;再如:GroupId, MsgSeqNumber, Offset, MsgFlags是与消息分段和消息分组相关的控制信息;除了这些系统自动产生无法更改的字段和有特殊用途的字段之外,如果您想选择某些字段为己所用,将其设定为自己应用程序中某个有意义的标识,你可以使用CorrelId和Feedback字段,但是,按照惯例,CorrelId常常被用于在请求/应答通讯模式中来表示请求消息和应答消息之间的关联;因此,我们可以灵活使用Feedback字段,利用该字段来进行一些应用程序控制。当我们接收到某个消息之后,我们可以检查Feedback字段,根据Feedback字段值进行相应的处理。

    8. 消息永久性属性的确定

    永久性消息保证了消息在系统和网络等故障下的安全可靠,但是同时从性能角度来讲会比非永久性消息要差,因此,要从不同的角度进行权衡和分析,然后决定消息的永久性属性。当对性能要求非常高,可靠性要求相对不高时,

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值