服务进程中的服务方法blpop阻塞在redis队列下(等待请求), 使用方(客户代码)向该队列push请求以促使服务方法在阻塞的代码行继续运行下去。
服务方法使用了mybatis的SqlSessionTemplate, 在进入服务方法时spring为mybatis调用了连接池druid的getConnection,
假设很久没有请求来,一直阻塞在blpop处,直到mysql的wait_timeout默认8小时到达(导致mysql实际上已经关闭了该连接),
而此时处在方法内部, 一旦有请求来,代码从阻塞处继续运行,没有机会促使spring调用一次连接池的getConnection,从而没有机会使得连接池获知该连接已无效,而导致使用了一个无效的连接。
但下一次再进入服务方法,又正常了,直到再次超过8小时没有请求过来,又这样。
问题简述:使用了mysql连接的方法执行时间超过了8个小时,导致mysql关闭了连接,而方法复活的时候不知道连接已经关闭了。
根结是应用代码的结构不良。
应该改为: 将服务方法分为两个方法:一个等待请求,一个用请求来执行服务逻辑。 等待请求的方法会阻塞,但不需要spring去切入。 执行服务的方法一旦运行不会阻塞(执行所需时间很短),spring对该方法切入了连接池的getConnection。
时间: 2024-10-29 19:08:13