我目前正在为使用 JMS(即 Spring 框架 JMS 和 Active MQ)在服务器和客户端之间发送带有有效负载的消息的应用程序开发带宽限制功能(不要问我为什么,这不是我的决定)。
我发现了很多限制传入 JMS 消息的限制方法(但没有一个基于实际带宽负载),但是我没有找到任何可能的方法来限制传出消息流。所以我决定自己写漏桶算法。
有什么方法可以获取 JMS 消息的大小吗?除了 Java 中的“sizeof”实现(在 Java 中,确定对象大小的最佳方法是什么?)
我目前正在为使用 JMS(即 Spring 框架 JMS 和 Active MQ)在服务器和客户端之间发送带有有效负载的消息的应用程序开发带宽限制功能(不要问我为什么,这不是我的决定)。
我发现了很多限制传入 JMS 消息的限制方法(但没有一个基于实际带宽负载),但是我没有找到任何可能的方法来限制传出消息流。所以我决定自己写漏桶算法。
有什么方法可以获取 JMS 消息的大小吗?除了 Java 中的“sizeof”实现(在 Java 中,确定对象大小的最佳方法是什么?)
我认为您没有比测量其序列化大小更好的方法来确定 JMS 消息大小。
但是您可以根据需要添加一些优化。有几种类型的消息(例如 MapMessage、ObjectMessage、TextMessage)。
文本消息的大小是其文本的长度。map 消息的大小是其所有字段的总大小。这些字段是原语或 java.util.Date,因此测量它们不是问题。对象消息包含可序列化对象,因此您可以通过写入 ByteOutputStream 来测量其大小。
如果您使用大多数 JMS 提供者的隐藏功能来发送延迟消息,我认为使用 JMS 实现漏桶可能会被简化。您可以在将消息排入队列时对其进行测量,并决定您希望订阅者何时接收它。请在此处阅读有关如何发送延迟消息的详细信息:http: //alexradzin.blogspot.com/2010/10/send-delayed-jms-messages.html
由于 JMS 消息在发送过程中是序列化的,因此获取消息大小的最佳方法是通过 ObjectOutputStream。
private int getMessageSizeInBytes(MessageWrapper message) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(message);
oos.close();
return baos.size();
}
除了@AlexR 之前的评论,BytesMessage 还有一个 getBodyLength() 方法
http://download.oracle.com/javaee/1.4/api/javax/jms/BytesMessage.html#getBodyLength
您可能可以通过捕获使用 Session.createMessage() 创建的一些对象来估计传输中的典型标头大小 - 即没有有效负载的 JMS 消息类型。我想我很想直接使用 byte[] 中的有效负载,使用 BytesMessage,如果带宽很关键,则通过 ZipOutputStream 进行压缩。此外,JMS 允许提示抑制消息时间戳和消息 ID,这可能有助于减少消息大小,例如
尽管不要求提供者支持它,
如果 JMS 提供者接受此提示,则这些消息的消息 ID 必须设置为 null;如果提供者忽略提示,则消息 ID 必须设置为其正常的唯一值
我曾经在 WebSphere MQ 各处使用带宽非常有限的 JMS,并且可以通过这种方式获得非常小的消息大小 - 尽管在这种情况下本机线框格式也针对大小进行了优化