将消息异步放在WebSphere MQ队列上

时间:2011-12-22 15:50:23

标签: java asynchronous ibm-mq put

我正在尝试将持久性消息放到WebSphere MQ队列中,但是这些需要是异步put。我似乎能够异步工作的唯一方法是,如果消息是非持久性的(我的意思是putSuccessCount等于放在MQAsyncStatus上的消息数量,所有其他时间它都是零)。下面的代码概述了我要做的事情:

import com.ibm.mq.MQAsyncStatus;
import com.ibm.mq.MQDestination;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.MQConstants;

public class MQPutTest extends TestCase{

    private static Logger log = Logger.getLogger(MQPutTest.class);

    public void testPut() throws Exception{

        Hashtable<String, Object> props = new Hashtable<String, Object>();
        props.put(MQConstants.CHANNEL_PROPERTY, "my_channel");
        props.put(MQConstants.PORT_PROPERTY, 1414);
        props.put(MQConstants.HOST_NAME_PROPERTY, "localhost");

        String qManager = "my_queue_manager"; 
        MQQueueManager qMgr = new MQQueueManager(qManager, props);

        int openOptions = MQConstants.MQOO_OUTPUT | MQConstants.MQOO_INPUT_AS_Q_DEF;

        MQDestination queue = qMgr.accessQueue("my_queue", openOptions);

        MQPutMessageOptions pmo = new MQPutMessageOptions();
        pmo.options = MQConstants.MQPMO_ASYNC_RESPONSE;

        MQMessage message = new MQMessage();
        message.format = MQConstants.MQFMT_STRING;
        message.writeString("test message");
        queue.put(message, pmo);

        queue.close();
        MQAsyncStatus asyncStatus = qMgr.getAsyncStatus();
        qMgr.disconnect();
    }
}

我将使用大量消息看到的性能提升归因于队列设置为非持久性而不是将消息设置为异步。我在MQ explorer bu的队列扩展属性中将默认的put响应类型设置为Asynchronous,这没有任何效果。

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

如果可以丢失一条或两条消息,您可以将消息添加到内部发送队列,例如

ExecutorService service = Executors.newSingleThreadedExecutor();

// build you message here

// add the message to be sent asynchronously.
service.execute(new Runnable() {
    public void run() {
         queue.put(message, pmo);
    }
});

进程终止时队列中的所有消息都将丢失。

答案 1 :(得分:0)

根据问题中的评论,WMQ没有“持久队列”的概念(因此我更改了帖子的标题)。持久性的队列属性不会改变 QMgr 处理队列或其中任何消息的方式。它所做的就是告诉程序如果程序员未能明确设置该值,则使用哪个持久性选项。任何给定消息是否持久取决于消息首次放入队列时MQMD指定的持久性。任何队列都可以包含任意组合的持久性和非持久性消息。

具体来说,他发布的代码片段并没有使用message.setPersistence()指定持久性,因此它将继承队列的默认值。这又取决于从queue属性继承的值。 在任何情况下,队列属性设置都不会覆盖应用的显式设置。

因此,您看到的性能差异确实最有可能反映队列的DEFPSIST属性的设置,但这并不意味着异步放置不起作用。请记住,异步put不会以任何方式减少将消息放入队列所需的时间。无论put是否同步,QMgr都有相同的代码路径来保留消息。不同之处在于您的应用不再等待QMgr完成其工作。当您要求更新MQAsyncStatus WMQ尚未编写任何消息时,完全有可能。如果它们都在一个单独的工作单元中,则更有可能,因为在COMMIT处理完成之前,WMQ不会返回所有消息的状态。除非您明确调用COMMIT,否则当您关闭队列时会发生这种情况。

您可以在qMgr.getAsyncStatus()COMMIT后的几秒钟内每秒重复CLOSE次呼叫来验证这一点。您应该看到第一个没有返回成功放置的消息,但最终您可以解释所有消息。

顺便提一下,消息是否持久的问题应该几乎总是在代码中处理。消息持久性通常作为在应用程序设计中捕获的业务需求派生。因此,项目经理和开发人员有责任确保满足要求。可靠地确保满足它的唯一方法是应用程序显式调用setPErsistence()。否则,应用程序将使用队列的DEFPSIST属性中的值隐式调用setPersistence()。那么为什么要在API中允许这种默认值呢?因为有一些合法的情况,持久性需要能够在运行时更改 。编写应用程序以有意识地采用默认值并在每个工作单元完成此操作后重新打开队列。在所有其他情况下,应在程序或托管对象中设置持久性。

最后,如果您在一个工作单元下放置10,000条消息,另一个原因是您可以获得响应,指出没有成功放置消息是缺少日志空间或未设置为可调整负载的可调参数。例如,如果将MAXUMSGS设置为小于10,000的值,则整个事务将回滚。另一方面,如果MAXUMSGS设置正确但主日志和辅助日志的大小和数量不足以保存事务中的数据量,则整个事务将再次回滚。您应该使用COMMIT间隔进行一些操作,因为最佳值取决于与队列和日志缓冲区大小相关的消息大小。一旦超过可以优化为单个写入操作的数据量,其他消息实际上会降低性能。当人们将10,000条消息放入一个单独的工作单元时,几乎不需要性能,而是因为这是它们适当的恢复单元,并且相应的性能损失是恢复要求的次要因素。