Use o pool de conexões Alibaba Druid para conectar ao LindormTable pelo endpoint compatível com MySQL.
Pré-requisitos
Antes de começar, verifique se você tem:
O recurso de compatibilidade com MySQL ativado na instância Lindorm. Consulte Ativar o recurso de compatibilidade com MySQL
JDK V1.8 ou posterior instalado
O endereço IP do cliente adicionado à lista de permissões da instância Lindorm. Consulte Configurar listas de permissões
Adicione dependências
Adicione as seguintes dependências ao arquivo pom.xml do projeto Maven:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
**Se usar druid-spring-boot-starter**, exclua o componente druid incluído e declare a dependência do druid explicitamente:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.11</version>
<exclusions>
<exclusion>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.11</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.3.0</version>
</dependency>
Configure o pool de conexões
No diretório src/main/resources do projeto Maven, crie o arquivo druid.properties com o seguinte conteúdo:
# Driver class — keep this unchanged.
driverClassName=com.mysql.cj.jdbc.Driver
# Replace <endpoint> with your LindormTable endpoint for MySQL and <database> with your database name.
# To get the endpoint, see View endpoints: https://www.alibabacloud.com/help/en/lindorm/user-guide/view-endpoints
# Keep the other URL parameters unchanged to maintain optimal performance.
url=jdbc:mysql://<endpoint>:33060/<database>?sslMode=disabled&allowPublicKeyRetrieval=true&useServerPrepStmts=true&useLocalSessionState=true&rewriteBatchedStatements=true&cachePrepStmts=true&prepStmtCacheSize=100&prepStmtCacheSqlLimit=50000000&socketTimeout=120000
username=<username>
password=<password>
# Initialize the connection pool on startup — keep this unchanged.
init=true
# Number of connections to create during initialization.
initialSize=10
# Maximum number of connections in the pool. Set this to match your thread pool size.
maxActive=40
# Minimum number of idle connections. For high-throughput scenarios, set this equal to maxActive.
# For workloads with large fluctuations, use a smaller value.
minIdle=40
# Maximum time (ms) the client waits to get a connection — keep this unchanged.
maxWait=30000
# Limits how many times a single connection can be reused, preventing uneven load
# across Lindorm SQL frontend nodes. Has a minor performance impact.
phyMaxUseCount=30000
# Keep-alive settings — keep these unchanged to prevent unexpected disconnections.
druid.keepAlive=true
# If a connection has been idle for longer than this value (ms), its validity is checked.
druid.keepAliveBetweenTimeMillis=120000
# Interval (ms) at which idle connections are checked for eviction or keep-alive.
timeBetweenEvictionRunsMillis=60000
# Connections idle for longer than this value (ms) are candidates for eviction.
minEvictableIdleTimeMillis=1800000
maxEvictableIdleTimeMillis=1800000
# Connection validation settings — keep these unchanged.
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
Parâmetros de conexão
| Parâmetro | Descrição |
|---|---|
url |
URL de conexão JDBC. Formato: jdbc:mysql://<endpoint do LindormTable para MySQL>/<nome do banco de dados>?<configurações de conexão>. Se omitir o nome do banco de dados, o cliente conectará ao banco de dados padrão. Para obter detalhes sobre todas as configurações de conexão, consulte Configurações de conexão. |
username |
Nome de usuário do LindormTable. Se esquecer a senha, redefina-a no sistema de gerenciamento de cluster do LindormTable. Consulte Alterar a senha de um usuário. |
password |
Se a aplicação executar em uma instância Elastic Compute Service (ECS), use uma conexão de virtual private cloud (VPC) para obter menor latência e maior segurança. Especifique o endpoint VPC do LindormTable para MySQL no parâmetro
url.Se a aplicação conectar pela Internet, ative o endpoint público no console Lindorm: acesse Database Connections > Wide Table Engine e clique em Enable Public Endpoint na aba Wide Table Engine. Em seguida, especifique o endpoint de Internet do LindormTable para MySQL no parâmetro
url.
Dimensione o pool de conexões
Os nós de front-end do Lindorm SQL usam o Server Load Balancer (SLB) para balanceamento de carga. Evite manter conexões abertas por longos períodos para distribuir as solicitações uniformemente. Configure phyMaxUseCount para limitar a reutilização de conexões.
Defina
maxActiveigual ao tamanho do pool de threads da aplicação.Para cargas de trabalho com alto throughput e sensíveis à latência, defina
minIdleigual amaxActivepara garantir que as conexões estejam sempre prontas.Em cenários com flutuações significativas de tráfego, use um valor menor para
minIdlepara reduzir o consumo de recursos ociosos.
Inicialize o pool de conexões
Carregue o arquivo de configuração e crie a fonte de dados:
// Load configuration from druid.properties.
Properties properties = new Properties();
InputStream inputStream = DruidPoolDemo.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(inputStream);
// Initialize the connection pool.
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
Execute operações CRUD
Todos os exemplos obtêm uma conexão do pool e a devolvem automaticamente usando try-with-resources. Se não usar try-with-resources, chame conn.close() explicitamente. Isso devolve a conexão ao pool, mas não a fecha. Se uma conexão tornar-se inválida sem ser devolvida, o Druid não detectará o estado inválido.
String tableName = "sql_table_" + new Random().nextInt(1000);
// Create a table.
try (Connection connection = dataSource.getConnection()) {
try (Statement statement = connection.createStatement()) {
String sql = "create table if not exists " + tableName + "(id VARCHAR, name VARCHAR, primary key(id))";
int ret = statement.executeUpdate(sql);
System.out.println(ret);
}
}
// Insert a single row.
try (Connection connection = dataSource.getConnection()) {
String sql = "insert into " + tableName + "(id,name) values(?,?)";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ps.setString(2, "bb");
int ret = ps.executeUpdate();
System.out.println(ret);
}
}
// Batch insert.
String insertSql = "insert into " + tableName + "(id,name) values(?,?)";
int batchSize = 100;
try (Connection connection = dataSource.getConnection()) {
try (PreparedStatement ps = connection.prepareStatement(insertSql)) {
for (int i = 0; i < batchSize; i++) {
ps.setString(1, "aa" + i);
ps.setString(2, "bb" + i);
ps.addBatch();
}
ps.executeBatch();
}
}
// Query data.
try (Connection connection = dataSource.getConnection()) {
String sql = "select * from " + tableName + " where id=?";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
String id = rs.getString(1);
String name = rs.getString(2);
System.out.println("id=" + id);
System.out.println("name=" + name);
}
}
}
// Delete data.
try (Connection connection = dataSource.getConnection()) {
String sql = "delete from " + tableName + " where id=?";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, "aa");
ps.executeUpdate();
}
}
No Lindorm SQL,
INSERTequivale aUPSERT. O cliente JDBC MySQL é otimizado paraINSERT, portanto use a sintaxeINSERTao gravar dados.Mantenha o
batchSizeentre 50 e 100. Lotes maiores podem causar erros de falta de memória (OOM) ou Full GC no servidor.Para aumentar ainda mais o throughput de gravação, eleve a concorrência de escrita.
Considerações para produção
Lidar com interrupções de conexão
Em ambientes de rede complexos, interrupções de conexão podem ocorrer devido a gargalos de gateway, instabilidade na rede ou alta perda de pacotes. As configurações de keep-alive em druid.properties ajudam a manter conexões ociosas, mas implemente também um mecanismo de nova tentativa no código da aplicação para falhas transitórias.
Durante atualizações e reinicializações do servidor, as conexões ativas podem sofrer interrupções temporárias. Capture as exceções e tente executar a operação novamente.
Monitorar o pool de conexões
Verifique periodicamente as configurações efetivas e as estatísticas do pool de conexões. Confira também as configurações nos logs:
druidDataSource.getStatData(); // Returns current pool statistics
druidDataSource.dump(); // Logs detailed pool configuration and state
Perguntas frequentes
**Por que minha aplicação lança a exceção Read timed out?**
O tempo limite padrão de socket no Druid é de 10 segundos. Se uma consulta demorar mais que isso, a conexão expira e gera esse erro. Defina socketTimeout em milissegundos na URL JDBC. O valor recomendado é 120000 (2 minutos):
jdbc:mysql://<endpoint>:33060/<database>?sslMode=disabled&allowPublicKeyRetrieval=true&useServerPrepStmts=true&useLocalSessionState=true&rewriteBatchedStatements=true&cachePrepStmts=true&prepStmtCacheSize=100&prepStmtCacheSqlLimit=50000000&socketTimeout=120000