Home  >  Article  >  Java  >  Problems when using alibaba druid to connect multiple data sources

Problems when using alibaba druid to connect multiple data sources

零下一度
零下一度Original
2017-07-21 17:27:327389browse

Problems when using alibaba druid to connect multiple data sources

Tags (space separated): druid springboot start autoconfig


  • Background

  • Discovery and analysis process

  • Summary

Background

Recently using alibaba druid I accidentally discovered a small bug when connecting multiple data sources. I have submitted a github issue and it has been officially fixed. Issue address:

Discovery and analysis process

The java development framework we use is encapsulated. The framework's support for data sources is based on the master and slave architecture, that is, it can be a set of multiple slave data sources, and master-slave writing and query switching will be automatically performed internally.

We are now in the process of specializing .net in java. In special scenarios, the new java system needs to connect to two data sources. The mysql data source is connected by default, but sometimes it is necessary to query the sqlserver data source to obtain some compatibility data. .
So, when configuring the second data source, the system load reports an error.

We use the springboot framework, and datasource config is configured based on springboot properties. Then use configuration to create automatic druid daasource beans. This doesn't seem to be a problem.

    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "ecommon.order.druid")
    public DataSource getOrderDataSource() {
       return new DruidDataSource();
    }

If it is not springboot, you will usually initialize all properties yourself. Load the configuration from the configuration file and set the DruidDataSource bean manually.

I didn’t think much and just used it this way. But at startup, an error was reported when initializing the bean.

'maxEvictableIdleTimeMillis' threw exception; nested exception is java.lang.IllegalArgumentException: maxEvictableIdleTimeMillis must be greater than minEvictableIdleTimeMillis

Probably means, 'maxEvictableIdleTimeMillis' maximum survival time Must be greater than 'minEvictableIdleTimeMillis' minimum time to live.

The first reaction must be that the configuration is wrong, check the configuration.

##一个连接在池中最小生存的时间(ms)
ecommon.order.druid.minEvictableIdleTimeMillis=300000
##一个连接在池中最大生存的时间(ms)
ecommon.order.druid.maxEvictableIdleTimeMillis=600000

It seems to be correct, and then under debug, the problem also occurs. The order of the minEvictableIdleTimeMillis attribute and maxEvictableIdleTimeMillis attribute seems to be fine. After trying it out, I swapped the order of the two attributes, but the problem still occurred.

Blinded state~_~.

I feel that this problem is a bit strange. Time is of the essence, so I directly find the place where the error is reported and trace the source code.
Go to the github search alibaba druid homepage, directly gith clone it, and locate the location of the error prompt.

There are two places where this exception is thrown during global search.
1: init method

public void init() throws SQLException {
            if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
                throw new SQLException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
            }

In order to facilitate reading, I deleted the code in init that is useless for us to analyze the problem.

2: setMaxEvictableIdleTimeMillis method

    public void setMaxEvictableIdleTimeMillis(long maxEvictableIdleTimeMillis) {
        if (maxEvictableIdleTimeMillis < 1000 * 30) {
            LOG.error("maxEvictableIdleTimeMillis should be greater than 30000");
        }
        
        if (maxEvictableIdleTimeMillis < minEvictableIdleTimeMillis) {
            throw new IllegalArgumentException("maxEvictableIdleTimeMillis must be grater than minEvictableIdleTimeMillis");
        }
        
        this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
    }

The logic of these two methods is relatively simple. The values ​​of these two bean properties will be checked during init initialization. setMaxEvictableIdleTimeMillis, there is a check when setting the maximum survival time. If your maximum survival time is less than the minimum survival time, an error will be reported directly.

So just put breakpoints in these two places, then debug, and trace the values ​​of the variables to basically know where the problem is.

Through debugging, I found that using the data source directly with new DruidDataSource() will not go to the init method. You will not enter the place where the error is triggered. It seems that my code path should not generate this check. Continue running and see what happens with the setMaxEvictableIdleTimeMillis method.

Found the problem. When performing the setMaxEvictableIdleTimeMillis method, the value of the minEvictableIdleTimeMillis attribute is 1800000.

Look where this value comes from.

protected volatile long  minEvictableIdleTimeMillis  = DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
public static final long  DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS = 
1000L * 60L * 30L;

minEvictableIdleTimeMillis property has a default value. The unit is ms (millisecond), so the default value here is 30m (minute) minutes.

We configured 600000ms, so it is smaller than 1800000. But this is strange, we clearly set the minEvictableIdleTimeMillis parameter. Why it didn't work? I immediately thought that it was a sequence problem.

Then continue debugging, first bypass this check to see if the setMinEvictableIdleTimeMillis method is executed after the setMaxEvictableIdleTimeMillis method, causing this check to conflict with the configuration sequence.

After debugging, this is indeed the problem. Then I was curious about how the framework we are using now helps us encapsulate druid. By looking at the source code of the framework, there is a hashcode sorting in it, which solves this problem. (Sure enough, a veteran driver and a master) I won’t go into details here.

So if we solve this problem, it is actually very simple. It is still very simple to know where to go around the problem.

One: First get the configured minEvictableIdleTimeMillis and maxEvictableIdleTimeMillis in

@Data
@EqualsAndHashCode
@ConfigurationProperties(prefix = "ecommon.order.druid")
public class SqlServerDruidConfig {
    private Long minEvictableIdleTimeMillis;
    private Long maxEvictableIdleTimeMillis;
}

Two: Then set these two properties yourself first, and there will be no errors when springboot autoconfig

 @Autowired
    private SqlServerDruidConfig druidConfig;

    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "ecommon.order.druid")
    public DataSource getOrderDataSource() {

        DruidDataSource dataSource = new DruidDataSource();

        /**setMinEvictableIdleTimeMillis需要先设置*/
        dataSource.setMinEvictableIdleTimeMillis(druidConfig.getMinEvictableIdleTimeMillis());
        dataSource.setMaxEvictableIdleTimeMillis(druidConfig.getMaxEvictableIdleTimeMillis());

        return dataSource;
    }

    @Bean
    public SqlServerDruidConfig getDruidConfig() {
        return new SqlServerDruidConfig();
    }

The analysis of the problem ends here. This small bug has been fixed by alibaba druid.
If you are interested in how to fix it, please refer to druid for the code about autoconfiger fix:

Summary

Suddenly you can understand that you have already benefited from the benefits of open source. You can participate in using it together, participating in discovering problems together, and participating in fixing bugs together. This may be the core technical value behind excellent works of art such as Linux and git.

The above is the detailed content of Problems when using alibaba druid to connect multiple data sources. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn