Java 在WebLogic中配置JMS消息大小:WebLogic.socket.MaxMessageSizeExceedeException

Java 在WebLogic中配置JMS消息大小:WebLogic.socket.MaxMessageSizeExceedeException,java,jms,weblogic,Java,Jms,Weblogic,我目前有两个客户机(生产者/消费者),我正试图通过JMS发送一个大文件。我正在成功地生成文件并将其发送到JMS服务器,没有任何问题。问题是当我尝试使用该消息时,出现以下异常: Aug 24, 2012 11:25:37 AM client.Client$1 onException SEVERE: Connection to the Server has been lost, will retry in 30 seconds. weblogic.jms.common.LostServerExcep

我目前有两个客户机(生产者/消费者),我正试图通过JMS发送一个大文件。我正在成功地生成文件并将其发送到JMS服务器,没有任何问题。问题是当我尝试使用该消息时,出现以下异常:

Aug 24, 2012 11:25:37 AM client.Client$1 onException
SEVERE: Connection to the Server has been lost, will retry in 30 seconds. weblogic.jms.common.LostServerException: java.lang.Exception: weblogic.rjvm.PeerGoneException: ; nested exception is: 
    weblogic.socket.MaxMessageSizeExceededException: Incoming message of size: '10000080' bytes exceeds the configured maximum of: '10000000' bytes for protocol: 't3'
<Aug 24, 2012 11:25:37 AM CDT> <Error> <Socket> <BEA-000403> <IOException occurred on socket: Socket[addr=127.0.0.1/127.0.0.1,port=7001,localport=51764]
 weblogic.socket.MaxMessageSizeExceededException: Incoming message of size: '10000080' bytes exceeds the configured maximum of: '10000000' bytes for protocol: 't3'.
weblogic.socket.MaxMessageSizeExceededException: Incoming message of size: '10000080' bytes exceeds the configured maximum of: '10000000' bytes for protocol: 't3'
    at weblogic.socket.BaseAbstractMuxableSocket.incrementBufferOffset(BaseAbstractMuxableSocket.java:174)
    at weblogic.rjvm.t3.MuxableSocketT3.incrementBufferOffset(MuxableSocketT3.java:351)
    at weblogic.socket.SocketMuxer.readFromSocket(SocketMuxer.java:983)
    at weblogic.socket.SocketMuxer.readReadySocketOnce(SocketMuxer.java:922)
下面是MessageListener:

public class ConsumerListener implements MessageListener {
    private Logger log;
    private File destination;
    private Execute instructions;

    public ConsumerListener(Execute instructions, File destination) {
        this.instructions = instructions;
        this.destination = destination;
        log = new MyLogger().getLogger("BPEL Client");
    }

    @Override
    public void onMessage(Message arg0) {

        try {
            if (arg0.getJMSRedelivered()) {
                log.severe("A re-delivered message has been received, and it has been ignored!"
                        + arg0.toString());
            } else {
                try {
                    if (arg0 instanceof TextMessage) {
                        consumeMessage((TextMessage) arg0);

                    } else if (arg0 instanceof BytesMessage) {
                        consumeMessage((BytesMessage) arg0);
                    } else {
                        log.warning("Currently, only TextMessages and BytesMessages are supported!");
                    }
                } catch (JMSException e) {
                    log.severe(e.toString());
                } catch (IOException e) {
                    log.severe(e.toString());
                } catch (Throwable t) {
                    log.severe(t.toString());
                }
            }
        } catch (JMSException e) {
            log.severe(e.toString());
        }
    }

    /**
     * Unwraps the JMS message received and creates a file and a control file if
     * there are instructions present.
     *
     * @param textMessage
     *            JMS message received to be consumed.
     * @throws JMSException
     * @throws IOException
     */
    protected void consumeMessage(TextMessage textMessage) throws JMSException,
            IOException {
        // ***All properties should be lowercase. for example fileName
        // should be
        // filename.***
        String fileName = textMessage.getStringProperty("filename");
        if (fileName == null || fileName.isEmpty()) {
            fileName = textMessage.getStringProperty("fileName");
        }
        if (fileName != null && !fileName.isEmpty()) {
            // Check if the
            // file name is equal to the shutdown file. If it
            // is, shutdown the consumer. This is probably not a good way to
            // do this, as the program can no longer be shutdown locally!

            // We have a file in the queue, need to create the file.
            createFile(destination.getAbsolutePath() + "\\" + fileName,
                    textMessage.getText());
            log.info("Done creating the file");
            String inst = textMessage.getStringProperty("instructions");
            // If there are instructions included, then create the
            // instruction file, and route the message based on this file.
            if (inst != null && !inst.isEmpty()) {
                // We need to rout the file.
                log.info("Instructions found, executing instructions");
                String[] tokens = fileName.split("\\.");
                String instFileName = "default.ctl";
                if (tokens.length == 2) {
                    instFileName = tokens[0] + ".ctl";
                }
                File controlFile = createFile(destination.getAbsolutePath()
                        + "\\" + instFileName, inst);
                Control control = new Control(controlFile);
                instructions.execute(control);
                log.info("Done executing instructions");
            } else {
                log.info("No instructions were found");
            }
            log.info("Done consuming message: " + textMessage.getJMSMessageID());
        }

    }

