转载

对WeblogicJMS进行性能调优(4.24)

对于Weblogic JMS的性能调优,在如下这篇文章中有一些总结:

https://blog.csdn.net/zhangout/article/details/6292206

1. 增加-Dweblogic.JMSThreadPoolSize=n(至少为5),以提高处理JMS的线程数,在

jRockit上增加-XXenablefatspin以减少加锁冲突;

2. 采用文件存储策略,将同步写策略设置为Direct-Write,同时在windows平台上启用磁盘写入缓存;

3. 使用分布式目的地时,激活连接工厂Load Balancing Enabled ,Server Affinity Enabled;

4. 为减少服务器不必要的JMS请求路由,如果多个目的地之间存在事务,则部署在同一JMS服务器上,尽量将连接工厂部署到JMS服务器所在的WebLogic实例上,集群环境下,则最好将连接工厂部署到集群中的所有服务器上,而集群中每个JMS服务器和目的地成员尽量使用类似的设置;

5. 启用消息分页存储功能,以释放内存,可以为JMS服务器和目的地设置, 激活Messages Paging Enabled和Bytes Paging Enabled,同时使用限额防止服务器耗尽接收消息的所有可用内存空间;

6. 在运行WebLogic Server进程之外的生产者务必使用流控制, 并增大Send Timeout;

7. 将JMS Server Expiration Scan Interval设很大的值,能禁止主动扫描过期消息;

8. 使用FIFO或者LIFO方式处理目的地消息;

9. MDB的max-beans-in-free-pool不应大于最大MDB线程数(默认线程数/2+1)。

个人理解里面有意义的调整还是通过 -Dweblogic.JMSThreadPoolSize 参数设置来增加JMS的线程数。对于初始化JMS上下文和创建JMS会话慢的问题,考虑主要两个原因导致。第1就是从Pool连接池中获取可用的连接慢,其次就是本身IntailContext就很慢。但是即使IntailContext操作太慢,花费上10秒的时间也属于不正常的现象。而且根据观察发现,更多都是去初始化Remote Machine远程JMS Server的连接和会话的时候很慢。

对于JMS代码层面的调优,在上面这篇文章中也给出了具体的内容如下:

a.注意必要的事项,避免使用不必要的特征

JMS提供了强有力的消息处理机制,但是为了最大限度的提高JMS系统的性能,应避免使用不需要使用的特征,同时也要注意必要的事项。比如:尽量使用接收程序能直接使用的最简单、最小的消息类型;消息选择器要尽可能简单(最好不使用),尽量不要使用复杂的操作符,如like、in或者between等,使用字符串数据类型的速度最慢;务必为特定的应用程序定义特定的JMS连接工厂,并且禁用默认的JMS连接工厂;不要在javax.*与weblogic.*的名字空间中使用JNDI名称;尽量使用异步消费者,线程不必封锁以等待消息的到达;使用完JNDI树上的资源后注意关闭。

b.消息类型的选择

标准JMS提供了五种消息类型,而TextMessage应用最为普遍, 当发送的消息是几种原始数据类型的集合体时,最好使用MapMessage消息类型,而不要使用ObjectMessage,以便减少不同系统间的耦合。此外消息是否使用压缩要慎重考虑,压缩未必能减少消息大小。如果生产者、消费者和目的地并置在同一WebLogic Server内部,通常不使用压缩。WebLogic特有的XMLMessage能为运行于消息主体之上的消息选择器提供内嵌式支持,而且易于数据交换。因此,建议应用程序之间传送消息使用XML消息格式,而应用程序内部间传送消息使用二进制消息格式。

c.确认方式的选择和JMS事务

使用事务性会话时,尽量使用恰当的消息确认方式:如果需求允许,使用NO_ACKKNOWLEDGE;非持久的订阅者使用DUPS_OK_ACKNOWLEDGE或者MULTICAST_NO_ACKNOWLEDGE。而使用JTA的UserTransaction,确认方式将被忽略。在使用JMS事务时,无效的消息会导致事务的回滚,以致消息重发这样的死循环。此时,可以将无效消息发送到错误消息队列,并提交JMS事务,这将确保消息不会再次传递。

