Skip to content

定制化参考 配置中心

Shengyuan 卢声远 edited this page Jan 20, 2021 · 5 revisions

简介

本文介绍了信也科技内部如何基于Apollo配置中心定制化DAS,为有类似需求的公司提供实施参考。

背景

DAS客户端应用程序启动时,需要获取逻辑数据库和物理数据库的信息来创建数据库连接池。缺省的基于das.xml和datasource.xml的获取方式在一般的场景下虽然足够使用,但存在诸多限制,例如如何区分不同环境的同名配置文件,如何防止数据库连接串泄露,如何动态修改,切换数据源等等。为解决上述问题,DAS客户端提供ClientConfigureLoader来允许用户提供自定义的配置获取方式。

信也科技内部的DAS客户端利用现有的Apollo环境提供了信也科技自身的ClientConfigureLoader实现。

Apollo是目前较流行的配置中心,其配置层次结构application,Namespace和properties。其中application下面可以存在多个Namespace(简称NS),每个Namespace以properties的格式存放多个配置项

在用户配置逻辑数据库,物理数据库和创建应用的时候,DAS Console会先写自身的数据库,再向Apollo同步数据,将配置信息写入对应的apollo application中。

配置项说明

命名规则

  1. Apollo公共name space的名字要求为全局唯一,为了避免冲突,所有用到namespace的地方,我们都增加das相关的前缀。namespace都是公有。
  2. apollo application和name space的名字是单词直接用-连接。例如,das-application-groups
  3. name space由固定前缀+实际名字组成。例如,das-my-order
  4. Name space中的配置项的属性名是驼峰方式。例如,applicationList

全局配置说明

实体类型 Apollo Application Name 说明 Name Space前缀
Dal Team global-das-teams 存放全部的Dal Team das-tm-
MySql物理数据库配置 global-mysql-datasource 存储物理数据库的链接属性 das-my-
SqlServer物理数据库配置 global-sqlserver-datasource 存储物理数据库的链接属性 das-ms-
分库分表策略 das-sharding-strategies 存放公共的分库分表策略配置 das-ss-
应用组配置 das-application- 存放所有应用组配置 das-ag-
数据连接池配置 global-datasource-pool-config 全局唯一数据连接池配置信息
服务器查找表 das-sever-lookup-table 存放所有服务器对应的IP和Port das-sv-
服务器组配置 das-server-groups 存放所有服务器组 das-sg-

配置项说明

数据库连接池配置

全局唯一数据连接池配置信息

Apollo Application:global-datasource-pool-config

Namespace = datasource-pool-config

testWhileIdle = truetestOnBorrow = true
testOnReturn = false
validationQuery = "SELECT 1"
validationInterval = 30000
timeBetweenEvictionRunsMillis = 30000
maxActive = 100
minIdle = 0
maxWait = 10000
initialSize = 1
removeAbandonedTimeout = 60
removeAbandoned = true
logAbandoned = true
minEvictableIdleTimeMillis = 30000
mysqlOption = rewriteBatchedStatements=true;allowMultiQueries=true;useUnicode=true;characterEncoding=UTF-8;
sqlServeOption = sendTimeAsDateTime=false;sendStringParametersAsUnicode=false;

物理库配置

物理数据库配置会按照数据库类型区分为MySql与SqlServer,每种类型的数据库会对应一个Apollo应用。

每个具体的物理数据库配置会对应于特定数据库应用下的Name Space,名字是物理数据库的名字,也即连接串名字,connectionName。

MySql

Apollo Application:global-mysql-datasource

Name space前缀:das-my-

SqlServer

Apollo Application:global-sqlserver-datasource

Name space前缀:das-ms-

样例

例如连接串名字为order的数据库,配置为:

Namespace = das-my-order

userName = your name
password = your pass
host = 12.12.12.12
port = 3306
dbName = order_shard_0
driverClassName = com.mysql.jdbc.Driver

DAL Team配置

由于逻辑数据库属于DAL Team。因此需要在Apollo上创建DAL Team的应用

Apollo Application:global-das-teams

Name space前缀:das-tm-

每个DAL Team创建为该应用下的Namespace

该DAL Team下的所有逻辑数据库配置作为该Namespace的配置项。

例如:

Namespace = dal-test-team

