场景说明
项目整体是使用的是spring cloud架构,配置中心为spring cloud config组件。
最近项目中有个需求是上线的时候需要新旧服务同时运行, 但数据库表结构在本期变更中发生了很大的变化,所以这里考虑的使用自定义数据源来实现新旧服务访问不同的数据源。
新服务访问线上的正式数据库,旧的服务访问当前线上数据库的备份库。新的部署规划如下:
备注:这里熟悉spring boot的同学会说,这很好办,可以通过spring boot配置文件的优先级顺序,直接在当前服务根路径下定义config/application.yml文件,然后直接配置spring.datasource
来覆盖全局的配置即可。大家都知道spring boot 工程目录下config/application.yml配置优先级是最高的,这在单体项目下,确实是成立的,但是如果使用的spring cloud config配置中心,则配置
中心的配置优先级才是最高的。
实现方案
项目环境: spring boot 1.5.9 + spring cloud 1.3.6
1. 在当前项目配置文件添加新数据源配置,这里增加数据源为dbBak, 使用的是druid连接池
spring: #数据源 datasource: dbBak: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useSSL=false&characterEncoding=utf8&allowMultiQueries=true username: root password: 123456 type: com.alibaba.druid.pool.DruidDataSource druid: # 初始化连接池个数 initial-size: 5 # 最大连接池个数 max-active: 20 # 最小连接池个数 min-idle: 5 # 配置获取连接等待超时的时间,单位毫秒,缺省启用公平锁,并发效率会有所下降 max-wait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 time-between-eviction-runs-millis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 min-evictable-idle-time-millis: 300000 # 如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用 validation-query: SELECT 1 FROM DUAL # 建议配置为true,不影响性能,并且保证安全性。 # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 test-while-idle: true # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 test-on-borrow: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 test-on-return: false # 打开PSCache,并且指定每个连接上PSCache的大小 pool-prepared-statements: true
2. 增加config配置文件,新建配置文件DuridDataSourceConfig配置类
@Configuration public class DruidDatasourceConfig { /** * 添加 DruidDataSource 组件到容器中,并绑定属性: * 将自定义的 Druid 数据源添加到容器中,不再让 Spring Boot 自动创建 * 这样做的目的是:绑定全局配置文件中的 druid 数据源属性到 com.alibaba.druid.pool.DruidDataSource * 从而让它们生效 * * @ConfigurationProperties(prefix = "spring.datasource"):作用就是将 全局配置文件中 前缀为 spring.datasource * 的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中 */ @ConfigurationProperties(prefix = "spring.datasource.dbBak") @Bean public DataSource druidDataSource() { return new DruidDataSource(); } /** * 注册 Druid 监控之管理后台的 Servlet */ @Bean public ServletRegistrationBean servletRegistrationBean() { ServletRegistrationBean bean = new ServletRegistrationBean( new StatViewServlet(), "/druid/*"); /** * 这些参数可以在 com.alibaba.druid.support.http.StatViewServlet 的父类 com.alibaba.druid.support.http.ResourceServlet 中找到 * loginUsername:Druid 后台管理界面的登录账号 * loginPassword:Druid 后台管理界面的登录密码 * allow:Druid 白名单,后台允许谁可以访问,多个用逗号分割, 如果allow没有配置或者为空,则允许所有访问 * initParams.put("allow", "localhost"):表示只有本机可以访问 * initParams.put("allow", ""):为空或者为null时,表示允许所有访问 * deny:Druid 黑名单,后台拒绝谁访问,多个用逗号分割 (共同存在时,deny优先于allow) * initParams.put("deny", "192.168.1.20");表示禁止此ip访问 */ Map<String, String> initParams = new HashMap<>(); initParams.put("loginUsername", "admin"); initParams.put("loginPassword", "88888"); initParams.put("allow", ""); initParams.put("allow", "localhost"); /** 设置初始化参数*/ bean.setInitParameters(initParams); return bean; } /** * 配置 Druid 监控之 web 监控的 filter * 这个过滤器的作用就是统计 web 应用请求中所有的数据库信息, * 比如 发出的 sql 语句,sql 执行的时间、请求次数、请求的 url 地址、以及seesion 监控、数据库表的访问次数 等等。 */ @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean bean = new FilterRegistrationBean(); bean.setFilter(new WebStatFilter()); /** exclusions:设置哪些请求进行过滤排除掉,从而不进行统计*/ Map<String, String> initParams = new HashMap<>(); initParams.put("exclusions", "*.js,*.gif,*.jpg,*,png,*.css,/druid/*"); bean.setInitParameters(initParams); /** "/*" 表示过滤所有请求*/ bean.setUrlPatterns(Arrays.asList("/*")); return bean; } }
3. 正常启动项目后,访问 http://localhost:8080/druid/ ,会打开durid控制台页面,切换到【数据源】页面,就会看到连接已经更新