    /**
     * Unwraps the JMS message received and creates a file and a control file if
     * there are instructions present.
     *
     * @param bytesMessage
     *            The bytes payload of the message.
     * @throws JMSException
     * @throws IOException
     */
    protected void consumeMessage(BytesMessage bytesMessage)
            throws JMSException, IOException {
        // ***All properties should be lowercase. for example fileName
        // should be
        // filename.***
        log.info("CONSUME - 1");
        String fileName = bytesMessage.getStringProperty("filename");
        if (fileName == null || fileName.isEmpty()) {
            fileName = bytesMessage.getStringProperty("fileName");
        }
        if (fileName != null && !fileName.isEmpty()) {
            // Check if the
            // file name is equal to the shutdown file. If it
            // is, shutdown the consumer. This is probably not a good way to
            // do this, as the program can no longer be shutdown locally!

            // We have a file in the queue, need to create the file.
            byte[] payload = new byte[(int) bytesMessage.getBodyLength()];
            bytesMessage.readBytes(payload);
            createFile(destination.getAbsolutePath() + "\\" + fileName, payload);
            log.info("Done creating the file");
            String inst = bytesMessage.getStringProperty("instructions");
            // If there are instructions included, then create the
            // instruction file, and route the message based on this file.
            if (inst != null && !inst.isEmpty()) {
                // We need to rout the file.
                log.info("Instructions found, executing instructions");
                String[] tokens = fileName.split("\\.");
                String instFileName = "default.ctl";
                if (tokens.length == 2) {
                    instFileName = tokens[0] + ".ctl";
                }
                File controlFile = createFile(destination.getAbsolutePath()
                        + "\\" + instFileName, inst);
                Control control = new Control(controlFile);
                instructions.execute(control);
                log.info("Done executing instructions");
            } else {
                log.info("No instructions were found");
            }
            log.info("Done consuming message: "
                    + bytesMessage.getJMSMessageID());
        }

    }

    /**
     * Creates a file with the given filename (this should be an absolute path),
     * and the text that is to be contained within the file.
     *
     * @param fileName
     *            The filename including the absolute path of the file.
     * @param fileText
     *            The text to be contained within the file.
     * @return The newly created file.
     * @throws IOException
     */
    protected File createFile(String fileName, String fileText)
            throws IOException {
        File toCreate = new File(fileName);
        FileUtils.writeStringToFile(toCreate, fileText);
        return toCreate;
    }

    /**
     * Creates a file with the given filename (this should be an absolute path),
     * and the text that is to be contained within the file.
     *
     * @param fileName
     *            The filename including the absolute path of the f ile.
     * @param fileBytes
     *            The bytes to be contained within the file.
     * @return The newly created file.
     * @throws IOException
     */
    protected File createFile(String fileName, byte[] fileBytes)
            throws IOException {
        File toCreate = new File(fileName);
        FileUtils.writeByteArrayToFile(toCreate, fileBytes);
        return toCreate;
    }
}

您还必须增加WLS控制台中所有托管服务器的最大消息大小,如屏幕截图所示

然后执行重新启动,问题将得到解决

此外,还有第二种替代方案。根据:

调整消息最大限制

如果推送到使用者的消息的聚合大小大于当前协议的最大消息大小(默认大小为10 MB,并使用控制台在每个WebLogic服务器实例上配置,使用Dweblogic.MaxMessageSize命令行属性在每个客户端上配置),则消息传递失败

设置客户端上的最大邮件大小

在发送和接收大型消息时,除了WebLogic服务器实例之外,您可能还需要配置WebLogic客户端。要设置客户端上的最大消息大小,请使用以下命令行属性:

