spring mvc + wildfly + postgresql performance tunning

时间:2017-08-30 07:04:07

标签: performance hibernate spring-mvc optimization wildfly

我花了很多时间试图弄清楚导致我的应用程序工作的原因很慢,也许有人会帮我检查问题所在。

版本:

spring mvc: 4.2.5.RELEASE

hibernate: 4.3.11.Final

spring-data-jpa: 1.8.2.RELEASE

wildfly: 10

PostgreSQL Server: 9.4

OS: Debian GNU/Linux 7.9 (wheezy)

Server configuration: VPS, 1 proc, 4GB RAM

关于我的应用

简单的网络应用程序,包含静态JSP着陆页,信息页和重定向到私有区的登录信息。公共页面是静态的,在登录期间首先查询数据库,然后尝试获取已登录用户的内容。

有什么问题:

当我浏览如下配置的页面时:

<http auto-config="true"> 
        <intercept-url pattern="/" access="permitAll"/>
        <intercept-url pattern="favicon.ico" access="permitAll"/>
        <intercept-url pattern="/login/**" access="permitAll"/>
        <intercept-url pattern="/info" access="permitAll"/>
...
</http>

没有问题,一切都在他的飞行中加载,没有停顿。它工作顺利。 当我发布/登录(将我重定向到/ main)然后当我在每个配置如此的网站上导航时:

<intercept-url pattern="/main/**" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/statistic/**" access="hasRole('ROLE_USER')"/>
<intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />

有时会有一些极端延迟甚至长达1分钟。

Hibernate配置

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}"/>
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!-- Configure the entity manager factory bean -->
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="packagesToScan" value="pl.portal.model"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="jpaProperties">
            <props>
                <!-- <prop key="hibernate.dialect">pl.portal.sql.ProjectPsqlDialect</prop> -->
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.enable_lazy_load_no_trans">true</prop>
                <prop key="hibernate.jdbc.use_streams_for_binary">false</prop>
                <prop key="hibernate.connection.useUnicode">true</prop>
                <prop key="hibernate.connection.characterEncoding">UTF-8</prop>
                <prop key="hibernate.connection.characterSet">UTF-8</prop>

            </props>
        </property>
    </bean>

任何人都可以给我一个提示如何确定造成延误的原因吗?在我的浏览器中检查webinspect - &gt; / admin,大小7,89KB,大小:54secons(每个js或css不能超过100ms)

EDIT2: 删除了线程转储的无效片段,粘贴了在应用程序上调用操作/admin后启动的线程的完整转储。线程花了61s

Thread dump

visualvm控制台上的

线程: enter image description here

4 个答案:

答案 0 :(得分:2)

这种延迟可能有很多原因,下面列出了一些最常见的延迟。

  1. 线程正在等待锁定。
  2. 数据库性能问题。
  3. CPU密集型任务。
  4. 网络延迟
  5. 在您的情况下,可以排除Web服务器和客户端之间的

    网络延迟,因为您提到静态页面和页面资源(如CSS)的服务器响应时间以毫秒为单位。

    对于其他方面,像 VisualVM 这样的远程管理系统是找出导致延迟的原因以及哪个进程占用大量CPU时间的最佳工具。您也可以选择 JProfiler 等商业资讯制作者,但VisualVm也可以完美地完成工作。

    要连接到ViusalVM,您需要有权访问您的服务器,并在JAVA_OPTS或您选择的任何地方添加JMX options并重新启动Web应用程序。

    等待锁定的线程 - 可能存在一段代码,其中有一个锁定静态字段的同步方法。如果该方法允许假设处理数据库查询大约需要5秒钟。排队等待10个请求。然后,最后一个请求将在50秒或更长时间内处理。

    如何检测这种瓶颈情况?

    您可以浏览代码并查找获取锁定的所有位置并添加一些调试日志。但是,如果问题不在您的代码中并且可能来自某些第三方库,该怎么办?

    我曾经遇到过Logger(log4j库)在日志文件翻转时会阻塞所有线程(大约10秒)的情况。通过代码审查无法检测到这种情况。

    救援人员。 VisualVM可能是检测线程锁定引起的延迟的最佳分析器。这是你可以做的。

    1. 监控线程。
    2. 当您看到许多线程处于阻塞状态时。
    3. 进行线程转储。
    4. 分析线程转储以查看导致此问题的功能并相应地解决问题。
    5. enter image description here

      CPU密集型任务 - 如果进程占用大量CPU时间,也可能导致延迟。您可以再次使用VisualVM的采样器,找出占用最多CPU时间的线程。

      希望这有助于找到延迟的原因!

答案 1 :(得分:0)

关于如何分析性能,您可以关注以下几个方面:

  1. DB
  2. 网络
  3. 申请层
  4. 内存
  5. 监视数据库是平面简单使用RDBMS监视工具,如Query Monitor for DB2或其他东西,具体取决于供应商。

    分析BNetwork,有许多不同的工具,但您需要做的是弄清楚延迟是什么以及网络速度是什么。

    我相信我们可以假设在你的情况下,网络是正常的,或者至少不是很有可能存在问题。

    要分析的第三件事是您的应用程序层,这是您需要适当的分析工具的地方。您可以使用免费的visualVM并随附jdk或者您可以使用已支付的套件。但是你可以试用版本。

    您还可以使用分析工具分析内存。

    执行 CPU采样后,您将能够确定应用程序的哪些区域导致延迟。 Yourkit还能够从Application层侧监视已执行的SQL。这样,您将获得SQL速度+执行它的延迟+传输结果集的时间。

    常见的性能调整选择是:

    休眠。对集合加载使用批处理,不要加入关系而不是FetchStrategy.SELECT。

    确保您不执行任何笛卡尔产品等。

答案 2 :(得分:0)

  

服务器配置:VPS,1 proc,4GB RAM

您是否可以访问服务器?尝试运行top命令并查看CPU使用情况。你只有一个触发器,可能还有一些巨大的触发器。

开始查找性能问题的典型方法:

条件1您可以使用探查器连接 做吧。 jvisualvm,jconsole,NetBeans Profiler,perf等。

  1. 使用分析器连接到您的流程;
  2. 运行任务,您认为这很慢并且等待;
  3. 保存分析器结果以进行分析;
  4. 您应该注意总CPU时间。

    条件2您无法连接探查器

    是的,在这里你可以使用jstack来获取线程转储。获取java进程ID的jps。

    1. 准备cmd / bash;
    2. 运行jps并找到您的进程pid,记住;
    3. 运行任务,您认为这很慢;
    4. 多次运行jstack并保存输出(jstack pid&gt; output.1,jstack pid&gt; output.2等);
    5. 分析所有结果,看看哪种方法最常见。
    6. 之前不要进行预先优化,测量性能。 :)

      更新以获取新信息后的答案。

      在线程转储中你可以看到很多“sun.nio.ch.EPollArrayWrapper.epollWait”,试着看一些链接:

      也许是你的情况。 epoll有一个bug。但是现在也发生了类似的情况。

答案 3 :(得分:0)

根据我的经验,您可能遇到数据库锁定问题。有一个sql锁定你的表一段时间。您的代码正在等待,然后锁被释放,您的代码继续。您可以monitor db lock来查找代码挂起时哪个sql锁定您的表。