《MQ配置和编程最佳实践》由会员分享,可在线阅读,更多相关《MQ配置和编程最佳实践(7页珍藏版)》请在金锄头文库上搜索。
1、MQ 配置和编程最佳实践配置和编程最佳实践对于 MQ 的使用,主要会涉及到 MQ 系统本身的配置和 MQ 应用程序的开发两 方面的工作。为了帮助大家更好地使用 MQ,本文将就 MQ 配置和编程中的一 些注意事项和技巧与大家探讨,并希望与大家分享这方面的一些最佳实践(Best Practice)。第一部分:有关第一部分:有关 MQ 对对象配置的最佳象配置的最佳实实践践对于 MQ 系统配置,我们要规划 MQ 通讯网络,确定系统的拓扑结构,确定各 种对象的属性和命名规则并创建所需的各种对象等,首先,我们谈一谈在系统 建设之初,如何设计和定义 MQ 的各种对象。1、有关有关队队列管理器:列管理器:创建
2、队列管理器时,应考虑的因素主要有:1) 队列管理器的日志类型以及日志文件的大小和个数,要根据用户数据量的 大小、各个队列上的消息总容量,来计算日志的总容量,以免在系统运行过程 中出现日志写满的情况; 2) 应该为队列管理器指定和建立死信队列; 3) 对最多打开句柄数 MAXHANDS(缺省为 256,如果您需要多于 256 个应 用程序同时连接队列管理器,应增大该值),最大消息长度 MAXMSGL,最多 的未提交的消息个数 MAXUMSGS 属性(缺省为 10000,如果您使用了消息分 段或分组,某个大消息的分段个数超过了 10000,应增大该值)的考虑; 4) 创建完队列管理器之后,应修改队
3、列管理器的配置文件,考虑有关 TCP 和 通道有关的参数的配置,举例如下:TCP:KeepAlive=YesChannels:AdoptNewMCA=ALLPipeLineLength=2MaxActiveChannels=2002、有关有关队队列:列:对于队列的属性,应该考虑的因素主要有:1) 永久性和非永久性设置:尤其要注意的是 DEFPSIST 属性的缺省值为 No,若要保证消息的安全可靠,必须将其设置为 Yes;2) 对于本地队列和传输队列,要考虑队列的最大深度 MAXDEPTH(缺省为 5000,应根据实际情况计算该值),队列中每个消息的最大字节数 MAXMSGL 的配置。3、有关通
4、道:、有关通道:对于通道的属性,应该考虑的因素主要有:1) 确定通道的运行方式采用长连接的方式还是触发的方式,通常,对于需要 频繁启动的通道,不适宜采用触发的方式。若采用触发方式启动通道,触发类 型应为 FIRST; 2) 对于发送类型的通道,要考虑通道的断开间隔(DISCINT)、短重试次数 (SHORTRTY)、短重试间隔(SHORTTMR)、长重试次数(LONGRTY)、 长重试间隔(LONGTMR)、批处理大小(BATCHSZ)的配置。第二部分:有关第二部分:有关 MQ 程序开程序开发发的最佳的最佳实实践践通常大家在使用 MQ 时,一般在系统设计之初只考虑 MQ 的系统配置,而很少 提
5、前考虑应用程序编写的指导原则,往往是边写边想,边想边写,边写边改, 使得开发效率和质量都比较低,为了使大家更快、更好地开发出 MQ 应用程序, 在该部分我们给出与 MQ 程序开发相关的一些最佳实践,供大家参考。这里我 们无法做到面面俱到,并且由于每个用户的具体需求不同,每条原则都不能一 概而论,但是从普遍意义上可以作为您的参考。 为了更好地掌握和了解 MQ 编程的技巧,我们首先要熟悉 MQ 的消息通讯模式, 这将帮助你更好地理解 MQ 编程的最佳实践。通常,MQ 有两种通讯模式,即 数据报(Datagram) 方式和请求/应答(Request/Reply) 方式:其中,Datagram 方式通
6、常又被称为“Send And Forget“(发送/忽略),是最简单的通讯模式,应 用程序只需在创建完消息之后,利用 MQ 的 API 将消息发送到队列中,它充分 利用了 MQ 确保消息传输,并且传一次且仅传一次(once and once only)的优势, 发送端应用程序无需关心消息何时被处理。 Request/Reply(请求/应答)方式相对复杂一些,在消息发出之后,你需要等 待对方的处理结果,在这种情况下,你通常需要考虑其他一些问题,如: 等待应答的时间是多少? 如果没有收到应答,是否再次发出请求? 应答发出之前是否会有数据库操作或其他交易被执行? 本次请求/应答过程的会话(sessi
7、on)信息是否需要被保留? 通常,我们要根据用户的需求来决定采用何种通讯模式,不同的通讯模式之下 对应用程序的考虑将会有所不同,使用的 MQ API 的参数和选项也将不同。 为了使你的 MQ 应用能够更加健壮,并且具有更强的可维护性,我们要学会灵 活高效地使用 MQ 的一些特性以及相关的 API 选项,从而提到应用程序的质量、 灵活性、可靠性和性能。这里,我们将给出一些较典型的建议。 1. 在每一个在每一个 MQ API 调用之后,必须检查完成码调用之后,必须检查完成码(completion code)和原因码和原因码 (reason code),对于非零的返回码,必须进行相应的处理,必要时,
8、最好将返,对于非零的返回码,必须进行相应的处理,必要时,最好将返 回码记录错误日志,从而在应用程序出现运行故障时便于检查和处理。回码记录错误日志,从而在应用程序出现运行故障时便于检查和处理。在 MQ 中,所有的 API 调用都会得到其完成码和原因码,完成码有 MQCC_OK、MQCC_WARNING、MQCC_FAILED 等,MQCC_OK 表示调用 成功,当得到 MQCC_WARNING、MQCC_FAILED 返回码时,表示 API 执行 不完全成功,你需要进一步检查原因码,通过不同的原因码分析失败原因。如: 原因码 2033 代表队列已空,没有消息可取;2080 代表消息的实际长度超过
9、了 你在程序代码中设置的缓冲区长度等等。 2. 对对 MQCONN, MQOPEN,MQCLOSE, MQDISC 的使用的使用 由于 MQCONN, MQOPEN,MQCLOSE, MQDISC 相对于 MQGET 和 MQPUT 来说是比较消耗资源的几个函数,在一个应用中,即使你需要对某个 队列进行多次读写操作,也不要对每一次读写都调用一次 MQCONN, MQOPEN,MQCLOSE, MQDISC 函数,正确的做法应该是,调用一次 MQCONN, MQOPEN 就可以对队列进行多次读写操作,另外,一定别忘记对 称地使用 MQCLOSE, MQDISC 函数将相关资源释放掉。 3. 读取
10、消息时,等待时间间隔的设置读取消息时,等待时间间隔的设置 对队列的读取操作,可以有两种方式,即轮巡方式和触发方式(利用 MQ 的触 发功能动态调起应用程序)。在采用轮巡方式读取队列时,在 MQGET 时,我 们需要设置消息读取选项 MQGMO_WAIT,同时指定等待时间间隔。不少用户 将时间间隔设定为 MQWI_UNLIMITED 以实现轮巡的目的,这样做的弊端在于 在没有消息到达时应用程序陷入无限的等待,无法接收来自外部系统的相关信 号,MQCLOSE,MQDISC 调用也无法被执行,因此,我们建议避免采用这种方 式,推荐的做法是设置特定的等待时间间隔,然后再循环发出 MQGET 调用。 4
11、. 如果在同步点控制之下使用如果在同步点控制之下使用 MQGET,在所有,在所有 MQGET 调用之后,必须检查调用之后,必须检查 消息的回滚次数消息的回滚次数(Backout Count)。 如果某个消息是在同步点控制之下读取的,并且由于某种原因消息被回滚,消 息描述符中(Message Descriptor)的 BackoutCount 字段的值将被加 1,你需要 判断该数值,如果它大于某个阈值,你需要使用其它手段来处理该消息。否则, 在某些情况下会导致读取消息-消息被回滚-再读取消息-消息再被回滚的死循环。例如:你使用了触发机制设定当队列中消息到达时,触发某个应用程序,该应 用程序在 M
12、Q XA Resource Manager 的控制之下,读取消息,并且利用其数据 对数据库进行更新,假设数据库出现问题,无法成功进行数据库操作,消息将 被回滚;这时,又满足了触发条件,又会触发起该应用程序,周而复始,陷入 死循环。在这种情况下,你必须在程序中加入对 BackoutCount 的判断。 5. 当处理当处理 backout 消息时,可以使用队列的消息时,可以使用队列的 BOTHRESH 和和 BOQNAME 属属 性。性。 如 4 中所言,如果某个消息是在同步点控制之下读取的,并且由于某种原因消 息被回滚,消息描述符中的 BackoutCount 字段的值将被加 1,你需要判断该数
13、 值,如果它大于某个阈值,你需要使用其它手段来处理该消息。在处理该消息 的应用中,你可以将其与设定的阈值做比较,这时,阈值会被写死在程序中, 为了提高其灵活性,你可以使用队列的 BOTHRESH 和 BOQNAME 属性。这 样,你可以在例外处理中,利用 MQINQ 查询得到阈值的大小,如果超出,可 以将消息转发到 BOQNAME 指定的队列中,继而对该队列进行相应的处理。 这种方法大大增强了应用程序的灵活性。6. 在使用在使用 MQOPEN, MQPUT 和和 MQGET 调用时,要使用调用时,要使用 FAIL_IF_ QUIESCING 的选项。的选项。 MQ 系统本身和使用它提供的服务的
14、用户应用程序之间是互相独立的,必要时, 我们可能要停止 MQ 系统,这时,我们不但希望新的应用不能连接,并且希望 所有已连接的应用能够立即停止。为了使所有的应用程序能够快速得知 MQ 系 统正在停止的信号,在上述 MQ API 中,必须设置 FAIL_IF_ QUIESCING 的选 项。 如果不设置 FAIL_IF_ QUIESCING 的选项,当 MQ 系统停止时,所有应用将 继续运行,这样会影响 MQ 系统的停止,从而导致 MQ 停止需要很长时间,同 时可能导致我们必须手工杀掉那些没有设置该选项的应用程序。 7. 消息描述符的不同字段的使用方法消息描述符的不同字段的使用方法 在 MQ 的
15、消息描述符 MQMD 中包含了很多字段,这些字段大部分是一些保留 字段,例如:MsgID 表示消息的唯一标识,如果你不指定,MQ 系统会为你自 动产生一个,并保证其唯一性;PutAppType, PutAppName, PutDate, PutTime 是系统自动产生的,表示哪个应用何时将消息发送到队列中;再如:GroupId, MsgSeqNumber, Offset, MsgFlags 是与消息分段和消息分组相关的控制信息; 除了这些系统自动产生无法更改的字段和有特殊用途的字段之外,如果您想选 择某些字段为己所用,将其设定为自己应用程序中某个有意义的标识,你可以 使用 CorrelId 和
16、 Feedback 字段,但是,按照惯例,CorrelId 常常被用于在请 求/应答通讯模式中来表示请求消息和应答消息之间的关联;因此,我们可以灵 活使用 Feedback 字段,利用该字段来进行一些应用程序控制。当我们接收到 某个消息之后,我们可以检查 Feedback 字段,根据 Feedback 字段值进行相 应的处理。 8. 消息永久性属性的确定消息永久性属性的确定 永久性消息保证了消息在系统和网络等故障下的安全可靠,但是同时从性能角 度来讲会比非永久性消息要差,因此,要从不同的角度进行权衡和分析,然后 决定消息的永久性属性。当对性能要求非常高,可靠性要求相对不高时,可以 首先考虑采用非永久性消息,在消息决不允许有任何丢失,并且在丢失之后又 无法重新发送时,要使用永久性消息。 9. 当指定消息的永久性和非永久性属性时,最好利用应用程序显式地指定,不当指定消息的永久性和非永久性属性时,最好利用应用程序显式地指定,不 要使用要使用“defined as queue“的方法来指定。的方法来指定。 消息的永久性和非永久性是消息本身的属性,多数情况下,只有消息的原始发