tomcat并发请求优化,hibernate数据库查询瓶颈,Mysql数据库优化

最近有个项目,需要有大量的Tomcat并发,之前对这方面了解不多,因此进行了深入研究,总结一下心得。希望对大家也有些帮助!

首先,遇到第一个问题:

三月 07, 2019 6:37:46 下午 org.apache.tomcat.util.net.NioEndpoint$Acceptor run
严重: Socket accept failed
java.io.IOException: 打开的文件过多
    at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
    at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:250)
    at org.apache.tomcat.util.net.NioEndpoint$Acceptor.run(NioEndpoint.java:1316)
    at java.lang.Thread.run(Thread.java:745)

这个问题,网上有很多解答,主要都是关于修改Linux底层文件句柄的最大上限的,但是实际上,要根据自己的项目分析为什么文件打开过多。当时针对这问题,做了如下三个改动:

      1、修改Linux底层文件句柄

     【原因】:系统(Centos 7.3)默认最大打开文件句柄为1024,我需要并发远大于这个数量级,因此调高次参数

     【方法】:

        /etc/security/limits.conf文件End file 前增加以下两行,重启系统
        * soft nofile 65536
        * hard nofile 65536

        确认修改是否成功 ulimit -a

       

     2、排查代码中未关闭的文件流,网络IO流

     【原因】:每个打开文件流、网络IO流,如socket之类的,都需要消耗文件句柄,如果不关闭,则会造成泄漏

     【方法】:

       finally里面关闭所有socket、文件流,不详细展开

       监控文件句柄数:

       lsof -p 29023 查看线程29023打开的文件句柄详细情况

       lsof -p 29023 | wc -l 统计线程29023打开句柄数量

      3、快速释放tomcat闲置连接

     【原因】:怀疑Tomcat连接一直未释放连接,是否有效未独立验证

     【方法】:修改tomcat连接超时时间,connectionTimeout="10000" 10s(依据项目具体情况而定)


华丽分隔线

第二个问题:Mysql 出现问题:

Caused by: java.sql.SQLException: Too many active concurrent transactions
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:965)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3976)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3912)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2530)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2683)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2486)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1858)
    at com.mysql.jdbc.PreparedStatement.executeUpdateInternal(PreparedStatement.java:2079)
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1756)

这个问题,还真是Mysql的bug,吓我一跳,说是mysql 5.1 同时启动的事务最多1023个,mysql 5.5才修复这个问题。一想到要把整个系统的mysql版本都更换了,内心一顿烦躁。

https://bugs.mysql.com/bug.php?id=26590

晚上回去仔细思考了一下,虽然是并发但是我并没有启动事务,仅仅是用hibernate update方法啊,为啥会引发这个错误呢?

后来,把1个多g的日志重新拿出来check一下,果然在大量的这个错误前,还隐藏了一个少量的错误,请继续往下看


华丽分隔线

第三个问题:c3p0连接池取不到数据库连接

Caused by: com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool@63577d06 -- timeout at awaitAvailable()
    at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1317)
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557)
    at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477)
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525)
    ... 45 more

【原因】:我们后台是servlet去接收并发消息的,servlet是单例多线程的,也就是大量并发过来时,是多个线程同时处理,数据库也是同时操作,监控数据库的连接数,show status like "%Thread%";当并发一产生时,立刻达到c3p0的连接数,<property name="maxPoolSize" value="650"/>

【方法】:

<property name="maxIdleTime" value="30"/> 大大减少获取不到连接的概率(只有重启网关的时候才会有错误,过30+s后连接数正常恢复,长时间未测试过)

<prop key="hibernate.connection.release_mode">after_transaction</prop> 该修改项对性能有优化,能减少获取不到连接的概率,但影响功能,代码回退,建议大家根据自己的系统确认下是否按照这个配置优化


华丽分隔线

前三步之后,出现连接取不到的概率大大减少,但偶尔也会产生

【方法】:代码修改,生产者消费者方式,后台处理servlet时候,启动队列,后台定时消费队列。

 

改完之后,没有再出过错误,数据库连接也不会疯涨了,Close

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值