数据密码修改服务不暂停方案
背景
应用投产后可能会有密码修改需要,怎样做到密码修改过程中不暂停服务,下面就已使用druid连接池为例说明解决方案
期望
密码修改过程中服务不暂停,不影响业务
常规方案
1、应用停机
2、修改数据库密码,并把密码加密成密文
3、修改应用数据库连接信息
4、启动应用
5、监控应用是否正常
常规方案比较简单,但是停机修改密码到应用启动成功的这段时间内会照成服务不可以,切服务之间存在相互依赖,影响范围较大
不停机方案
4.1. 方案思路
应用采用druid数据库连接池。数据库认证规则用户已认证的连接不会重复认证,即修改密码后对之前身份认证过的用户连接不受影响了。影响的只有在修改密码后进行身份认证的连接。
修改密码前修改连接池配置,使连接池中的连接不要释放,同时不创建新的连接,这样数据用户修改密码后则不会对当前应用产生影响。
4.2. 方案步骤
1、双机或以上集群方式部署的应用(这里A、B两台服务为例)
2、修改A、B两台服务器druid连接配置,初始连接数、最小连接数、最大连接数调整为相同值(全部修改为最大),最小空闲连接数保活开启。
druid:
# 初始化物理连接个数@Apollo
initial-size: 50
# 最小连接池数量@Apollo
min-idle: 50
# 最大连接池数量@Apollo
max-active: 50
# 配置获取连接等待超时的时间
max-wait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
min-evictable-idle-time-millis: 300000
#用来检测连接是否有效的sql,要求是一个查询语句,如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用
validation-query: SELECT ‘X’ FROM DUAL
#申请连接的时候检测,如果空闲时间大于imeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
test-while-idle: true
#申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
test-on-borrow: false
#归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
test-on-return: false
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall’用于防火墙
filters: stat,slf4j
# 打开PSCache,并且指定每个连接上PSCache的大小
pool-prepared-statements: true
# 要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true@Apollo
max-pool-prepared-statement-per-connection-size: 100
# 最小空闲连接数保活
keep-alive: true
3、逐台重启应用
4、重启成功后修改数据库用户密码
5、修改A路应用配置文件(或者apollo配置中心)数据库密码,重启A应用,观察A应用状态
6、A应用无问题,修改B路应用配置文件数据库密码,重启B应用,观察B应用状态
7、采用滚动部署方式修改druid连接配置信息重新部署应用
如果初始连接数、最小连接数、最大连接数可以因为密码修改是应用创建新连接,导致连接数据库错误,影响业务开展。
配置文件自动刷新方案
方案思路
使用apollo的配置属性自动更新机制,监听数据源配置属性的变化,如果属性有变化,重新刷新数据源对象。
程序改造
1、新建一个Druid数据源的配置类DruidConfig,并添加注解 @EnableApolloConfig 和@RefreshScope
@Configuration
@EnableApolloConfig
public class DruidConfig {
@RefreshScope
@ConfigurationProperties(prefix=“spring.datasource”)
@Bean
public DataSource druidDataSource () {
return new DruidDataSource();
}
}
2、新建一个apollo配置类ApolloConfig,监听属性的变化,如果有变化,则刷新druidDataSource对象。
@Component
public class ApolloConfig {
@Autowired
private org.springframework.cloud.context.scope.refresh.RefreshScope refreshScope;
@ApolloConfigChangeListener()
private void configChange(ConfigChangeEvent changeEvent){
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
logger.info(“Apollo配置属性发生了变化 {}”, change.toString());
if (key.contains(“spring.datasource”)) {
refreshScope.refresh("druidDataSource ");
break;
}
}
}
}
实施变便
1、DBA确定好修改后的密码,并进行加密。把密文给到项目组。
2、在Apollo配置中心修改加密后的密码,暂时不发布。
3、DBA修改数据库用户密码。并通知项目组。
4、项目组发布配置文件变更,使用之生效。