databaseSets = MySqlSimple,MySqlSimpleDbShard,MySqlSimpleTableShard,MySqlSimpleDbTableShard,SqlSvrSimple,SqlSvrSimpleDbShard,SqlSvrSimpleTableShard,SqlSvrSimpleDbTableShard
MySqlSimple.provider = mysqlProvider
MySqlSimple.entries = dal_shard_0
MySqlSimple.dal_shard_0.type = Master
MySqlSimple.dal_shard_0.sharding =
MySqlSimple.dal_shard_0.datasource = dal_shard_0
MySqlSimpleDbShard.provider = mysqlProvider
MySqlSimpleDbShard.shardingStrategy = class=com.ppdai.das.shard.ModStrategy;columns=CountryID;mod=2;
MySqlSimpleDbShard.entries = dal_shard_0,dal_shard_1
MySqlSimpleDbShard.dal_shard_0.type = Master
MySqlSimpleDbShard.dal_shard_0.sharding = 0
MySqlSimpleDbShard.dal_shard_0.datasource = dal_shard_0
MySqlSimpleDbShard.dal_shard_1.type = Master
MySqlSimpleDbShard.dal_shard_1.sharding = 1
MySqlSimpleDbShard.dal_shard_1.datasource = dal_shard_1
MySqlSimpleTableShard.provider = mysqlProvider
MySqlSimpleTableShard.shardingStrategy = class=com.ppdai.das.shard.ModStrategy;tableColumns=CityID;tableMod=4;separator=_;shardedTables=person
MySqlSimpleTableShard.entries = dal_shard_0
MySqlSimpleTableShard.dal_shard_0.type = Master
MySqlSimpleTableShard.dal_shard_0.sharding =
MySqlSimpleTableShard.dal_shard_0.datasource = dal_shard_0
MySqlSimpleDbTableShard.provider = mysqlProvider
MySqlSimpleDbTableShard.shardingStrategy = class=com.ppdai.das.shard.ModStrategy;columns=CountryID;mod=2;tableColumns=CityID;tableMod=4;separator=_;shardedTables=person
MySqlSimpleDbTableShard.entries = dal_shard_0,dal_shard_1
MySqlSimpleDbTableShard.dal_shard_0.type = Master
MySqlSimpleDbTableShard.dal_shard_0.sharding = 0
MySqlSimpleDbTableShard.dal_shard_0.datasource = dal_shard_0
MySqlSimpleDbTableShard.dal_shard_1.type = Master
MySqlSimpleDbTableShard.dal_shard_1.sharding = 1
MySqlSimpleDbTableShard.dal_shard_1.datasource = dal_shard_1
SqlSvrSimple.provider = sqlProvider
SqlSvrSimple.entries = sql_shard_0
SqlSvrSimple.sql_shard_0.type = Master
SqlSvrSimple.sql_shard_0.sharding =
SqlSvrSimple.sql_shard_0.datasource = sql_shard_0
SqlSvrSimpleDbShard.provider = sqlProvider
SqlSvrSimpleDbShard.shardingStrategy = class=com.ppdai.das.shard.ModStrategy;columns=CountryID;mod=2;
SqlSvrSimpleDbShard.entries = sql_shard_0,sql_shard_1
SqlSvrSimpleDbShard.sql_shard_0.type = Master
SqlSvrSimpleDbShard.sql_shard_0.sharding = 0
SqlSvrSimpleDbShard.sql_shard_0.datasource = sql_shard_0
SqlSvrSimpleDbShard.sql_shard_1.type = Master
SqlSvrSimpleDbShard.sql_shard_1.sharding = 1
SqlSvrSimpleDbShard.sql_shard_1.datasource = sql_shard_1
SqlSvrSimpleTableShard.provider = sqlProvider
SqlSvrSimpleTableShard.shardingStrategy = class=com.ppdai.das.shard.ModStrategy;tableColumns=CityID;tableMod=4;separator=_;shardedTables=person
SqlSvrSimpleTableShard.entries = sql_shard_0
SqlSvrSimpleTableShard.sql_shard_0.type = Master
SqlSvrSimpleTableShard.sql_shard_0.sharding =
SqlSvrSimpleTableShard.sql_shard_0.datasource = sql_shard_0
SqlSvrSimpleDbTableShard.provider = sqlProvider
SqlSvrSimpleDbTableShard.shardingStrategy = class=com.ppdai.das.shard.ModStrategy;columns=CountryID;mod=2;tableColumns=CityID;tableMod=4;separator=_;shardedTables=person
SqlSvrSimpleDbTableShard.entries = sql_shard_0,sql_shard_1
SqlSvrSimpleDbTableShard.sql_shard_0.type = Master
SqlSvrSimpleDbTableShard.sql_shard_0.sharding = 0
SqlSvrSimpleDbTableShard.sql_shard_0.datasource = sql_shard_0
SqlSvrSimpleDbTableShard.sql_shard_1.type = Master
SqlSvrSimpleDbTableShard.sql_shard_1.sharding = 1
SqlSvrSimpleDbTableShard.sql_shard_1.datasource = sql_shard_1

应用的逻辑数据库配置

应用使用到的逻辑数据库需要写入该应用对应的Apollo应用下das-config NS。格式:

  1. 所有该应用用到的逻辑数据库名字用','隔开写入databaseSets配置项
  2. 应用所属的DAL Team写入dalTeam配置项
  3. 应用所属应用组的ID写入appGroupId

