MQ配置和编程最佳实践2

9. 当指定消息的永久性和非永久性属性时,最好利用应用程序显式地指定,不要使用”defined as queue”的方法来指定。

消息的永久性和非永久性是消息本身的属性,多数情况下,只有消息的原始发出者才了解丢失消息将产生的重大影响,因此,消息的原始发出者应在应用程序中显式地指定消息的永久性,如果将其定义为依赖于队列的该属性,就会比较被动,当队列的永久性属性(DEPSIST)被意外地设为NO时,就会有丢失的风险。

10. 应用程序可以将请求消息的永久性属性为No,即对于请求消息使用非永久性消息。

一般情况下,请求消息丢失对应用系统不会产生严重的影响,如果出现请求消息丢失的情况,我们可以重新发送,因此,不必将请求消息设置为永久性消息。把请求消息设置为非永久性消息的另外一个好处是,系统不需要对非永久性消息记录日志,从而减少I/O操作,提高系统的性能。

11. 在异种操作系统平台上使用MQ传输消息时,将消息格式设置为MQFMT_STRING。

MQ的一大优势之一,是对built-in(内置的)消息格式,可以实现不同操作系统平台间、不同系统字符集之间的数据转换,如开发平台ASCII码和主机EBCDIC码之间的转换。为了实现该数据转换,MQ必须获知本身和对方MQ系统的队列管理器的CCSID和Encoding以及消息的格式。一般而言,CCSID和Encoding会被自动设置和处理,不需要应用程序关心,但是,消息的格式必须由应用程序指定,对于MQ内置支持的消息格式,MQ可以自动转换,这些消息格式由MQFMT_*来指定。鉴于应用程序数据都可以用MQFMT_STRING来表示,并且MQFMT_STRING是MQ内置支持可以转换的格式之一,你可以使用它来表示你的消息格式,同时,对于数字型消息,你需要使用atoi, itoa等函数实现数字型和字符型之间的转换。

12. 对大消息的处理

MQ支持单条消息的最大长度为100M,队列管理器、队列、通道支持的最大消息的缺省值为4M,即使如此,我们却应该根据不同的网络类型和带宽,具体地确定不同情况下单条消息的合适大小。例如:如果在拨号网络或网络带宽较窄的情况下,我们将单条消息的大小设置得太大,就会影响传输效率,在这种情况下,一定要使用MQ的分段功能将消息进行分段处理,确保每一个物理消息的大小适当,MQ会自动维护整个逻辑消息的完整性,并且可以在接收端一次性将其取出。

13. 如何使用MQ的请求/应答通讯模式来处理同步的消息处理模式。

大家知道,MQ的异步处理模式是非常强健的,同时它也支持同步的消息处理,例如MQ的client-server通讯就是一种典型的同步工作模式,对于server-server通讯,我们也可以实现同步工作模式,这里就涉及到如何巧妙地使用MQ提供的消息生命周期的功能。这时,对于请求消息和应答消息我们最好为其设置生命周期。

典型的应用案例如下:假设系统A向系统B发出请求,调用B上的某个交易,这里,我们首先要设置请求消息的生命周期,并且在消息到期时将消息丢弃,如果在消息发出之前消息过期,它就会在进入通道之前,被MQ系统丢弃;如果当消息到达目的地之后,在被对方应用程序取走之前消息过期,它也将被MQ系统丢弃。系统B上的交易便不会被调起执行。对于应答消息,我们也设置它的生命周期,与请求消息不同的是,我们设置在消息到期时将其转发到另外一个特定的队列中,这时,如果系统B上的交易执行完之后,会产生应答消息,如果由于通讯等原因,该应答消息在到达系统A时应用程序设置的Timeout时间已经超出,应用程序必然认为系统B上的交易没有被执行,也不会处理该应答消息,这样,应答消息便会过期,当它过期时,根据我们的设置,它会自动被MQ系统转发到特定队列中,我们另设专门的应用程序对此进行冲正处理。

14. 对消息类型的设置。

通常情况下,我们不要求用户一定去设置消息的类型,设置消息类型的方法是在消息描述符MQMD的MsgType字段,消息类型有datagram, request, reply, report等若干种。但是为了更好地对消息进行管理,我们必要时要设定消息类型,从而对不同的消息进行处理。例如,当reply消息和report消息都被发送到同一个应答队列时,我们可以根据消息类型的不同对其进行不同的处理。

15. 对消息转换的设置。

通常,当需要进行消息转换时,我们有两种方法来进行设置:一种方法是在调用MQGET时设置MQGMO_CONVERT的读取消息选项;第二种方法是将发送端通道的convert属性设置为yes。对比二者,我们推荐使用第一种方法,它的优势在于:它避免了消息通道代理程序对消息的转换,从而提高了通道的性能;其次,当一对多传输时,避免了对不同的目标系统使用不同的转换算法,而统一放在接收端进行。

