springboot项目中,用atomikos做的多数据源配置,某一个数据库,白天的时候访问非常慢,深夜访问就正常?
项目连接了3个数据库,分别是 base1,base2,base3;
base1,base2白天晚上访问都正常;
base3,白天访问大部分都是超时,偶尔能通,还非常慢,到了晚上就可以正常访问了;
三个数据库数据结构,接口配置一模一样,只是用来区分不同的国家而已;
因为做了实时大屏看板,所以会频繁的请求该项目,并且会不停的切换数据源;会不会是数据源的通用配置有点小了?
数据源的通用配置如下:
<bean id="dataSourceConfig" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" abstract="true"> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
<property name="poolSize" value="10"/>
<property name="maxPoolSize" value="20"/>
<property name="minPoolSize" value="5"/>
<property name="maxIdleTime" value="5"/>
<property name="maxLifetime" value="60"/>
<property name="borrowConnectionTimeout" value="60"/>
<property name="testQuery" value="SELECT 'x' from dual"/>
<property name="isLoad" value="${datasource.loadDB.haier}" />
</bean>
AtomikosDataSourceBean代码如下
/** * Copyright (C) 2000-2013 Atomikos <info@atomikos.com>
*
* This code ("Atomikos TransactionsEssentials"), by itself,
* is being distributed under the
* Apache License, Version 2.0 ("License"), a copy of which may be found at
* http://www.atomikos.com/licenses/apache-license-2.0.txt .
* You may not use this file except in compliance with the License.
*
* While the License grants certain patent license rights,
* those patent license rights only extend to the use of
* Atomikos TransactionsEssentials by itself.
*
* This code (Atomikos TransactionsEssentials) contains certain interfaces
* in package (namespace) com.atomikos.icatch
* (including com.atomikos.icatch.Participant) which, if implemented, may
* infringe one or more patents held by Atomikos.
* It should be appreciated that you may NOT implement such interfaces;
* licensing to implement these interfaces must be obtained separately from Atomikos.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/
package com.atomikos.jdbc;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.sql.XADataSource;
import com.atomikos.beans.PropertyUtils;
import com.atomikos.datasource.RecoverableResource;
import com.atomikos.datasource.xa.jdbc.JdbcTransactionalResource;
import com.atomikos.icatch.system.Configuration;
import com.atomikos.logging.Logger;
import com.atomikos.logging.LoggerFactory;
import com.atomikos.util.ClassLoadingHelper;
/**
* The preferred class for using Atomikos connection pooling. Use an instance of
* this class if you want to use Atomikos JTA-enabled connection pooling. All
* you need to do is construct an instance and set the required properties as
* outlined below. The resulting bean will automatically register with the
* transaction service (for recovery) and take part in active transactions.
* All SQL done over connections (gotten from this class) will participate in JTA transactions.
*/
public class AtomikosDataSourceBean
extends AbstractDataSourceBean
{
private static final Logger LOGGER = LoggerFactory.createLogger(AtomikosDataSourceBean.class);
private static final long serialVersionUID = 1L;
private Properties xaProperties = null;
private String xaDataSourceClassName;
private transient XADataSource xaDataSource;
public AtomikosDataSourceBean()
{
this.xaProperties = new Properties();
}
protected String printXaProperties()
{
StringBuffer ret = new StringBuffer();
if ( xaProperties != null ) {
Enumeration it = xaProperties.propertyNames();
ret.append ( "[" );
boolean first = true;
while ( it.hasMoreElements() ) {
if ( ! first ) ret.append ( "," );
String name = ( String ) it.nextElement();
String value = xaProperties.getProperty( name);
ret.append ( name ); ret.append ( "=" ); ret.append ( value );
first = false;
}
ret.append ( "]" );
}
return ret.toString();
}
/**
* Gets the properties used to
* configure the XADataSource.
*/
public Properties getXaProperties()
{
return xaProperties;
}
/**
* Sets the properties (name,value pairs) used to
* configure the XADataSource. Required, unless you call setXaDataSource directly.
*
* @param xaProperties
*
*
*/
public void setXaProperties ( Properties xaProperties )
{
this.xaProperties = xaProperties;
Map<String,String> db = new HashMap<String,String>();
db.put("url", xaProperties.getProperty("URL"));
db.put("user", xaProperties.getProperty("user"));
db.put("password", xaProperties.getProperty("password"));
//将子类的数据库信息传给父类使用
super.dbInfo = db;
}
/**
* Get the XADataSource class name.
*/
public String getXaDataSourceClassName()
{
return xaDataSourceClassName;
}
/**
* Sets the fully qualified underlying XADataSource class name. Required, unless you
* call setXaDataSource directly.
*
* @param xaDataSourceClassName
*/
public void setXaDataSourceClassName ( String xaDataSourceClassName )
{
this.xaDataSourceClassName = xaDataSourceClassName;
}
/**
* Gets the configured XADataSource (if any).
* @return The instance, or null if none.
*/
public XADataSource getXaDataSource()
{
return xaDataSource;
}
/**
* Sets the XADataSource directly - instead of providing the xaDataSourceClassName and xaProperties.
* @param xaDataSource
*/
public void setXaDataSource(XADataSource xaDataSource)
{
this.xaDataSource = xaDataSource;
}
protected com.atomikos.datasource.pool.ConnectionFactory doInit() throws Exception
{
if (xaDataSource == null)
{
if (xaDataSourceClassName == null)
throwAtomikosSQLException("Property 'xaDataSourceClassName' cannot be null");
if (xaProperties == null)
throwAtomikosSQLException("Property 'xaProperties' cannot be null");
}
if ( LOGGER.isInfoEnabled() ) LOGGER.logInfo(
this + ": initializing with [" +
" xaDataSourceClassName=" + xaDataSourceClassName + "," +
" uniqueResourceName=" + getUniqueResourceName() + "," +
" maxPoolSize=" + getMaxPoolSize() + "," +
" minPoolSize=" + getMinPoolSize() + "," +
" borrowConnectionTimeout=" + getBorrowConnectionTimeout() + "," +
" maxIdleTime=" + getMaxIdleTime() + "," +
" reapTimeout=" + getReapTimeout() + "," +
" maintenanceInterval=" + getMaintenanceInterval() + "," +
" testQuery=" + getTestQuery() + "," +
" xaProperties=" + printXaProperties() + "," +
" loginTimeout=" + getLoginTimeout() + "," +
" maxLifetime=" + getMaxLifetime() +
"]"
);
if (xaDataSource == null)
{
Class xadsClass = null;
try {
xadsClass = ClassLoadingHelper.loadClass ( getXaDataSourceClassName() );
} catch ( ClassNotFoundException nf ) {
AtomikosSQLException.throwAtomikosSQLException ( "The class '" + getXaDataSourceClassName() +
"' specified by property 'xaDataSourceClassName' could not be found in the classpath. Please make sure the spelling is correct, and that the required jar(s) are in the classpath." , nf );
}
Object driver = xadsClass.newInstance();
if ( ! ( driver instanceof XADataSource ) ) {
AtomikosSQLException.throwAtomikosSQLException (
"The class '" + getXaDataSourceClassName() +
"' specified by property 'xaDataSourceClassName' does not implement the required interface javax.jdbc.XADataSource. Please make sure the spelling is correct, and check your JDBC driver vendor's documentation."
);
}
xaDataSource = (XADataSource) driver;
xaDataSource.setLoginTimeout ( getLoginTimeout() );
xaDataSource.setLogWriter ( getLogWriter() );
PropertyUtils.setProperties(xaDataSource, xaProperties );
}
JdbcTransactionalResource tr = new JdbcTransactionalResource(getUniqueResourceName() , xaDataSource);
com.atomikos.datasource.pool.ConnectionFactory cf = new com.atomikos.jdbc.AtomikosXAConnectionFactory(xaDataSource, tr, this);
Configuration.addResource ( tr );
return cf;
}
protected void doClose()
{
RecoverableResource res = Configuration.getResource ( getUniqueResourceName() );
if ( res != null ) {
Configuration.removeResource ( getUniqueResourceName() );
//fix for case 26005
res.close();
}
}
public String toString()
{
String ret = "AtomikosDataSoureBean";
String name = getUniqueResourceName();
if ( name != null ) {
ret = ret + " '" + name + "'";
}
return ret;
}
protected boolean isAssignableFromWrappedVendorClass(Class<?> iface) {
boolean ret = false;
if (xaDataSource != null ) {
ret = iface.isAssignableFrom(xaDataSource.getClass());
}
return ret;
}
@Override
protected Object unwrapVendorInstance() {
return xaDataSource;
}
}
AbstractDataSourceBean代码如下
/** * Copyright (C) 2000-2010 Atomikos <info@atomikos.com>
*
* This code ("Atomikos TransactionsEssentials"), by itself,
* is being distributed under the
* Apache License, Version 2.0 ("License"), a copy of which may be found at
* http://www.atomikos.com/licenses/apache-license-2.0.txt .
* You may not use this file except in compliance with the License.
*
* While the License grants certain patent license rights,
* those patent license rights only extend to the use of
* Atomikos TransactionsEssentials by itself.
*
* This code (Atomikos TransactionsEssentials) contains certain interfaces
* in package (namespace) com.atomikos.icatch
* (including com.atomikos.icatch.Participant) which, if implemented, may
* infringe one or more patents held by Atomikos.
* It should be appreciated that you may NOT implement such interfaces;
* licensing to implement these interfaces must be obtained separately from Atomikos.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/
package com.atomikos.jdbc;
import java.io.PrintWriter;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Map;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.fastjson.JSON;
import com.atomikos.datasource.pool.ConnectionFactory;
import com.atomikos.datasource.pool.ConnectionPool;
import com.atomikos.datasource.pool.ConnectionPoolException;
import com.atomikos.datasource.pool.ConnectionPoolProperties;
import com.atomikos.datasource.pool.CreateConnectionException;
import com.atomikos.datasource.pool.PoolExhaustedException;
import com.atomikos.icatch.HeuristicMessage;
import com.atomikos.icatch.StringHeuristicMessage;
import com.atomikos.logging.Logger;
import com.atomikos.logging.LoggerFactory;
import com.atomikos.util.IntraVmObjectFactory;
import com.atomikos.util.IntraVmObjectRegistry;
/**
*
*
* Abstract data source bean with generic functionality.
*
*
*/
public abstract class AbstractDataSourceBean
implements HeuristicDataSource, ConnectionPoolProperties, Referenceable, Serializable
{
private static final Logger LOGGER = LoggerFactory.createLogger(AbstractDataSourceBean.class);
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(AbstractDataSourceBean.class);
static final int DEFAULT_ISOLATION_LEVEL_UNSET = -1;
static final int DEFAULT_POOL_SIZE = 1;
private int minPoolSize = DEFAULT_POOL_SIZE;
private int maxPoolSize = DEFAULT_POOL_SIZE;
private int borrowConnectionTimeout = 30;
private int reapTimeout = 0;
private int maxIdleTime = 60;
private String testQuery;
private int maintenanceInterval = 60;
private int loginTimeout;
private transient ConnectionPool connectionPool;
private transient PrintWriter logWriter;
private String resourceName;
protected Map<String,String> dbInfo;
private String isLoad;//记录该数据库是否需要加载
private int defaultIsolationLevel = DEFAULT_ISOLATION_LEVEL_UNSET;
private int maxLifetime;
protected void throwAtomikosSQLException ( String msg ) throws AtomikosSQLException
{
throwAtomikosSQLException ( msg , null );
}
protected void throwAtomikosSQLException ( String msg , Throwable cause ) throws AtomikosSQLException
{
AtomikosSQLException.throwAtomikosSQLException ( msg , cause );
}
/**
* Gets the minimum size of the pool.
*/
public int getMinPoolSize() {
return minPoolSize;
}
/**
* Sets the minimum pool size. The amount of pooled connections won't go
* below that value. The pool will open this amount of connections during
* initialization. Optional, defaults to 1.
*
* @param minPoolSize
*/
public void setMinPoolSize(int minPoolSize) {
this.minPoolSize = minPoolSize;
}
/**
* Get the maximum pool size.
*/
public int getMaxPoolSize() {
return maxPoolSize;
}
/**
* Sets the maximum pool size. The amount of pooled connections won't go
* above this value. Optional, defaults to 1.
*
* @param maxPoolSize
*/
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
/**
* Sets both the minimal and maximal pool size.
* Required if the maxPoolSize is not set. Overrides any minPoolSize
* or maxPoolSize settings you might have configured before!
*/
public void setPoolSize(int poolSize) {
this.minPoolSize = poolSize;
this.maxPoolSize = poolSize;
}
/**
* Get the maximum amount of time in seconds the pool will block
* waiting for a connection to become available in the pool when it
* is empty.
*/
public int getBorrowConnectionTimeout() {
return borrowConnectionTimeout;
}
/**
* Sets the maximum amount of time in seconds the pool will block
* waiting for a connection to become available in the pool when it
* is empty. Optional.
*
* @param borrowConnectionTimeout The time in seconds. Zero or negative means no waiting at all.
* Defaults to 30 seconds.
*/
public void setBorrowConnectionTimeout(int borrowConnectionTimeout) {
this.borrowConnectionTimeout = borrowConnectionTimeout;
}
/**
* Get the amount of time in seconds the connection pool will allow a connection
* to be borrowed before claiming it back.
*/
public int getReapTimeout() {
return reapTimeout;
}
/**
* Sets the amount of time (in seconds) that the connection pool will allow a connection
* to be in use, before claiming it back. Optional.
*
* @param reapTimeout The timeout in seconds. Zero means unlimited. Note that this value is
* only an indication; the pool will check regularly as indicated by the maintenanceInteval property.
* Default is 0 (no timeout).
*/
public void setReapTimeout(int reapTimeout) {
this.reapTimeout = reapTimeout;
}
/**
* Sets the maintenance interval for the pool maintenance thread.
* Optional.
*
* @param maintenanceInterval The interval in seconds. If not set or not positive then the pool's default (60 secs) will be used.
*/
public void setMaintenanceInterval(int maintenanceInterval) {
this.maintenanceInterval = maintenanceInterval;
}
/**
* Gets the maintenance interval as set.
*/
public int getMaintenanceInterval() {
return this.maintenanceInterval;
}
/**
* Gets the maximum amount of time in seconds a connection can stay in the pool
* before being eligible for being closed during pool shrinking.
*/
public int getMaxIdleTime() {
return maxIdleTime;
}
/**
* Sets the maximum amount of seconds that unused excess connections should stay in the pool. Optional.
*
* Note: excess connections are connections that are created above the minPoolSize limit.
*
* @param maxIdleTime The preferred idle time for unused excess connections. Note that this value is
* only an indication; the pool will check regularly as indicated by the maintenanceInteval property.
* The default is 60 seconds.
*/
public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
}
/**
* Sets the maximum amount of seconds that a connection is kept in the pool before
* it is destroyed automatically. Optional, defaults to 0 (no limit).
* @param maxLifetime
*/
public void setMaxLifetime(int maxLifetime) {
this.maxLifetime = maxLifetime;
}
/**
* Gets the maximum lifetime in seconds.
*
*/
public int getMaxLifetime() {
return maxLifetime;
}
/**
* Gets the SQL query used to test a connection before returning it.
*/
public String getTestQuery() {
return testQuery;
}
/**
* Sets the SQL query or statement used to validate a connection before returning it. Optional.
*
* @param testQuery - The SQL query or statement to validate the connection with. Note that
* although you can specify updates here, these will NOT be part of any JTA transaction!
*/
public void setTestQuery(String testQuery) {
this.testQuery = testQuery;
}
public int poolAvailableSize() {
return connectionPool.availableSize();
}
public int poolTotalSize() {
return connectionPool.totalSize();
}
public PrintWriter getLogWriter() throws SQLException {
return logWriter;
}
public int getLoginTimeout() throws SQLException {
return loginTimeout;
}
public void setLogWriter(PrintWriter out) throws SQLException {
this.logWriter = out;
}
public void setLoginTimeout(int seconds) throws SQLException {
this.loginTimeout = seconds;
}
public synchronized void init() throws AtomikosSQLException
{
/*2021年3月29日13:37:03增加动态加载数据源,来适配Romania和国内工厂一套代码,通过isLoad属性指定加载 */
if(StringUtils.isBlank(this.isLoad) || "false".equals(this.isLoad)) {
log.info("[{}]数据源加载配置为[{}],跳过加载",this.resourceName,this.isLoad);
return;
}else {
log.info("[{}]数据源加载配置为[{}],正常加载",this.resourceName,this.isLoad);
}
if ( LOGGER.isInfoEnabled() ) {
LOGGER.logInfo ( this + ": init..." );
}
//目前连接池存在连接
if (connectionPool != null) {
log.info("connectionPool不为null,存在连接");
LOGGER.logInfo("测试log日志是否打印1");
return;
}else {
log.info("connectionPool为null,不存在连接");
LOGGER.logInfo("测试log日志是否打印2");
//数据库名称
String dbName = this.resourceName;
String driver="com.mysql.jdbc.Driver";//获取mysql数据库的驱动类
Connection conn = null;
try {
Class.forName(driver);
LOGGER.logInfo("dbInfo信息:"+dbInfo.toString());
long startTime = System.currentTimeMillis();
conn = DriverManager.getConnection(dbInfo.get("url")+"&connectTimeout=10000",dbInfo.get("user"),dbInfo.get("password"));
long endTime = System.currentTimeMillis();
log.info("conn run time(毫秒):"+(endTime - startTime));
if(conn != null) {
if(conn.isClosed()) {
log.error("[{}]数据库连接检测异常:[{}]",dbName,JSON.toJSONString(dbInfo));
LOGGER.logInfo("数据库连接检测异常1");
return;//假如打不开数据库链接则跳过初始化数据库
}else {
LOGGER.logInfo("数据库连接检测正常1");
//说明数据库可以正常连接,关闭测试连接
conn.close();
log.info("[{}]数据库连接检测正常",dbName);
}
}else {
LOGGER.logInfo("数据库连接检测异常2");
log.error("[{}]数据库连接检测异常:[{}]",dbName,JSON.toJSONString(dbInfo));
return;
}
} catch (SQLException e) {
LOGGER.logInfo("数据库连接检测异常3");
log.error("[{}]数据库连接检测异常:[{}]",dbName,JSON.toJSONString(dbInfo),e);
//出现异常则跳过初始化数据库
return;
} catch (ClassNotFoundException e) {
log.error("未找到数据库驱动[{}]",driver,e);
//出现异常则跳过初始化数据库
return;
}finally {
if(null != conn) {
try {
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
}
if ( maxPoolSize < 1 ) {
throwAtomikosSQLException("Property 'maxPoolSize' must be greater than 0, was: " + maxPoolSize);
}
if ( minPoolSize < 0 || minPoolSize > maxPoolSize ) {
throwAtomikosSQLException("Property 'minPoolSize' must be at least 0 and at most maxPoolSize, was: " + minPoolSize);
}
if ( getUniqueResourceName() == null ) {
throwAtomikosSQLException("Property 'uniqueResourceName' cannot be null");
}
if ( getTestQuery() != null ) {
LOGGER.logWarning(this + ": testQuery set - pool may be slower / you might want to consider setting maxLifetime instead...");
}
if ( getMinPoolSize() == DEFAULT_POOL_SIZE ) {
LOGGER.logWarning ( this + ": poolSize equals default - this may cause performance problems!" );
}
try {
//initialize JNDI infrastructure for lookup
getReference();
ConnectionFactory cf = doInit();
connectionPool = new ConnectionPool(cf, this);
} catch ( AtomikosSQLException e ) {
//these are logged at creation time -> just rethrow
throw e;
} catch ( Exception ex) {
String msg = "Cannot initialize AtomikosDataSourceBean";
AtomikosSQLException.throwAtomikosSQLException ( msg , ex );
}
if ( LOGGER.isDebugEnabled() ) {
LOGGER.logDebug ( this + ": init done." );
}
}
public void close()
{
if ( LOGGER.isInfoEnabled() ) {
LOGGER.logInfo ( this + ": close..." );
}
if (connectionPool != null) {
connectionPool.destroy();
}
connectionPool = null;
doClose();
try {
IntraVmObjectRegistry.removeResource ( getUniqueResourceName() );
} catch ( NameNotFoundException e ) {
//ignore but log
if ( LOGGER.isDebugEnabled() ) {
LOGGER.logDebug ( this + ": Error removing from JNDI" , e );
}
}
if ( LOGGER.isDebugEnabled() ) {
LOGGER.logDebug ( this + ": close done." );
}
}
protected abstract ConnectionFactory doInit() throws Exception;
protected abstract void doClose();
/* DataSource impl */
public Connection getConnection ( HeuristicMessage msg ) throws SQLException
{
if ( LOGGER.isInfoEnabled() ) {
LOGGER.logInfo ( this + ": getConnection ( " + msg + " )..." );
}
Connection connection = null;
long startTime = System.currentTimeMillis();
init();
long endTime = System.currentTimeMillis();
log.info("getConnection run time(毫秒):"+(endTime - startTime));
try {
connection = (Connection) connectionPool.borrowConnection ( msg );
} catch (CreateConnectionException ex) {
throwAtomikosSQLException("Failed to grow the connection pool", ex);
} catch (PoolExhaustedException e) {
throwAtomikosSQLException ("Connection pool exhausted - try increasing 'maxPoolSize' and/or 'borrowConnectionTimeout' on the DataSourceBean.");
} catch (ConnectionPoolException e) {
throwAtomikosSQLException("Error borrowing connection", e );
}
if ( LOGGER.isDebugEnabled() ) {
LOGGER.logDebug ( this + ": returning " + connection );
}
return connection;
}
public Connection getConnection(String username, String password) throws SQLException
{
LOGGER.logWarning ( this + ": getConnection ( user , password ) ignores authentication - returning default connection" );
return getConnection();
}
/**
* Get the resource name.
*/
public String getUniqueResourceName() {
return resourceName;
}
/**
* Sets the resource name. Required.
*
* @param resourceName An arbitrary user-specified value that identifies
* this datasource. It must be unique for recovery purposes.
*/
public void setUniqueResourceName(String resourceName) {
this.resourceName = resourceName;
}
/**
* Tests whether local transactions are allowed - defaults to true
* for JDBC. This property is used by the pooling mechanism.
*/
public boolean getLocalTransactionMode() {
return true;
}
public Reference getReference() throws NamingException
{
return IntraVmObjectFactory.createReference ( this , getUniqueResourceName() );
}
public Connection getConnection() throws SQLException
{
StringHeuristicMessage m = null;
return getConnection ( m );
}
public Connection getConnection ( String msg ) throws SQLException
{
return getConnection ( new StringHeuristicMessage ( msg ) );
}
public Connection getConnection ( String user , String passwd , String msg )
throws SQLException
{
LOGGER.logWarning ( this + ": getConnection ( user , password , msg ) ignores authentication - returning default connection" );
return getConnection ( msg );
}
public Connection getConnection ( String user , String passwd ,
HeuristicMessage msg ) throws SQLException
{
LOGGER.logWarning ( this + ": getConnection ( user , password , msg ) ignores authentication - returning default connection" );
return getConnection ( msg );
}
/**
* Sets the default isolation level of connections returned by this datasource.
* Optional, defaults to the vendor-specific JDBC or DBMS settings.
*
* @param defaultIsolationLevel The default isolation level.
* Negative values are ignored and result in vendor-specific JDBC driver or DBMS internal defaults.
*/
public void setDefaultIsolationLevel(int defaultIsolationLevel) {
this.defaultIsolationLevel = defaultIsolationLevel;
}
/**
* Gets the default isolation level for connections created by this datasource.
*
* @return The default isolation level, or -1 if no specific value was set.
*
*/
public int getDefaultIsolationLevel() {
return defaultIsolationLevel;
}
public boolean isWrapperFor(Class<?> iface) {
return isAssignableFromThisClass(iface) || isAssignableFromWrappedVendorClass(iface);
}
protected abstract boolean isAssignableFromWrappedVendorClass(Class<?> iface);
private boolean isAssignableFromThisClass(Class<?> iface) {
return iface.isAssignableFrom(getClass());
}
public <T> T unwrap(Class<T> iface) throws SQLException {
if (isAssignableFromThisClass(iface)) {
return (T) this;
} else if (isAssignableFromWrappedVendorClass(iface)) {
return (T) unwrapVendorInstance();
}
throw new SQLException("Not a wrapper for class: " + iface);
}
protected abstract Object unwrapVendorInstance();
/**
* JDK 1.7 requirement.
*
* @throws SQLFeatureNotSupportedException
*/
public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
throw new SQLFeatureNotSupportedException();
}
/**
* Refreshes all available connections in the pool.
*/
public void refreshPool() {
if (connectionPool != null) {
connectionPool.refresh();
}
}
public String getIsLoad() {
return isLoad;
}
public void setIsLoad(String isLoad) {
this.isLoad = isLoad;
}
}
这是系统运行日志
2023-06-27 12:25:15,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:25:15.875 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO c.h.c.i.b.displayBoard.service.SystemServiceImpl - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- queryLine-service1:97712023-06-27 12:25:15,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:25:15.875 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO com.atomikos.jdbc.AbstractDataSourceBean - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- AtomikosDataSoureBean '9771DB': getConnection ( null )...
2023-06-27 12:25:15,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:25:15.875 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO com.atomikos.jdbc.AbstractDataSourceBean - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- [9771DB]数据源加载配置为[true],正常加载
2023-06-27 12:25:15,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:25:15.875 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO com.atomikos.jdbc.AbstractDataSourceBean - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- AtomikosDataSoureBean '9771DB': init...
2023-06-27 12:26:12,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:12.065 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO com.atomikos.jdbc.AtomikosConnectionProxy - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3ef58ed7: calling getAutoCommit...
2023-06-27 12:26:12,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:12.065 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO com.atomikos.jdbc.AtomikosConnectionProxy - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3ef58ed7: calling prepareStatement(select Production_Line_Id as lineId ,Production_Line_Code as lineCode,Production_Line_Desc as lineDesc from pm_production_lines_t
2023-06-27 12:26:12,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:12.450 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO com.atomikos.jdbc.AtomikosConnectionProxy - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- atomikos connection proxy for com.mysql.jdbc.jdbc2.optional.JDBC4ConnectionWrapper@3ef58ed7: close()...
2023-06-27 12:26:25,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:25.263 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO c.h.c.i.b.displayBoard.service.SystemServiceImpl - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- System run time(miao):69
2023-06-27 12:26:25,sg-huaweiyun,seamom-prod,seamom-mes-base,seamom-mes-base-84748ccd44-8nlvg,2023-06-27 11:26:25.264 [DubboServerHandler-172.16.3.43:20880-thread-181] INFO c.h.c.i.b.displayBoard.service.SystemServiceImpl - [TID:59cb3626a68d4337b545619d71596be4_280_16878399158750027] --- queryLine-service2:9771
第四行跟第五行之间时间间隔1分钟,不知道为什么会这样
回答:
建议通过aop的方式记录一下 (数据源名称 访问开始 访问结束 接口路径等信息), 后面分析看看是网络导致的访问变慢 还是 和访问量相关
以上是 springboot项目中,用atomikos做的多数据源配置,某一个数据库,白天的时候访问非常慢,深夜访问就正常? 的全部内容, 来源链接: utcz.com/p/945222.html