例如:

Namespace = das-config

databaseSets = MySqlSimple,MySqlSimpleDbShard,MySqlSimpleTableShard,MySqlSimpleDbTableShard,SqlSvrSimple,SqlSvrSimpleDbShard,SqlSvrSimpleTableShard,SqlSvrSimpleDbTableShard
dalTeam = dal-test-team
appGroupId = dal-test-app-group

应用组配置

Apollo Application:das-application-groups

Name space前缀:das-ag-

每个应用组创建为该application下的NS

应用组

每个应用组创建为das-application-groups application下的NS,将组名用于NS的名字。例如AppGroup-1, AppGroup-User。

每个应用组包含以下内容:

  1. applicationList。属于同一AppGroup的所有App ID。之间用','分隔。一个配置项
  2. serverEnabled。是否是远程连接Das Server的方式
  3. serverGroupId。指定的server-group-id。一个配置项

例如:

Namespace = das-test-app-group

applicationList = 1000001,1000002
serverEnabled = true
serverGroupId = financial-svr-group

服务器组配置

Apollo Application:das-server-groups

Name space前缀:das-sg-

每个服务器组创建为该application下的NS

服务器组

每个服务器组创建为das-server-groups application下的NS,组名就是NS的名字。例如das-group-1, das-group-fin

每个服务器组包含以下内容:

  1. applicationGroupList。所有指向该服务器组的应用组的Name(name唯一)
  2. serverList。[ip]:[port]。','分隔。方便客户端确定可用server实例

例如:

Namespace = das-sg-financial-svr-group

applicationGroupList = das-test-app-group, financial-app-group
serverList= 123.0.0.1:9090,123.0.0.1:9092,123.0.0.1:9093

服务器查找表

在apollo创建一个名叫das-sever-lookup-table的application

Name space前缀:das-sv-

用server的IP创建NS,包含:

  1. [port]:当前实例所属的server group id。方便das sever查找自身所在server group
  2. [port]_maxPoolSize
  3. [port]_keepAliveTime 其他基于port的配置信息,格式如上

注意

  1. 一个server ip下面可能会存在多个port
  2. 在添加服务器的时候,需要同时写das-server-groups对应IP下的serverList和sever-lookup-table

例如:

Namespace = das-sv-123.0,0.1

9090 = das-sg-financial-svr-group
9090_maxPoolSize = 200
9090_keepAliveTime = 60
9091 = das-sg-financial-svr-group
9091_maxPoolSize = 200
9091_keepAliveTime = 60
9092 = das-sg-financial-svr-group
9092_maxPoolSize = 200
9092_keepAliveTime = 60

策略配置集成

公共策略存储

Apollo 应用:das-sharding-strategies

名字前缀:das-ss-

策略按前缀加名字保存为公共的name space。

例如策略名字为OrderRange,则实际name space为das-ss-OrderRange

  1. className:静态加载的策略类名
  2. dynamicSource:动态加载的Java代码。
  3. 两者不会并存 Namespace = das-ss-OrderRange Collapse source
isDynamic = true/false
className = com.ppdai.das.shard.AnotherModStrategy
或者
className=com.ppdai.das.shard.MyStrategy
dynamicSource = java code....

逻辑数据库策略配置

在逻辑数据库配置中,按照策略类型存储为:

  1. 如果存储的是公共策略则,则按照strategyName=策略名的形式存储
  2. 原来私有策略,则按照class=策略实现类的方式存储。和一期目前做法保保持一致
  3. 策略的其他相关属性还是按照key/value的形式存储。

策略样例:

私有策略: 
MySqlSimpleDbShard.shardingStrategy = class=com.ppdai.das.shard.ModStrategy;columns=CountryID;mod=2;
 
公共策略:
MySqlSimpleDbShard.shardingStrategy = strategyName=das-ss-OrderRange;columns=CountryID;lowField=startDate;hightField=endDate;

客户端策略加载

客户端的配置加载程序在读取逻辑数据库shardingStrategy的时候:

  1. 如果包含class,则为私有策略,按类名实例化策略对象
  2. 如果包含strategyName,则为公共策略,需要:
    1. 按名字去das-sharding-strategies查找对应的name space
    2. 如果包含className属性,则判断为静态策略, 按类名实例化策略对象
    3. 如果包含dynamicSource,则判断为动态策略,按照调研中的办法加载
  3. 其他属性按照现在的方式作为初始化参数调用策略的初始化接口

预定义静态策略存储

对于通用的动态策略,建议在充分验证后,用Java类实现并放在相应的公共模块

  1. 如果是非信也科技特定策略,建议放在das-client里 package com.ppdai.das.strategy下面
  2. 如果是信也科技特定策略,建议放在ppdai-das-common里 package com.ppdai.das.shard下面