-Dweblogic.MaxMessageSize

注意:此设置适用于交付给客户端的所有WebLogic服务器网络数据包,而不仅仅是JMS相关数据包

编辑:

此问题可以通过以下一个或多个操作来解决

  • 配置系统属性-Dweblogic.MaxMessageSize
  • 使用WLS控制台增加管理员和所有托管服务器的最大消息大小。WLS控制台中的步骤是:服务器/协议/常规
  • 从WLS控制台增加最大消息大小。WLS控制台中的步骤是:队列/配置/阈值和配额/最大消息大小
应用weblogic.MaxMessageSize属性的过程

保留setDomainEnv文件的备份。停止所有服务器。在每个setDomainEnv文件中添加-Dweblogic.MaxMessageSize=yourValue,更具体地说,在EXTRA_JAVA_属性行中添加。之后,首先启动管理员,当管理员处于运行状态时,然后启动托管服务器


我希望这会有所帮助。

在我的例子中,设置-Dweblogic.MaxMessageSize解决了这个问题。我的问题是消息大小的最大限制是什么?我们就是不能继续增加工资 解决此问题的邮件大小。此外,是否有任何方法可以优化此值
对于某些其他值?

感谢您的回复,尽管我已经尝试了这两种方法,但问题仍然存在。我不明白的是,为什么我可以生成一个大的JMS消息并将其放到队列中,但我不能使用完全相同的JMS消息?我已经更新了帖子。您是否尝试过所有3种可用的解决方案,但都没有解决您的问题?您是否在管理服务器和所有托管服务器中从WLS控制台配置了最大邮件大小?ThanksI已经尝试了所有3个选项,我不确定是否正确的唯一选项是系统属性。我用设置属性的图像编辑了我的问题。这是正确的地方吗?在进行更改后,我已尝试重新启动服务器,但仍然收到相同的错误。看起来还可以。您能告诉我WLS版本吗?WebLogic服务器版本:10.3.5.0您可以尝试更改群集中的广播类型。如果已设置为单播,请忽略此项。我已经解决了问题,我没有在客户端应用程序上设置-Dweblogic.MaxMessageSize,它现在工作正常。这将是您必须通过查找您正在发送的最大消息来发现自己的事情。如何查找最大的t3消息?我看不到在weblogic中记录t3消息的任何机制。您可以使用管理控制台监控队列,也可以使用Enterprise Manager进行更图形化的布局,但EM主要用于实时查看流量。另一个选项只是将该值设置为可能的最大值(在那里配置MaxMessageSize时,可以使用管理控制台找到该值)。如果您的最大消息超过该大小,那么weblogic将无法支持它。在我的例子中,它实际上是t3消息,而不是JMS消息。我检查了weblogic控制台,找不到任何有助于记录或监视它的标志或配置。当然,通过增加它的工作大小。但这更多的是一个打了官司的案件。我想知道它是如何随着我的远程数据量的增加而增长的。任何指向记录或监视t3消息的机制的指针都将非常有用。我在官方weblogic论坛上也问了同样的问题,但还没有得到任何答案。
public class ConsumerListener implements MessageListener {
    private Logger log;
    private File destination;
    private Execute instructions;

    public ConsumerListener(Execute instructions, File destination) {
        this.instructions = instructions;
        this.destination = destination;
        log = new MyLogger().getLogger("BPEL Client");
    }

    @Override
    public void onMessage(Message arg0) {

        try {
            if (arg0.getJMSRedelivered()) {
                log.severe("A re-delivered message has been received, and it has been ignored!"
                        + arg0.toString());
            } else {
                try {
                    if (arg0 instanceof TextMessage) {
                        consumeMessage((TextMessage) arg0);

                    } else if (arg0 instanceof BytesMessage) {
                        consumeMessage((BytesMessage) arg0);
                    } else {
                        log.warning("Currently, only TextMessages and BytesMessages are supported!");
                    }
                } catch (JMSException e) {
                    log.severe(e.toString());
                } catch (IOException e) {
                    log.severe(e.toString());
                } catch (Throwable t) {
                    log.severe(t.toString());
                }
            }
        } catch (JMSException e) {
            log.severe(e.toString());
        }
    }

