JavaEE 6应用程序(Glassfish v3)中的性能 - 日志记录,DI,数据库操作,EJB,托管Bean

Mic*_* W. 5 performance logging java-ee java-ee-6 glassfish-3

我使用的重要技术有:Glassfish v3,JSF 2.0,JPA 2.0,EclipseLink 2.0.2,log4j 1.2.16,commons-logging 1.1.1.

我的问题是应用程序的某些部分非常慢.我用netbeans 6.8分析功能对此进行了分析.

I.记录 - 我使用log4j和apache commons记录在日志记录文件和控制台中生成日志.日志也出现在glassfish的服务器日志中.我使用记录器如下:

    private static Log logger = LogFactory.getLog(X.class);
    ...
    if (logger.isDebugEnabled()) {
        ...
        logger.debug("Log...");
    }
Run Code Online (Sandbox Code Playgroud)

问题是,有时这样的短语需要花费很多时间(大约800毫秒).当我切换到java.util.logging时,它不是那么糟糕但也很慢(200毫秒乐队).有什么问题?我需要一些日志记录... 更新 - 从Netbeans 6.8切换到Netbeans 6.9.1后解决了慢速日志记录的问题. - 当日志打印到其控制台时,Netbeans 6.8可能非常慢?!所以它与Log4J或公​​共记录没有任何关系.

II.数据库操作:我第一次调用以下EJB的find方法需要2,4秒!其他呼叫仅持续几毫秒.那么为什么第一次手术需要很长时间?这是(仅仅因为)连接建立还是与XFacade的依赖注入有关,以及这些注射何时执行?:

@Stateless
@PermitAll
public class XFacade {
    @PersistenceContext(unitName = "de.x.persistenceUnit")
    private EntityManager em;
    // Other DI's
    ...

    public List<News> find(int maxResults) {
      return em.createQuery(
      "SELECT n FROM News n ORDER BY n.published DESC").setMaxResults(maxResults).getResultList() 
    }
}
Run Code Online (Sandbox Code Playgroud)

III.依赖注入,JNDI查找:DI之间是否存在差异(@EJB ...)和关注性能的InitialContext查找?注入本地,远程和无接口EJB之间是否存在差异(性能视图)?

IV.托管豆 - 我使用了许多Session Scoped Beans,因为ViewScope似乎非常错误,而Request Scoped实际上并不总是如此.还有其他选择吗? - 因为这些Beans并不慢,但服务器端内存在整个会话期间都会受到压力.当用户退出时需要一些时间!

V. EJB - 我不使用MDB会话Bean和Singleton Beans.他们经常使用@EJB Annotation 注入其他Bean .一个Singleton Bean使用@Schedule Annotations开始重复操作.我发现一个有趣的事情是,从EJB 3.1开始,您可以使用@Asynchronous Annotation使Session Bean Method异步.在实现有关性能的EJB时,我通常应该考虑什么?

也许有人可以给我一些通用和/或具体的提示来提高javaee应用程序的性能,特别是关于上述问题.谢谢!

Pas*_*ent 4

首先,您应该使用负载测试工具在真实环境中测试您的应用程序,您无法根据在 IDE 中观察到的行为真正得出有效的结论。最重要的是,不要忘记分析实际上会改变性能。

I. 日志记录 (...) 从 Netbeans 6.8 切换到 Netbeans 6.9.1 后,日志记录速度慢的问题得到了解决

这是您无法信任 IDE 内部行为的第一个证据。

二. 数据库操作:我第一次调用以下EJB的find方法需要2.4秒!额外的调用仅持续几毫秒。那么为什么第一次手术要花那么长时间呢?

也许是因为某些 GlassFish 服务是(延迟)加载的,也许是因为必须实例化无状态会话 Bean (SLSB),也许是因为EntityManagerFactory必须创建它们。简介说了什么?为什么在激活应用程序服务器日志记录时会看到?既然后续调用都正常了,那问题出在哪里呢?

三.依赖注入、JNDI 查找:像 (@EJB ...) 之类的 DI 和 InitialContext 查找在性能方面有区别吗?

JNDI 查找的成本很高,而且在良好的旧服务定位器中使用一些缓存是事实上的做法。因此,我预计使用 DI 时性能不会最差(我实际上预计容器会擅长于此)。老实说,这从来都不是我关心的问题。

当您进行性能优化时,典型的工作流程是 1) 检测缓慢的操作 2) 找到瓶颈 2) 对其进行处理 3) 如果操作仍然不够快,则返回到 2)。根据我的经验,瓶颈 90% 的时间都出现在 DAL 中。如果你的瓶颈是 DI,那么 IMO 就不存在性能问题。换句话说,我认为你担心太多了,你已经非常接近“过早优化”了。

四.托管 Bean - 我使用许多会话范围 Bean,因为 ViewScope 似乎有很多错误,而请求范围并不总是实用。还有其他选择吗?- 因为这些 Bean 并不慢,但在整个会话期间服务器端内存压力很大。当用户注销时需要一些时间!

我没有看到任何问题:) 所以我无话可说。更新(回答评论):使用对话范围可能确实更便宜。但一如既往,测量。

V. EJB - 我不使用 MDB,仅使用会话 Bean 和 Singleton Bean。他们经常使用 @EJB 注释注入其他 Bean。一个 Singleton Bean 使用 @Schedule 注解来启动重复操作。我发现一个有趣的事情是,从 EJB 3.1 开始,您可以使用 @Asynchronous Annotation 使会话 Bean 方法异步。在实现有关性能的 EJB 时,我通常应该考虑什么?

SLSB(和 MDB)总体上表现良好。但使用 SLSB 时需要记住以下几点:

  • 如果您的客户端和 EJB 并置以避免远程调用的开销,则优先Local选择接口。Remote
  • 仅在必要时才使用有状态会话 Bean (SFSB)(它们更难使用,管理状态会产生性能成本,并且本质上不能很好地扩展)。
  • 避免过多链接 EJB(尤其是远程 EJB),与多个细粒度方法调用相比,更喜欢粗粒度方法。
  • 调整 SLSB 池(以便您有足够的 bean 来服务并发客户端,但不要太多,以避免浪费资源)。
  • 适当地使用事务(例如,对只读方法使用 NOT_SUPPORTED)。

我还建议不要使用某些东西,除非您确实需要该功能并且有一个真正的问题需要解决(例如@Asynchronous)。

也许有人可以给我一些一般和/或具体的技巧来提高 javaee 应用程序的性能,特别是关于上述问题。谢谢!

专注于您的数据访问代码,我很确定这代表了大多数业务流程执行时间的 80%。

正如我已经暗示的那样,您确定您确实存在性能问题吗?我不相信。但如果确实如此,请在 IDE 之外衡量性能。