在 WebLogic 中配置 JMS 消息大小:weblogic.socket.MaxMessageSizeExceededException
Posted
技术标签:
【中文标题】在 WebLogic 中配置 JMS 消息大小:weblogic.socket.MaxMessageSizeExceededException【英文标题】:Configuring JMS Message Size in WebLogic: weblogic.socket.MaxMessageSizeExceededException 【发布时间】:2012-08-20 05:58:34 【问题描述】:我目前有两个客户端(生产者/消费者),我正在尝试通过 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)
我相信这与我在 WebLogic 中的 MaxMessage 大小设置有关,而不是代码问题(但我当然可能是错的)。这是我对最大消息大小的设置
我不确定为什么会收到此异常,因为此协议的最大消息大小大于异常声称的大小...有什么想法吗?
我也尝试添加服务器启动参数 -Dweblogic.MaxMessageSize=200000000,但无济于事。
这是我设置 MessageListener 和消息使用者本身的一些代码。
public boolean setClient(MessageListener listener)
try
Properties parm = new Properties();
parm.setProperty("java.naming.factory.initial",
"weblogic.jndi.WLInitialContextFactory");
parm.setProperty("java.naming.provider.url", iProps.getURL());
parm.setProperty("java.naming.security.principal", iProps.getUser());
parm.setProperty("java.naming.security.credentials",
iProps.getPassword());
ctx = new InitialContext(parm);
final QueueConnectionFactory connectionFactory = (QueueConnectionFactory) ctx
.lookup(iProps.getConFactory());
connection = connectionFactory.createQueueConnection();
((WLConnection) connection)
.setReconnectPolicy(JMSConstants.RECONNECT_POLICY_ALL);
((WLConnection) connection).setReconnectBlockingMillis(30000L);
((WLConnection) connection).setTotalReconnectPeriodMillis(-1L);
session = connection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
queue = (Queue) ctx.lookup(iProps.getQueue());
// The following code in the switch statement is the only code that
// differs for the producer and consumer.
switch (cType)
case PRODUCER:
producer = (WLMessageProducer) session
.createProducer(queue);
// Setting to send large files is done in WebLogic
// Administration Console.
// Set
producer.setSendTimeout(60000L);
break;
case CONSUMER:
consumer = session.createConsumer(queue);
if (listener != null)
consumer.setMessageListener(listener);
else
log.warning("A Message listener was not set for the consumer, messages will not be acknowledged!");
break;
default:
log.info("The client type " + cType.toString()
+ " is not currently supported!");
return false;
connection.setExceptionListener(new ExceptionListener()
@Override
public void onException(JMSException arg0)
Logger log2 = new MyLogger().getLogger("BPEL Client");
if (arg0 instanceof LostServerException)
log2.severe("Connection to the Server has been lost, will retry in 30 seconds. "
+ arg0.toString());
else
log2.severe(arg0.toString());
);
shutdownListener = new ShutdownListener(connection, session, producer, consumer);
connection.start();
log.info("Successfully connected to " + iProps.getURL());
return true;
catch (JMSException je)
log.severe("Could not connect to the WebLogic Server, will retry in 30 seconds. "
+ je.getMessage());
try
Thread.sleep(30000L);
catch (InterruptedException e)
log.warning(e.toString());
return setClient(listener);
catch (Exception e)
log.severe("Could not connect to the WebLogic Server, will retry in 30 seconds. "
+ e.toString());
try
Thread.sleep(30000L);
catch (InterruptedException ie)
log.warning(ie.toString());
return setClient(listener);
这是消息监听器:
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;
【问题讨论】:
您可以尝试更改集群中的广播类型。如果已设置为UNICAST,请忽略。 我已经发现了问题,我没有在客户端应用程序上设置 -Dweblogic.MaxMessageSize,现在它可以正常工作了。 【参考方案1】:您还必须从 WLS 控制台增加最大消息大小,如屏幕截图中所示所有托管服务器。
然后重新启动,问题就解决了。
此外,还有第二种替代解决方案。根据Oracle Tuning WebLogic JMS Doc:
调整 MessageMaximum 限制
如果推送给消费者的消息的总大小大于当前协议的最大消息大小(默认大小为 10 MB,并且使用控制台基于每个 WebLogic Server 实例配置,使用控制台基于每个客户端配置) Dweblogic.MaxMessageSize 命令行属性),消息传递失败。
在客户端上设置最大消息大小
在发送和接收大型消息时,除了 WebLogic Server 实例之外,您可能还需要配置 WebLogic 客户端。要在客户端上设置最大消息大小,请使用以下命令行属性:
-Dweblogic.MaxMessageSize
注意:此设置适用于所有传送到客户端的 WebLogic Server 网络数据包,而不仅仅是 JMS 相关数据包。
已编辑:
可以通过执行以下一项或多项操作来解决此问题。
配置系统属性 -Dweblogic.MaxMessageSize 使用 WLS 控制台为管理员和所有托管服务器增加最大消息大小。 WLS 控制台中的步骤是:服务器/协议/常规 从 WLS 控制台增加最大消息大小。 WLS 控制台中的步骤是:队列/配置/阈值和配额/最大消息大小
PROCEDURE 用于应用 weblogic.MaxMessageSize 属性
保留 setDomainEnv 文件的备份。停止所有服务器。在每个 setDomainEnv 文件中添加 -Dweblogic.MaxMessageSize=yourValue,更具体地说,在 EXTRA_JAVA_PROPERTIES 行中添加。然后先启动 ADMIN,当 ADMIN 处于 RUNNING 状态时,再启动 MANAGED 服务器。
我希望这会有所帮助。
【讨论】:
感谢您的回复,虽然我已经尝试了这两种方法,但问题仍然存在。我不明白的是为什么我可以产生一个大的 JMS 消息并把它放在队列中,但我不能消费完全相同的 JMS 消息? 我已经更新了帖子。您是否尝试了所有 3 种可用的解决方案,但都没有解决您的问题?您是否从管理服务器和所有托管服务器中的 WLS 控制台配置了最大消息大小?谢谢 我已经尝试了所有 3 个选项,唯一不确定我是否正确执行的选项是系统属性。我用我在哪里设置属性的图像编辑了我的问题。这是正确的地方吗?进行更改后,我尝试重新启动服务器,但仍然收到相同的错误。 好像没问题。你能告诉我 WLS 版本吗? WebLogic 服务器版本:10.3.5.0【参考方案2】:在我的情况下,设置 -Dweblogic.MaxMessageSize 解决了这个问题。我的问题是邮件大小的最大限制应该是多少?我们只是不能继续增加 消息大小来解决此问题。另外还有什么方法可以优化这个值 与某些其他值?
【讨论】:
这将是您必须通过找到您发送的最大消息来发现自己的东西。 如何找到最大的 t3 消息?我没有看到任何在 weblogic 中记录 t3 消息的机制。 您可以使用管理控制台监控队列,也可以使用企业管理器进行更图形化的布局,但 EM 主要用于实时查看流量。另一个选项是将值设置为最大可能数(可以在管理控制台上配置 MaxMessageSize 时找到)。如果您最大的消息超过该大小,那么 weblogic 将无法支持它。 在我的情况下实际上是 t3 消息,而不是 JMS 消息。我检查了 weblogic 控制台,找不到任何标志或任何配置可以帮助我记录或监控它。当然,通过增加它的大小它可以工作。但它更多的是打击和审判案件。我想知道它是如何随着我的远程数据大小的增加而增长的。任何指向记录或监视 t3 消息的任何机制的指针都将非常有帮助。我在官方weblogic论坛上问过同样的问题,但还没有得到任何答案。以上是关于在 WebLogic 中配置 JMS 消息大小:weblogic.socket.MaxMessageSizeExceededException的主要内容,如果未能解决你的问题,请参考以下文章