    /**
     * Unwraps the JMS message received and creates a file and a control file if
     * there are instructions present.
     *
     * @param textMessage
     *            JMS message received to be consumed.
     * @throws JMSException
     * @throws IOException
     */
    protected void consumeMessage(TextMessage textMessage) throws JMSException,
            IOException {
        // ***All properties should be lowercase. for example fileName
        // should be
        // filename.***
        String fileName = textMessage.getStringProperty("filename");
        if (fileName == null || fileName.isEmpty()) {
            fileName = textMessage.getStringProperty("fileName");
        }
        if (fileName != null && !fileName.isEmpty()) {
            // Check if the
            // file name is equal to the shutdown file. If it
            // is, shutdown the consumer. This is probably not a good way to
            // do this, as the program can no longer be shutdown locally!

            // We have a file in the queue, need to create the file.
            createFile(destination.getAbsolutePath() + "\\" + fileName,
                    textMessage.getText());
            log.info("Done creating the file");
            String inst = textMessage.getStringProperty("instructions");
            // If there are instructions included, then create the
            // instruction file, and route the message based on this file.
            if (inst != null && !inst.isEmpty()) {
                // We need to rout the file.
                log.info("Instructions found, executing instructions");
                String[] tokens = fileName.split("\\.");
                String instFileName = "default.ctl";
                if (tokens.length == 2) {
                    instFileName = tokens[0] + ".ctl";
                }
                File controlFile = createFile(destination.getAbsolutePath()
                        + "\\" + instFileName, inst);
                Control control = new Control(controlFile);
                instructions.execute(control);
                log.info("Done executing instructions");
            } else {
                log.info("No instructions were found");
            }
            log.info("Done consuming message: " + textMessage.getJMSMessageID());
        }

    }

    /**
     * Unwraps the JMS message received and creates a file and a control file if
     * there are instructions present.
     *
     * @param bytesMessage
     *            The bytes payload of the message.
     * @throws JMSException
     * @throws IOException
     */
    protected void consumeMessage(BytesMessage bytesMessage)
            throws JMSException, IOException {
        // ***All properties should be lowercase. for example fileName
        // should be
        // filename.***
        log.info("CONSUME - 1");
        String fileName = bytesMessage.getStringProperty("filename");
        if (fileName == null || fileName.isEmpty()) {
            fileName = bytesMessage.getStringProperty("fileName");
        }
        if (fileName != null && !fileName.isEmpty()) {
            // Check if the
            // file name is equal to the shutdown file. If it
            // is, shutdown the consumer. This is probably not a good way to
            // do this, as the program can no longer be shutdown locally!

            // We have a file in the queue, need to create the file.
            byte[] payload = new byte[(int) bytesMessage.getBodyLength()];
            bytesMessage.readBytes(payload);
            createFile(destination.getAbsolutePath() + "\\" + fileName, payload);
            log.info("Done creating the file");
            String inst = bytesMessage.getStringProperty("instructions");
            // If there are instructions included, then create the
            // instruction file, and route the message based on this file.
            if (inst != null && !inst.isEmpty()) {
                // We need to rout the file.
                log.info("Instructions found, executing instructions");
                String[] tokens = fileName.split("\\.");
                String instFileName = "default.ctl";
                if (tokens.length == 2) {
                    instFileName = tokens[0] + ".ctl";
                }
                File controlFile = createFile(destination.getAbsolutePath()
                        + "\\" + instFileName, inst);
                Control control = new Control(controlFile);
                instructions.execute(control);
                log.info("Done executing instructions");
            } else {
                log.info("No instructions were found");
            }
            log.info("Done consuming message: "
                    + bytesMessage.getJMSMessageID());
        }

    }

    /**
     * Creates a file with the given filename (this should be an absolute path),
     * and the text that is to be contained within the file.
     *
     * @param fileName
     *            The filename including the absolute path of the file.
     * @param fileText
     *            The text to be contained within the file.
     * @return The newly created file.
     * @throws IOException
     */
    protected File createFile(String fileName, String fileText)
            throws IOException {
        File toCreate = new File(fileName);
        FileUtils.writeStringToFile(toCreate, fileText);
        return toCreate;
    }

    /**
     * Creates a file with the given filename (this should be an absolute path),
     * and the text that is to be contained within the file.
     *
     * @param fileName
     *            The filename including the absolute path of the f ile.
     * @param fileBytes
     *            The bytes to be contained within the file.
     * @return The newly created file.
     * @throws IOException
     */
    protected File createFile(String fileName, byte[] fileBytes)
            throws IOException {
        File toCreate = new File(fileName);
        FileUtils.writeByteArrayToFile(toCreate, fileBytes);
        return toCreate;
    }
}