Apollo 配置中心
包含两个数据库
apolloconfigdb
app: appId Name(应用名称) OrgId(部门Id) OrgName(部门名称)
appnamespace: Name(namespace名称 全局唯一) appId format(namespace的format类型) isPublic(namespace是否公共)
audit: entityName(表名) entityId(记录id) OpName(操作名称) isDelete(是否删除)
cluster: Name(集群名字) AppId ParentClusterId(父cluster) isDelete(是否删除)
commit: ChangeSets(修改变更集) AppId ClusterName Namespace isDelete(是否删除)
grayreleaserule: AppId ClusterName Namespace BranchName Rules(灰度规则) ReleaseId(灰度对应的release)
BranchStatus(灰度状态0:删除 1:正在使用的规则 2:全量发布)
instance: appId ClusterName DataCenter(数据中心名称) Ip
instanceconfig: instanceId ConfigAppId ConfigClusterName ConfigNamespaceName ReleaseKey ReleaseDeliberyTime
item: NamespaceId(集群NamespaceId) Key(配置项key) Value(配置项Value) LineNum(行号)
namespace: AppId NamespaceName ClusterName
namespacelock: NamespaceId
release: ReleaseKey Name AppId ClusterName NamespaceName Configurations isAbandoned isDelete
releaseHistory: AppId NamespaceName ClusterName ReleaseId PrevisousReleaseId
Operation(0:普通发布 1:回滚 2:灰度发布 3:灰度更新规则 4:灰度合并回主发布 5:主分支发布灰度自动发布
6:主分支回滚灰度自动发布 7:放弃灰度)
releasemessage: Message(发布的消息内容)
serverconfig: Key(配置项key) Value(配置项Value) Cluster(针对的集群,default不针对特定集群)
apolloportaldb
app
appnamespace
authorities
consumer
consumeraudit
consumerrole
consumertoken
favorite
permission
role
rolepermission
serverconfig
userrole
users
三个微服务
apollo-adminservice
对protal提供配置的修改,发布
apollo-configservice
对客户端提供配置的读取,推送
apollo-portalservice
通过域名访问Meta Server获取AdminService服务列表,然后直接通过IP+PORT访问
client
通过域名访问Meta Server获取ConfigService服务列表,然后直接通过IP+PORT访问
**apollo-configservice详细解读**
ConfigController
url: get /configs/{appId}/{clusterName}/{namespace:.+}
作用: 对应应用的ApolloConfig(appId clusterName namespace mergedReleaseKey configurations)配置
细节:
第一步 修整namespace参数(去掉后缀,)
去掉传入的namespace参数的后缀(比如.properties)
根据appId和namespace去缓存中获取AppNamespace的名称
如果没有,则根据namespace从缓存中获取公共命名空间的appNamespace的名称
如果没有,则直接返回namespace
第二步 获取客户端的地址ip
第三步 将传入的messages参数 转换为ApolloNotificationMessages 通知信息(Map<String, Long> details)
第四步 根据传入的 appId clientIP cluster/datacenter/'default' namespace ApolloNotificationMessages 获取 Release
将 appId cluster namespace 用+串联作为key
根据 key 从灰度发布缓存中获取 灰度发布(比较 appId clientIP) 获取releaseId
如果在配置config-service.cache.enabled=true 那么从缓存中 根据 releaseId 获取release
如果没有获取到,则根据 appId cluster namespace 去数据库获取最新的有效的release
第五步 判断该namespace是否属于该appId
如果不是 那么根据namespace获取AppNamespace的AppId 在重复第四步的调用(只是类似的调用)
第六步 审计获取到的release 即 表Instance 以及对应 InstanceConfig
第七步 合并获取到的release的releaseKey(+串联)
第八步 根据
appId
clusterName(当前的appId对应的release的cluster,否则为空)
namespace
mergedReleaseKey(所有release中的releasekey +串联)
configurations(所有release中的configuration Map<String,String>)
创建一个ApolloConfig 返回(如果mergedReleaseKey和传入一致返回304)
ConfigFileController
url:get /configfiles/{appId}/{clusterName}/{namespace:.+}
作用: 获取该应用配置下以 properties 格式配置的配置数据 (即所有release的configurations)
url: get /configfiles/json/{appId}/{clusterName}/{namespace:.+}
作用: 获取该应用配置下以 json 格式配置的配置数据 (即所有release的configurations)
统一细节:
第一步 修整namespace参数(去掉后缀,)
去掉传入的namespace参数的后缀(比如.properties)
根据appId和namespace去缓存中获取AppNamespace的名称
如果没有,则根据namespace从缓存中获取公共命名空间的appNamespace的名称
如果没有,则直接返回namespace
第二步 获取客户端的地址ip
第三步 判断是否有灰度发布(根据 appId clientIp namespace 串联为key检测缓存 clientIp可以是*)
如果有直接调用 ConfigController 的 接口 获取 ApolloCOnfig
如果有配置 则直接根据需要传输的格式(properties,json)将 ApolloCOnfig 中的 configuration 格式化成字符串
直接返回结果
第四步 如果不是灰度发布
根据 outputFormat, appId, clusterName, namespace, dataCenter 串联成key
判断缓存中是否存在 存在直接返回
不存在 直接调用 ConfigController 的 接口 获取 ApolloCOnfig
如果有配置 则直接根据需要传输的格式(properties,json)将 ApolloCOnfig 中的 configuration 格式化成字符串
第五步 如果获取到的值为空 直接返回
不为空 再次检测是否有灰度发布数据,有则直接返回
将 获取到的值 缓存起来 即上面 的 串联key 和 当前得到的返回值
然后缓存
Set<String> watchedKeys = watchKeysUtil.assembleAllWatchKeys(appId, clusterName, namespace, dataCenter);
cacheKey2WatchedKeys.putAll(cacheKey, watchedKeys)
watchedKeys2CacheKey.put(watchedKey, cacheKey);
这些用于消息监听器检测到消息发送出去后对当前的缓存进行清除操作
第六步 返回指定格式的 的格式化字符串(即应用配置)
NotificationController
url: get /notifications
作用: 获取 配置通知
ApolloConfigNotification(namespaceName notificationId Map<String, Long> details 当前这个只一般没有)集合
notificationId 为releaseMessage的id
details为<watchKey, releaseMessage.id>
细节:
第一步 将传入的参数 notifications gson成 ApolloConfigNotification 集合 如果为空 则直接抛出异常
第二步 将ApolloConfigNotification集合进行过滤
遍历集合 如果其中 namespaceName为空 则跳过
修整namespace参数(去掉后缀,)
去掉传入的namespace参数的后缀(比如.properties)
根据appId和namespace去缓存中获取AppNamespace的名称
如果没有,则根据namespace从缓存中获取公共命名空间的appNamespace的名称
如果没有,则直接返回namespace
设置 ApolloConfigNotification 的 namespace 为 originNamespace
得到 Map<String, ApolloConfigNotification> 集合 即 key=namespace value=ApolloConfigNotification
第三步 遍历Map<String, ApolloConfigNotification> 集合
如果 namespace 和 ApolloConfigNotification中的namespace 不一致
则 将这两个值放入 DeferredResultWrapper 中的 normalizedNamespaceNameToOriginalNamespaceName
用于在将 值设置 进 DeferredResultWrapper 时 使用原生的namespace进行填充
第四步 生成watchKey
如果 clusterName 不为default 那么 生成一个 appId+clusterName+namespace 的 key
如果 dataCenter 不为空 且 datacenter不等于 clusterName 那么生成一个 appId+dataCenter+namespace 的key
生成一个默认的 appId+"default"+namespace 的 key
返回 一个 key=namespace value=watchKey 的map
第六步 根据这些watchKeys 从releaseMessage的缓存中获取对应的所有的 releaseMessage
第七步 根据这些releaseMessage和 namespaces clientSideNotifications watchedKeysMap
生成新的 ApolloConfigNotification 集合
遍历所有的releaseMessage 获取 message 和 id 放入map
遍历所有的namespaces 获取 clientSideNotifications 中namespace对应的 notificationId
遍历其中的 watchKeysMap 获取当前的namespace对应的watchkey 获取最新的releaseMessage的id
如果存在releaseMessage比用户传过来的的更新 则生成新的 ApolloConfigNotification
将这些最新的 ApolloConfigNotification 组成集合
第八步 如果最新的 ApolloConfigNotification 集合不为空,
则将这些最新的 ApolloConfigNotification 集合设置到 异步返回数据集合中
(使用上面的 DeferredResultWrapper中的 originNamespace 和 namespace 替换)
第九步 如果最新的 ApolloConfigNotification 集合为空 则对异步deferredResults做一些清理工作
第十步 返回 异步结果 即 最新的 ApolloConfigNotification 集合
**apollo-adminser