对于通过Pool来增加性能,在Oracle官方文档里面有详细的描述,具体地址在:

https://docs.oracle.com/cd/E28280_01/web.1111/e13727/j2ee.htm#JMSPG376

注意可以看下给出的示例代码(PoolTestBean.,感觉是每次使用的时候都会重新创建连接和会话,但是Oracle文章中的解释是:

尽管在这个例子中,连接工厂,连接,和会话对象是每次发送一个消息时都会新创建,实际上这三个类是一起工作的,所以当他们被使用的时候,他们只是从Pool连接池中取回一个对象而已。

Speeding Up JNDI Lookups by Pooling Session Objects

The JNDI lookups of the Connection Factory and Destination objects can be expensive in terms of performance. This is particularly true if the Destination object points to a Foreign JMS Destination MBean, and therefore, is a lookup on a non-local JNDI provider. Because the Connection Factory and Destination objects are thread-safe, they can be looked up once inside an EJB or servlet at creation time, which saves the time required to perform the lookup each time.

Inside a servlet, these lookups can be performed inside the init() method. The Connection Factory and Destination objects may then be assigned to an instance variable and reused whenever a message is sent.

Inside an EJB, these lookups can be performed inside the ejbCreate() method and assigned to an instance variable. For a session bean, each instance of the bean will then have its own copy. Since stateless session beans are pooled, this method is also very efficient (and is perfectly consistent with the , because the number of a times that lookups occur is drastically reduced by pooling the JMS connection objects. (Caching these objects in a static member of the EJB class may work, but it is discouraged by the

However, if these objects are cached inside the ejbCreate() or init() method, then the EJB or servlet must have some way to recreate them if there has been a failure. This is necessary because some JMS providers, like WebLogic JMS, may invalidate a Destination object after a server failure. So, if the EJB runs on Server A , and JMS runs on Server B , then the EJB on Server A will have to perform the JNDI lookup of the objects from Server B again after that server has recovered. The example, PoolTestBean.java includes a sample EJB that performs this caching and re-lookup process correctly.

Speeding Up Object Creation Through Caching

Once Connection Factory object and/or Destination object pooling has been established, it may be tempting to cache other objects, such as the Connection, Session, and Producer objects, inside the ejbCreate() method. This will work, but it is not always the most efficient solution. Essentially, by doing this you are removing a Session object from the cache and permanently assigning it to a particular EJB, whereas by using the JMS wrappers as designed, that Session object can be shared by other EJBs and servlets as well. Furthermore, the wrappers attempt to reestablish a JMS connection and create new session objects if there is a communication failure with the JMS provider, but this will not work if you cache the Session object on your own.

Enlisting the Proper Transaction Mode

When a JMS send() or receive() operation is performed inside a transaction, the EJB or servlet automatically enlists the JMS provider in the transaction. A transaction can be started automatically inside an EJB or servlet that has container-managed transactions, or it can be started explicitly using the UserTransaction interface. In either case, the container automatically enlists the JMS provider. However, if the underlying JMS connection factory used by the EJB or servlet does not support XA, the container throws an exception.

Performing the transaction enlistment has overhead. Furthermore, if an XA connection factory is used, but the send() or receive() method is invoked outside a transaction, the container must still create a JTA transaction to wrap the send() or receive() method in order to ensure that the operation properly takes place no matter which JMS provider is used. Although this is only a one-phase commit, it can still slow down the server.

Therefore, when writing an EJB or servlet that uses a JMS resource in a non-transactional manner, it is best to use a JMS connection factory that is not configured to support XA.

对于跨机器访问JMS Server的时候,在初始化上下文和创建连接和会话的时候,是否会导致实际性能问题,暂时没有找到明确的的原因和解释。但是根据实际的日志监控来看,大部分的响应慢的都是跨了Server的情况。因此对于该问题实际上还需要进一步分析和评估。

原文  http://blog.sina.com.cn/s/blog_493a84550102xcuq.html
正文到此结束
Loading...