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

时间:2010-08-20 06:05:56

标签: 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 Profiling 功能对此进行了分析。

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

    private static Log logger = LogFactory.getLog(X.class);
    ...
    if (logger.isDebugEnabled()) {
        ...
        logger.debug("Log...");
    }

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

II。数据库操作: 我第一次调用以下EJB的find方法需要2,4 s!其他呼叫仅持续几毫秒。那么为什么第一次手术需要很长时间?这是(仅仅因为)连接建立还是与依赖注入有关 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() 
    }
}

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

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

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

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

2 个答案:

答案 0 :(得分:4)

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

  

予。记录(...)从Netbeans 6.8切换到Netbeans 6.9.1后解决了慢速记录的问题

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

  

II。数据库操作:我第一次调用以下EJB的find方法需要2,4秒!其他呼叫仅持续几毫秒。那么为什么第一次操作需要很长时间?

可能是因为某些GlassFish服务被(延迟)加载,可能是因为必须实例化无状态会话bean(SLSB),可能是因为必须创建EntityManagerFactory。分析说了什么?为什么在激活应用服务器日志时会看到什么?什么问题,因为后续的电话没问题?

  

III。依赖注入,JNDI查找:DI之间是否存在差异(@EJB ...)和关注性能的InitialContext查找?

JNDI查找很昂贵,事实上在好的旧服务定位器中使用一些缓存。因此,我不认为使用DI时性能最差(我实际上希望容器能够擅长)。老实说,这对我来说从来都不是一个问题。

当您进行性能优化时,典型的工作流程是:1)检测慢速操作2)找到瓶颈2)对其进行操作3)如果操作仍然不够快,请返回2)。根据我的经验,瓶颈是DAL中90%的时间。如果您的瓶颈是DI,则IMO没有性能问题。换句话说,我认为你太担心而且你非常接近“过早优化”。

  

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

我没有看到任何问题:)所以我没有什么可说的。 更新(回复评论):使用会话范围可能确实更便宜。但一如既往地衡量。

  

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

SLSB(和MDB)的表现非常好。但是在使用SLSB时,请注意以下几点:

  • 如果您的客户端和EJB并置以避免远程调用的开销,则首选Local over Remote接口。
  • 仅在必要时使用有状态会话Bean(SFSB)(它们更难使用,管理状态具有性能成本,并且它们本质上不能很好地扩展)。
  • 避免过多地链接EJB(特别是如果它们是远程的),更喜欢粗粒度方法而不是多个细粒度方法调用。
  • 调整SLSB池(以便您只有足够的bean来为并发客户端提供服务,但不能过多以避免浪费资源)。
  • 适当使用交易(例如,对于只读方法使用NOT_SUPPORTED)。

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

  

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

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

正如我已经暗示的那样,你确定你确实遇到了性能问题吗?我不相信。但如果你真的是,那就测量IDE之外的性能。

答案 1 :(得分:1)

我同意Pascal Thivent的观点,认为“过早优化”是不好的。很好地设计你的代码,然后担心性能。

此外,您可以针对性能或内存保护进行优化。选择哪一个导致你在早上头痛,并优化。

我其实非常喜欢NetBeans的分析器;它是最好的免费之一,恕我直言。

我建议:

  1. 对性能进行性能分析,但将范围限制为您自己的包(例如de.x)或排除Java核心类。这样您的应用程序就不会陷入分析并且会给您带来误导性的数字。基本上,尽量让“开销”尽可能低,如底部的栏所示。
  2. alt text

    1. 浏览您的网络应用程序一段时间,查看占用大部分CPU时间的内容。还要注意一些对象是延迟加载的,所以第一次访问代码时可能会很慢。此外,您正在使用JIT编译器,因此代码在运行它的第一个(或第二个......)时间可能会很慢,但随着您更频繁地使用该代码,它会变得更快。简而言之,请使用Web应用程序一段时间。您可以使用Selenium“记录”网络会话并“回放”它。这样您就可以获得更好的性能指标,并查看应用程序的运行速度,而不是测量“预热时间”。

    2. 如果有一段特定的代码或类导致您遇到麻烦,请使用profiling points查看导致该段代码变慢的原因。

    3. 如果您有一段特定的代码导致您出现问题,请随时发布。