dev2dev 首页 > 资源中心 > 专家Blog > 专家Blog文章
EJB实体缓存和事务
大家都知道 EJB 容器支持实体 Bean 缓存。通常是在特定于供应商的部署描述符中为每个 Bean 定义缓存容量。在 WebLogic 中是 weblogic-ejb-jar.xml 文件中的 max-beans-in-cache 元素。如果没有指定该元素的值,就使用默认值 1000 。
可能因为说明文档将 max-beans-in-cache 描述为一个纯粹的性能优化参数,很多开发人员没有意识到一些其他的因素也会影响正确的缓存容量的选择。
例如,一个通常不为人注意的事实是,当事务使用实体 bean 时, bean 实际上被加载到实体缓存中,并在事务的整个持续时间内都保存在缓存中,即使代码并没有修改实体 bean ,而只是读取它的值。
设想一下会话 Bean 或 MDB Bean 中的代码对实体 bean Person 执行 finder 方法,然后迭代返回 Collection :
... Collection persons = personLocalHome.findSomething(); for (Iterator iter = persons.iterator(); iter.hasNext();) { PersonLocal person = (PersonLocal)iter.next(); Long id = person.getId(); // do something: log, send email, etc ... } ...
如果 findSomething() 方法返回的对象的数目超出了在 max-beans-in-cache 中所指定的值,当 Iterator 返回第 N+1 个(当前的实体缓存容量是 N )对象时,就会(很可能是突然地)出现令人讨厌的 weblogic.ejb20.cache.CacheFullException 异常。
这看起来没什么大不了的,有人可能会说不管怎么样 finder 不会返回很多 collection 的,等等。但是不要忘了,首先,默认情况下, WebLogic 实体缓存是多版本的。这意味着,如果多个事务请求同一个实体 bean ,将在缓存中创建多个版本(每个事务一个版本),这将会大大降低每个对象的缓存容量。其次,容器中运行多个同时的事务是很平常的。设想一下如果上面的代码被会话 bean 或 MDB bean 调用,它的 max-beans-in-free-pool 参数值(默认值也是 1000 )很大,而且假定同时有 50 个客户请求传入。这样每个事务在实体缓存中就只有 1000/50 = 20 个槽可使用,而如果 finder 返回的对象多于 20 个,那么有一些事务就可能要失败了。
这些东西在设计具有大量实体 bean 的操作时一定要记住。更糟糕的是,开发人员通常使用小容量的数据库,这造成了在使用生产规模的数据库部署之前问题完全不能暴露。我推荐一个应对措施,在开发中不要使用默认的缓存容量设置,而将其设置为一个比较低的值 (10-100) ,这样就可以在开发的早期阶段发现并解决与缓存相关的问题。
评论
我以前提到的 CacheFullException bug 只出现在特定的情况下(会话 bean 和 CMP bean 的事务属性的特定组合)。
BEA 已经用 CR 209987 修复了这个 bug ,而且 WLS 8.1 SP5 也会包含它。
发表人: maximdim , 2005 年 5 月 9 日, 01:32 PM
似乎在抛出 CacheFullException 后有一个清除实体缓存的 bug ,至少是在 WLS 8.1 中。
发表人: maximdim , 2005 年 4 月 18 日, 11:25 AM
Vincent ,
在 WebLogic 中, max-beans-in-free-pool 参数控制 无名 bean 实例池的最大容量。该参数对性能不会造成太大影响,因为对于如今的 JVM ,对象的实例化开销并不大(除非您的对象本身就需要很大开销才能实例化)。而且,总是可以成功地从空闲池中获得实体 bean 实例,即使池是空的,也会创建一个新的 bean 实例并返回,所以即使空闲池用完了,也不会出现异常的。我建议如果您的实体 bean 不进行开销很大的操作,最好不要更改 max-beans-in-free-pool 参数。
至于您的例子, 50 个同时的请求,每个返回 5000 个对象——至少对默认的多版本缓存策略,缓存中有足够的空间容纳 50x5,000=250,000 个 bean 。但是要注意您的内存占用量。我还想问问什么样的设计会需要在一次调用中返回 5,000 个对象。
发表人: maximdim , 2005 年 4 月 18 日, 08:17 AM
你好, Dmitri ,我有点分不清如何设置 EJB 实体缓存和事务的 max-beans-in-cache 和 max-beans-in-free-pool 参数。如果我的应用程序必须处理 50 个同时的客户机请求,而且每个请求会返回 5000 个对象,我是不是就得把 max-beans-in-cache 设为 5000 ,而 max-beans-in-free-pool 设为 250000 ?谢谢。 Vincent 。
发表人: taifook , 2005 年 4 月 17 日, 09:41 PM
BEA 支持站点上有一些不错的补充信息: Investigating CacheFullException for Entity and Stateful Session Beans 。
发表人: maximdim , 2005 年 4 月 15 日, 10:39 AM
原文出处: http://dev2dev.bea.com/blog/maximdim/archive/2005/04/ejb_entity_cach.html
作者其它文章
|