springboot如何正确使用tomcat连接池

在springboot的application.properties中,我们常常这么设置:

spring.datasource.url=jdbc:mysql://192.168.0.1:3306/dbname
spring.datasource.username=aaa
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

假如只有上面这些关于连接池的设置,那么springboot将根据 org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder 中的下面次序去找有没有相应的jar:

private static final String[] DATA_SOURCE_TYPE_NAMES = new String[] {
            "org.apache.tomcat.jdbc.pool.DataSource",
            "com.zaxxer.hikari.HikariDataSource",
            "org.apache.commons.dbcp.BasicDataSource", // deprecated
            "org.apache.commons.dbcp2.BasicDataSource" };

假如工程是内置tomcat容器的,那么默认就是 org.apache.tomcat.jdbc.pool.DataSource,同时tomcat连接池的那些最大最小参数都是默认值:
initialSize 10
maxActive 100
maxIdle 100
minIdle 10
可以看到这些默认值基本上也能满足大多数场景了。

假如觉得上面的这些值还不够好,那么需要在application.properties中这么设置才可以:
spring.datasource.tomcat.initialSize=10
spring.datasource.tomcat.maxActive=200
spring.datasource.tomcat.maxIdle=200
spring.datasource.tomcat.minIdle=10

这是因为在 org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Tomcat 这个类中如下定义:

@Bean
        @ConfigurationProperties(prefix = "spring.datasource.tomcat")
        public org.apache.tomcat.jdbc.pool.DataSource dataSource(
                DataSourceProperties properties) {
            org.apache.tomcat.jdbc.pool.DataSource dataSource = createDataSource(
                    properties, org.apache.tomcat.jdbc.pool.DataSource.class);
            DatabaseDriver databaseDriver = DatabaseDriver
                    .fromJdbcUrl(properties.determineUrl());
            String validationQuery = databaseDriver.getValidationQuery();
            if (validationQuery != null) {
                dataSource.setTestOnBorrow(true);
                dataSource.setValidationQuery(validationQuery);
            }
            return dataSource;
        }

可以看到 prefix = “spring.datasource.tomcat”,所以需要在配置中的前缀应该是 spring.datasource.tomcat,不这么设置,实际上是没有启用这些参数的。

最后,如何验证这些参数是否生效:在 org.apache.tomcat.jdbc.pool.DataSourceProxy 这个类的getConnection()方法中加个断点,然后运行后访问数据库时,查看这个 datasource 的这些参数。

下一篇将是 《springboot如何正确使用dbpc2连接池》

docker容器之间通过link方式的互联

这里只是描述在单docker容器之间通过link方式的互联,容器之间的其他联系方式不在本文里面描述。

首先我们来看一个例子:
1. 创建一个mysql容器:
docker run –name mymysql -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.5.49
这里创建了一个名字是 mymysql 的容器,为了举例,故意把名字弄成不一样,同时只是为了举例,不用去计较volumes
2. 创建一个需要使用mysql的容器,这里用wordpress来举例:
docker run –name wordpress -d -p 80:80 –link mymysql:mysql wordpress
同样只是为了举例,不要去计较volumes。很神奇的,不用设置mysql的连接地址,不用设置mysql的密码,wordpress启动后,这些都识别出来了。

这里面到底发生了什么?下面让我们一点一点来分析一下:
我们把mymysql这个容器叫做“源容器”,把wordpress这个容器叫做“接收容器”。在“接收容器”创建的时候,用 –link mymysql:mysql,其中 mymysql是“源容器”的名称,mysql这个名称叫做“别名”,是在“接收容器”中会用到,比如在程序中可以用 jdbc:mysql://mysql:3306/xxdb。

为了让“接收容器”访问“源容器”,比如为了能使得jdbc:mysql://mysql:3306/xxdb找到真正的地址,比如jdbc:mysql://192.168.0.3:3306/xxdb, docker提供了2种方式:
1. 环境变量
2. /etc/hosts 文件

环境变量

我们先运行下面的命令:
docker run -i -t –rm –link mymysql:mysql busybox:latest env #这个意思是在“接收容器”busybox中打印出所有的环境变量

HOSTNAME=5878f7496b83
TERM=xterm
MYSQL_PORT=tcp://192.168.0.3:3306
MYSQL_PORT_3306_TCP=tcp://192.168.0.3:3306
MYSQL_PORT_3306_TCP_ADDR=192.168.0.3
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_PORT_3306_TCP_PROTO=tcp
MYSQL_NAME=/inspiring_swanson/mysql
MYSQL_ENV_MYSQL_ROOT_PASSWORD=123456
MYSQL_ENV_GOSU_VERSION=1.7
MYSQL_ENV_MYSQL_MAJOR=5.5
MYSQL_ENV_MYSQL_VERSION=5.5.49
HOME=/root

看到了“接收容器”中的打印的环境变量就知道了,“接收容器”将“源容器”中的环境变量加了一个“别名”ENV这样的前缀,我们只要在程序中获取这些环境变量的值,就可以知道我们所需要的。

/etc/hosts 文件

我们先运行下面的命令:
docker run -i -t –rm –link mymysql:mysql busybox:latest cat /etc/hosts #这个意思是在“接收容器”busybox中打印出/etc/hosts这个文件的内容

127.0.0.1       localhost
::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
192.168.0.3     mysql 1023833075ea mymysql
192.168.0.5     6761e72cb33f

看到上面的192.168.0.3 mysql的映射关系了,这样也就能理解为什么jdbc:mysql://mysql:3306/xxdb能找到真正的地址,比如jdbc:mysql://192.168.0.3:3306/xxdb

参考

docker从入门到实践(容器互联)
以Tomcat+Mysql为例,实现Docker多容器连接