当我们不需要进行格式转换时,使用在MQMD中将消息格式Format字段设置为MQFMT_NONE的方法来表示,MQFMT_NONE表示忽视任何格式转换。

16. 应用程序最好不要在MQGET和MQPUT调用时使用过大的消息缓冲区,从而减少队列管理器对内存的需求。

当应用程序发出MQGET和MQPUT调用时要设定用于装载消息的数据缓冲区大小,MQ系统将据此来分配内存,如果使用过大的消息缓冲区,队列管理器就会分配较大的内存来处理这些调用,从而造成内存浪费,影响性能。如果我们在接收端不知道消息的大小,为了不至于设置一个很大的缓冲区去接收数据,我们可以在真正的MQGET之前先使用Browse方式来浏览一下队列中的消息,根据浏览到的消息的MQMD的OriginalLength字段的数值来确定消息缓冲区的大小,然后再使用MQGET真正的将消息读取出来。

17. 在设定消息的优先级时,不要直接在消息描述符中设置,最好设置队列的优先级,然后使用”defined as queue”来设置消息的优先级。

优先级是消息的属性之一,当应用发生变化时,我们可能需要改变消息的优先级,如果我们将其写死在程序中,就会影响程序的灵活性。如果借助于队列的优先级来设置消息的优先级,系统管理员可以根据需要,通过改变队列的DEFPRTY的属性来更改其优先级,而无需改变应用程序代码,这样可以大大提高系统管理和网络管理的灵活性。

18. 请求型应用在打开请求队列时,最好不要使用MQOO_OUTPUT选项。

请求队列可以是本地队列,也可能是远程队列,本地队列是既可读又可写的,而远程队列是只可写(MQOO_OUTPUT)的。通常,请求型应用一般都是需要将请求发送到请求队列中,对队列的操作都是MQPUT,这时,队列的类型不会有影响,因为本地队列和远程队列都是可写的。但是,如果某个请求型应用需要读取请求队列,则要求请求队列一定是本地队列,这时就不能使用MQOO_OUTPUT选项。因此建议在打开请求队列时,最好不使用MQOO_OUTPUT选项,可以使得不同的应用之间很容易移植,而且当队列属性改变时,不会对应用程序造成影响。

19. 与数据库交互时,MQPUT 和 MQGET必须使用同步点控制,即使用MQ的两阶段提交功能,来保证数据的一致性和完整性。

为了保证数据库操作和MQ操作同时成功或同时回滚,需要在做MQPUT 和 MQGET调用时,使用MQPMO_SYNCPOINT和MQGMO_SYNCPOINT选项将队列操作和数据库操作作为一个事物来完成。这样,如果数据库出现问题导致操作失败时,消息可以被正确回滚;否则,会导致数据不一致的现象。

20. 与数据库操作相关的队列消息的属性最好设为永久性消息,即消息的persistence属性应设为yes,并且永不过期。

由于与数据库操作相关的消息的重要性很强,它必须被设置为永久性消息,被MQ系统记录日志,从而在队列管理器重新启动或机器重启时不会丢失。另外,在”Send and Forget”通讯模式之下,由于这是典型的异步通讯模式,消息何时被处理是不确定的,为了防止消息超时,我们应将其生命周期设置为永不过期。

21. 对消息做了修改或者转发的应用,最好传递原始消息的identity context(身份鉴别上下文)信息。

每个MQ的消息都有其特定的鉴别上下文,通过消息描述符(MQMD)的相关字段来表示,它代表了消息是由谁产生的,当消息在MQ网络中传输时,该上下文应该必须被保留。当消息被另外的用户修改或者转发时,需要修改其上下文,将其原始的上下文重新赋进去。这主要是处于安全的考虑,通过上下文,可以获得消息产生者的信息。

22. 保持永久性动态队列名称的唯一性,确保同一个应用多次调用/运行产生的动态队列的名字唯一性。

当应用程序需要动态产生应答队列时,它可以产生临时性动态队列和永久性动态队列,某些情况下,将利用永久性动态队列保留一些可恢复的消息,这意味着该永久性动态队列可以重新被打开,因此要保证它们名称的唯一性。

23. 在使用临时性动态队列来处理应答时,处理请求消息的应用要保证不要将应答消息设置为永久性消息。

临时性动态队列不能存储永久性消息,鉴于此,对请求做出响应的应用程序必须知道接收应答的队列是临时性动态队列还是永久动态队列,请求端应用和响应端应用必须对响应消息的永久性进行协调,以保证只有非永久性消息会被放置到临时动态队列中。

结论:为了更好地使用MQ,我们必须遵循一定的标准和指导原则,使得我们开发出更加可靠、高效的应用程序,当然,这是从普遍意义上而言,在实际应用中需要您灵活掌握,因地制宜地选用更加适合您的配置和编程模式。

 

以下文章点击率最高

Loading…

     

如果这文章对你有帮助,请扫左上角微信支付-支付宝,给于打赏,以助博客运营

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注