• Spring Boot环境下出现No operations allowed after connection close错误


    一个基于springcloud的微服务项目,详细配置: SpringCloud + SpringMVC+SpringData JPA+ MySql+Postgresql

    其中项目配置了多数据源,前期开发测试是没什么问题的,但是等到项目在服务器上面测试时,第二天就上午出现了数据库连接异常。经过查看日志发现下面这个异常:

    注意异常信息: No operations allowed after connection closed。

    也就是说jpa获取的连接是已经关闭的了,对一个关闭了的链接进行操作导致出现异常了。

    原因:
    之所以会出现这个异常,是因为MySQL5.0以后针对超长时间DB连接做了一个处理,那就是如果一个DB连接在无任何操作情况下过了8个小时后(Mysql 服务器默认的“wait_timeout”是8小时),Mysql会自动把这个连接关闭。这就是问题的所在,在连接池中的connections如果空闲超过8小时,mysql将其断开,而连接池自己并不知道该connection已经失效,如果这时有 Client请求connection,连接池将该失效的Connection提供给Client,将会造成上面的异常。 
    所以配置datasource时需要配置相应的连接池参数,定是去检查连接的有效性,定时清理无效的连接。

    解决方法
    在application.yml的两个数据源的配置下添加如下连接池配置(红色字体部分):

    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka
    server:
      port: 9013
    spring:
      application:
        name: api
      datasource:
        druid:
          #数据库连接1
          mysql:
            name: mysql
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: com.mysql.jdbc.Driver
            url: jdbc:mysql://localhost:3306/datacube?useUnicode=true&characterEncoding=utf8&useSSL=false
            username: root
            password: rootrot
          #数据库连接2
          greenplum:
            name: greenplum
            type: com.alibaba.druid.pool.DruidDataSource
            driver-class-name: org.postgresql.Driver
            url: jdbc:postgresql://localhost:5432/datacube?useUnicode=true&characterEncoding=utf8&useSSL=false
            username: root
            password: rootroot
    
    
        # 下面为连接池的补充设置,应用到上面所有数据源中
        # 初始化大小,最小,最大
          initialSize: 5
          minIdle: 10
          maxActive: 1000
          #配置获取连接等待超时的时间
          maxWait: 60000
          #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
          timeBetweenEvictionRunsMillis: 60000
          #配置一个连接在池中最小生存的时间,单位是毫秒
          minEvictableIdleTimeMillis: 300000
          #验证连接是否有效。此参数必须设置为非空字符串,下面三项设置成true才能生效
          validationQuery: SELECT 1
          #指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.
          testWhileIdle: true
          #指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
          testOnBorrow: true
          #指明是否在归还到池中前进行检验
          testOnReturn: false
          #打开PSCache,并且指定每个连接上PSCache的大小
          poolPreparedStatements: true
          maxPoolPreparedStatementPerConnectionSize: 20
          #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
          filters: stat,wall,log4j
          #通过connectProperties属性来打开mergeSql功能;慢SQL记录
          connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000;druid.stat.logSlowSql=true
          #合并多个DruidDataSource的监控数据
          useGlobalDataSourceStat: true
    #      WebStatFilter:
    #        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
    #      stat-view-servlet:
    #       login-username: admin
    #       login-password: admin
    
    
    jpa:
       database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
       show-sql: true
       hibernate:
         #dialect: org.hibernate.dialect.MySQL5Dialect
         ddl-auto: none
         naming:
          strategy: org.hibernate.cfg.ImprovedNamingStrategy
    

      


    在这个项目中使用的是阿里的druid连接池,配置简单,除了数据库地址,驱动类,用户名和密码其他一起都是默认,开始的时候由于项目更新上线频率比较多,没有出现太多的问题,后来换库了 。导致之前的链接失效了,请求的时候时好时坏,跟了一下代码以及其他项目的配置,其中有一个属性 testOnBorrow设置为false(默认设置为false) ,testOnBorrow=false则不检测池里连接的可用性,

    于是假如连接池中的连接被数据库关闭了,应用通过连接池getConnection时,都可能获取到这些不可用的连接,且这些连接如果不被其他线程回收的话,它们不会被连接池被废除,也不会重新被创建,占用了连接池的名额,项目本身作为服务端,数据库链接被关闭,客户端调用服务端就会出现大量的timeout,客户端设置了超时时间,然而主动断开,服务端必然出现close_wait ,由于tomcat 默认最大线程数是200,很快就挂掉,虽说多数源,没有问题的数据源,链接并发过来也会死掉,所以说加大tomcat 默认线程(server.tomcat.max-threads=3000)只是短时间内其他数据源链接不会死掉。


    默认的配置不适用所有场景,所以使用的时候需要配合场景使用。

    由于testOnborrow =true 很大的消耗性能,为了保证服务器的稳定,可以配合其他配置来避免这一点,配合testWhileIdle=true(但是默认为false) 和timeBetweenEvictionRunsMillis来避免这种问题,所以设置testOnborrow =false是可以提高效率的


    原文:https://blog.csdn.net/qq_38023253/article/details/80815618

  • 相关阅读:
    Ubuntu中开启Telnet服务
    单片机串口通讯RXD与TXD如何对接详解
    KEIL, a Smart Comliler
    linux mail 命令(转载)
    VC程序在没装VC的机器中运行
    srand()以及rand()函数用法
    VC菜菜鸟:基于CFree的HelloWorld程序
    Keil使用中的若干问题(转)
    VMWARE 重新安装出错
    Linux个人学习笔记(编辑中)
  • 原文地址:https://www.cnblogs.com/chancy/p/10776079.html
Copyright © 2020-2023  润新知