构建高性能的j2ee应用不但需要了解常用的实施技巧。下面介绍最常用的10种有效方法,可帮助架构设计师们快速成为这方面的专家。
java性能的基础―内存管理
任何java应用,单机的或j2ee的性能基础都可归结到你的应用是如何管理内存的问题。java的内存管理包括两个重要任务:内存的分配和内存的回收。在内存的分配中,目标是要减少需要创建的对象。
内存回收是导致性能下降的普遍原因。也就是说,内存中的对象越多,垃圾回收越困难。所以我们对创建对象的态度应该越保守越好。
在j2ee应用中常见的两个内存有关的问题是:游离的对象(也被称为内存泄露)和对象循环(指大量频繁创建和删除-在java中体现为解除引用---对象)。
我们应注意确保所有可到达的对象实际是活的,即这些对象不但在内存中,而且也要在执行的代码中是存在的。当对象在应用中已经没有用了,而我们却忘记了删除对该对象的引用时,游离的对象就出现了。
我们知道垃圾回收会占用cpu时间。短期对象的大量创建增加了垃圾回收的频率会造成性能下降。
不要在servlet中实现业务逻辑
在构建j2ee应用时,架构工程师通常会使用到j2ee的基本部分――servlet。如果架构师不使用session beans, entity beans, 或 message beans, 那么改进性能的方法就很少。只能采用增加cpu或更多的物理服务器等方法。ejb使用了缓存(cache)和资源池等方法可以提高性能和扩展性。
尽可能使用本地接口访问ejb
在早期的j2ee (遵循ejb1.x规范)应用中,访问ejb是`通过rmi使用远程接口实现的。随着ejb2.0的出现,可以通过本地接口访问ejb,不再使用rmi,在同一个jvm中使用远程方法已经少多了。但是现在还是有一些使用ejb1.x实现的应用和不知道使用本地接口的一些ejb新手。为说明这点,我们作个比较:
1、客户端应用调用本地stub
2、该stub装配参数
3、该stub传到skeleton
4、该skeleton分解参数
5、该skeleton调用ejb对象
6、ejb对象执行容器服务
7、ejb对象调用企业bean实例
8、企业bea执行操作
9、执行组装/分解步骤然后返回
与远程接口处理相比较,本地接口的ejb方法是:
1、客户端调用本地对象
2、本地对象执行容器服务
3、本地对象调用企业bean实例
4、企业bean实例执行操作
5、没有其他返回步骤!
如果你不需要从远程的客户端访问一个特殊ejb,就应该使用本地方法。
在实现session bean的服务中封装对实体ejb的访问
从servlet访问实体ejb不但效率低而且难于维护。使用session facade(会话外观)模式可把对实体ejb的访问封装在会话ejb中,在该会话ejb中通过使用本地接口访问实体ejb而避免过多的远程调用。
这项技术会有额外的性能和扩展方面的好处,这是因为会话和实体ejb可以使用缓存和资源池技术来进行改进。另外,由于负载的需要,会话和实体ejb可被扩展部署到其他硬件设备上,这比将servlet层复制扩展到其他硬件设备上要简单的多。
尽量粗粒度访问远程ejb
当访问远程ejb时,调用set/get方法将产生过多的网络请求,同时也导致远程接口处理的过载。为避免这种情况,可考虑将数据属性集中在一个对象中,这样通过一次对远程ejb的调用就可以传递所有数据。这项技术就是数据传输对象(data transfer object)模式。
优化sql
j2ee的架构设计工程师和开发人员通常不是sql专家或经验丰富的数据库管理员。首先应该确保sql使用了数据库提供的索引支持。在某些情况下,将数据库的索引和数据分开存放会提高性能。但要知道,增加额外的索引可以提高select性能但也会降低insert的性能。对于某些数据库,关联表之间的排序会严重影响性能。可以多向数据库管理员咨询。
避免在实体ejb中过多执行sql
有时候,通过实体ejb访问数据会执行多个sql语句。根据j2ee 规范,第一步,将调用实体bean的find(发现)方法;第二步,在第一次调用实体ejb的业务方法时,容器会调用ejbload()从数据库中获得信息。
很多cmp(容器管理持久性)在调用发现方法时就缓存了实体数据,所以在调用ejbload()时就不再访问数据库了。应该避免使用bmp(bean管理的持久性)或者自己实现缓存算法避免二次访问数据库。
使用fast lane reader 模式访问只读数据
j2ee应用经常要以只读方式访问大量长时间不变的数据,而不是访问单个实体,例如浏览在线产品目录。在这种只读情况下,使用实体ejb访问数据会导致严重过载并且实现很麻烦。实体ejb 适合于对单个实体的粗粒度访问,访问大量的列表只读数据时效率不高。不管是使用cmp还是bmp,一定需要编写代码操作多个实体ejb及其关联。这将导致访问多个数据库并存在大量的也是不必要的事务开销。
利用java messaging servce(消息服务)
j2ee规范在jms中提供了内置的异步处理服务。当涉及到系统需求时,应该了解在什么情况下应该采用jms进行异步处理的设计。一旦确定要执行一些异步处理,那么同步处理的任务就应该越少越好,将数据库密集的操作安排在稍后的异步处理中完成。
缓存jndi lookup查找
很多操作在进行jndi查找时要消耗大量资源。通常应该缓存jndi资源避免网络调用和某些处理的过载。可以缓存的jndi查找包括:
ejb home interfaces
data sources
jms connection factories
ms destinations/topics
一些jndi包实现了缓存功能。但是调用对ejb主接口的narrow方法时,这种功能作用有限。缓存查找的设计应该使用共享的intialcontext 实例,尽管构建它很麻烦。这是因为需要访问多种数据源,包括应用资源文件jndi.properties,系统属性的各项参数,传入到构造函数的各项参数。
闽公网安备 35060202000074号