如果您曾经读过我以前的文章,您可能会知道选择正确的实体缓存容量至关重要,而且这不只是从性能优化的角度考虑的。如果缓存容量太大,应用程序的内存占用量就会非常大,而且是完全不必要的;另一方面,如果将缓存容量配置得过小,就有可能出现CacheFullException异常。那么该如何为实体bean选择最佳的缓存容量呢?
如果您不是通过部署描述符中的max-beans-in-cache元素来显式地指定实体bean的缓存容量,WebLogic就会使用默认的容量:1000。这对于一些能够先验地知道实例数不会太大的bean来说就足够了。例如,如果bean代表数据库中的查找表,比如“国家”和“州”,那么bean实例的最大值就很容易知道。这种情况下,完全可以不指定缓存容量,而让WebLogic使用默认值,因为如果缓存没有全部使用对内存也没有什么影响。另外,对于不变化或不经常变化的bean,使用ReadOnly并发策略是一个很好的方法。这不仅会消除不必要的ejbLoad()调用,还可以限制对于每一个PK实体缓存中只能有一个bean实例(多版本就不一定了),因此节省了内存使用并提高了性能。
对于那些不知道可能同时访问的最大实例数的bean来说,情况可能有些复杂。您需要分析和估计由finder方法返回并在同一个事务中访问的bean的最大数目,然后乘以应用程序要处理的操作所涉及的同时发生的最大事务数(这通常会受制于应用程序入口点(会话bean和/或MDB)的最大实例数)。这将使您能够粗略估计出特定的实体bean所需的最大缓存容量。
如果应用程序中使用了很多实体bean,分析并配置每个bean的缓存可能会很麻烦。估计由master-detail关系的detail端所返回的bean实例数尤其棘手。例如,应用程序对order表执行finder方法,而每个order都有items集合,它可能是一个,也可能是很多个。另一个问题是,因为每个实体bean都有各自的缓存,所以内存利用率不高。
可能认识到了“一个bean一个缓存(single cache per bean)”模型的局限性,从WebLogic版本7开始,BEA添加了实体bean的应用程序级缓存支持。它允许同一个J2EE应用程序中的多个实体bean共享一个运行时缓存。
应用程序级缓存具有以下优点:
1.减少了实体bean缓存的数目,并因而减少了配置缓存所需的工作量。
2.因为减少了碎片,因而更好地利用了内存和堆空间。例如,如果一个特定的EJB遇到了突发的活动,它就可以利用组合缓存(即应用程序级缓存)所有可用的内存,而其他使用该缓存的EJB则被页面换出。如果两个EJB使用不同的缓存,当一个bean的缓存满了之后,容器不能换出其他bean缓存中的EJB,从而导致了内存浪费。
3.简化管理:组合缓存使系统管理员能够将多个缓存调整为一个缓存。
4.提供了更好的可伸缩性。
可以考虑使用应用程序级缓存来代替为每个bean指定单独的缓存。它对引用单个缓存的实体bean的数目没有限制,对所定义的缓存数目也没有限制。缓存容量可以根据bean的实例数来指定(与一个bean一个缓存的方法类似),或者指定为内存的最大容量。从管理角度来看,使用最大内存容量极具吸引力,但是要知道,WebLogic不会计算被缓存中的bean所占用的实际内存的总量(这一操作执行起来很可能开销非常大),而只是用指定的内存总量除以weblogic-ejb-jar.xml部署描述符中所指定的bean的平均缓存容量。如果没有指定容量,bean将使用100字节的平均容量。因此我认为将缓存容量指定为若干个bean实例更为透明。