一、问题描述
前段时间使用sharding-jdbc对项目进行分库分表操作,使用如下版本的依赖:
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>3.0.0.M3</version>
</dependency>
在dev和beta环境都可以正常部署及实现。但是将项目部署到preview环境时却报错了,报错信息如下:
分析定位问题
当时很疑惑为什么会报不支持jdbc的url的错误。beta和preview环境jdbc的url的区别只是换了数据库服务器的域名和数据库名。并且beta和preview环境,java和tomcat的版本都是一样的。百思不得其解,多次尝试无果后回归日志,从上往下可以看到是io.shardingsphere.core.metadata.datasource.dialect包下的MySQLDataSourceMetaData.java抛出的异常。找到该文件找到源码。源码如下:
package io.shardingsphere.core.metadata.datasource.dialect;
import com.google.common.base.Strings;
import io.shardingsphere.core.exception.ShardingException;
import io.shardingsphere.core.metadata.datasource.DataSourceMetaData;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public final class MySQLDataSourceMetaData implements DataSourceMetaData {
private static final int DEFAULT_PORT = 3306;
private final String hostName;
private final int port;
private final String schemeName;
private final Pattern pattern = Pattern.compile("jdbc:mysql://([a-zA-Z0-9\\-\\.]+):?([0-9]*)/(\\w+);?\\w*");
public MySQLDataSourceMetaData(String url) {
Matcher matcher = this.pattern.matcher(url);
if (matcher.find()) {
this.hostName = matcher.group(1);
this.port = Strings.isNullOrEmpty(matcher.group(2)) ? 3306 : Integer.valueOf(matcher.group(2));
this.schemeName = matcher.group(3);
} else {
throw new ShardingException("The URL of JDBC is not supported.", new Object[0]);
}
}
public boolean isInSameDatabaseInstance(DataSourceMetaData dataSourceMetaData) {
return this.hostName.equals(dataSourceMetaData.getHostName()) && this.port == dataSourceMetaData.getPort();
}
public String getHostName() {
return this.hostName;
}
public int getPort() {
return this.port;
}
public String getSchemeName() {
return this.schemeName;
}
public Pattern getPattern() {
return this.pattern;
}
}
通过源码可以看出应该是preview环境的jdbc的url的格式和sharding-jdbc要求的正则表达式不匹配所致。
恍然大悟,beta环境使用的jdbc的url类似如下格式:
sharding.jdbc.datasource.db1.url=jdbc:mysql://xxx-xxx.xxx.xxx:3306/xxx_xxx?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false&tinyInt1isBit=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
而preview环境使用的jdbc的url类似如下格式:
sharding.jdbc.datasource.db1.url=jdbc:mysql://xx-xx_xx_xx.xx.xx:3306/xx_xx_xx?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false&tinyInt1isBit=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
三、解决问题
通过上面的分析可以看到原来3.0.0.M3版本的shardingsphere不支持URL中数据库服务器域名中带下划线,改为3.1.0版本的问题得到解决。
3.1.0版本jdbc的url的正则表达式为:
private final Pattern pattern = Pattern.compile("jdbc:mysql:(\\w*:)?//([\\w\\-\\.]+):?([0-9]*)/([\\w\\-]+);?\\S*", 2);