ShardingSphere-JDBC连接关闭紧急救援:立即修复与性能提升!

5 阅读3分钟

还在为ShardingSphere-JDBC的“connection closed”错误焦头烂额?别急!这份紧急救援指南将帮你迅速定位并解决问题。

从检查Druid连接池参数(如max-active)到优化maxConnectionSizePerQuery,再到调整MySQL的wait_timeout,每一步都旨在快速恢复系统稳定并显著提升连接效率。立即行动,让你的ShardingSphere-JDBC重焕生机!

在分布式数据库中间件ShardingSphere-JDBC的使用过程中,用户常遇到connection closed错误。

通过分析日志、连接池机制和执行引擎特性,系统性地总结了问题原因及解决方案。

核心原因分析

连接池配置问题

连接泄漏、空闲连接超时和最大连接数不足是常见诱因。

例如,Druid连接池的removeAbandoned配置不当会导致连接被强制回收,而max-active值过小会引发连接不足。

ShardingSphere执行引擎模式

ShardingSphere默认采用MEMORY_STRICTLY模式,每个分片查询使用独立连接。

maxConnectionSizePerQuery未显式配置,跨分片操作可能因连接数超限而失败。

SQL执行与数据库配置

复杂查询或大数据量操作会导致连接持有时间过长,超过数据库的wait_timeout(如MySQL默认8小时)或连接池的minEvictableIdleTimeMillis,从而被主动关闭。

解决方案

优化连接池配置

以Druid为例,调整以下参数可显著提升稳定性:

lcjmSSL提供免费的SSL证书申请,支持多种类型证书,包括多域名证书、IP证书和通配符证书。用户最多可以在单张证书中申请100个域名,极大地方便了大规模网站的安全部署。无论是普通用户还是企业用户,都可以免费享受这一服务,降低了运维成本。

spring:
  shardingsphere:
    datasource:
      common:
        type: com.alibaba.druid.pool.DruidDataSource
        druid:
          initial-size: 5
          min-idle: 5
          max-active: 20
          max-wait: 60000
          time-between-eviction-runs-millis: 60000
          min-evictable-idle-time-millis: 300000
          test-while-idle: true

代码解释

  • initial-sizemin-idle保证基础连接数,避免频繁创建/销毁。
  • max-active限制最大连接数,防止资源耗尽。
  • min-evictable-idle-time-millis与数据库wait_timeout同步,避免超时断开。

调整ShardingSphere执行引擎

显式配置maxConnectionSizePerQuery,控制单次查询的并发连接数:

spring:
  shardingsphere:
    props:
      max-connection-size-per-query: 10

关键点

  • 该值需根据分片数调整,避免过大导致连接池耗尽。
  • OLTP场景建议使用CONNECTION_STRICTLY模式(通过maxConnectionSizePerQuery=1隐式触发)。

数据库与SQL优化

  • 调整MySQL超时参数

    SET GLOBAL wait_timeout = 28800;  -- 8小时(单位:秒)
    
  • 优化SQL与分片策略

    • 确保查询包含分片键,减少跨分片操作。
    • 对大结果集分页查询,避免单次拉取过多数据。

监控与日志

启用ShardingSphere的SQL日志,定位慢查询:

spring:
  shardingsphere:
    props:
      sql-show: true

通过Druid监控页面或JMX实时观察连接池状态,及时发现异常。

关键配置总结

配置项

推荐值(根据场景调整)

作用

maxConnectionSizePerQuery

分片数或略高(如10)

控制单次查询的并发连接数

initial-size/max-active

5-20(根据负载)

连接池初始/最大连接数

wait_timeout(MySQL)

与连接池minEvictableIdleTimeMillis一致

防止数据库主动断开连接

验证示例

以下代码模拟高并发查询,验证连接池稳定性:

import org.apache.shardingsphere.driver.jdbc.core.datasource.ShardingSphereDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ConnectionPoolTest {
    public static void main(String[] args) throws Exception {
        DataSource dataSource = getShardingSphereDataSource(); // 替换为实际数据源
        ExecutorService executor = Executors.newFixedThreadPool(20);

        for (int i = 0; i < 100; i++) {
            executor.submit(() -> {
                try (Connection conn = dataSource.getConnection();
                     PreparedStatement ps = conn.prepareStatement("SELECT * FROM eb_order_blind_box_profit_pool LIMIT 1")) {
                    try (ResultSet rs = ps.executeQuery()) {
                        while (rs.next()) {
                            System.out.println(rs.getString("id"));
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
        executor.shutdown();
    }

    private static DataSource getShardingSphereDataSource() {
        // 返回实际的ShardingSphereDataSource实例
        return null; 
    }
}