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-adminserver详细解读**
AppController
url: post /apps
作用: 创建App 如果是默认还会创建AppNamespace, Cluster namespace
细节:
第一步 验证appId的格式(只允许输入数字,字母和符号 - _ .)
第二步 判断是否已有相同appId的App存在
第三步 保存APP
第四步 插入一条Audit(id entityName entityId opName comment)
第四步 判断该appId对应的AppNamespace的名称为 application 是否存在
第五步 创建appId和名称为application的 ApplicationNamespace
第六步 插入一条Audit(id entityName entityId opName comment)
第七步 验证是否有该appId对应的名称为 default 的cluster
第八步 保存Cluster
第九步 插入一条Audit(id entityName entityId opName comment)
第十步 获取appId对应的AppNamespace集合
遍历集合
每一条AppNamespace保存 Namespace 插入一条Audit
url: delete /apps/{appId:.+}
作用:删除APP
细节:
第一步 验证对应appId的APP是否存在
第二步 设置APP的delete属性为true 进行逻辑删除
第三步 插入一条Audit
url: put /apps/{appId:.+}
作用: 修改app
细节:
第一步 验证appId是否一致
第二步 修改该APP中除AppId外的一切属性
第三步 插入一条审计Audit
url: get /apps
作用: 获取所有的app或分页获取
细节:
第一步 有名称则获取指定名称的app 没有则按分页获取所有的app
第二步 返回结果
url: get /apps/{appId:.+}
作用: 获取指定appId的app详情
细节:
根据appId查询,返回结果
url: get /apps/{appId}/unique
作用: 判断当前appId是否唯一
细节:
查询数据库,是否有唯一
AppNamespaceController
url: post /apps/{appId}/appnamespaces
作用: 创建该appId对应的appNamespace
细节:
第一步 判断是否已存在相同appId和name的appNamespace
第二步 保存该appNamespace
第三步 获取该appId对应的ParentId=0的cluster
第四步 遍历cluster
保存Namespace(cluster.name, appNamespace.name, appId)
每一个都插入 Namespace Audit
第五步 插入 appNamespace Audit
url: get /appnamespaces/{publicNamespaceName}/namespaces
作用: 获取所有该名称的公共namespace
细节:
第一步 根据名称获取改名称下为公共的appNamespace
第二步 根据公共appNameSpace存在 则使用该名称去获取Namespace
第三步 对Namespace进行过滤
根据namespace.appid和namespace.cluster 获取cluster
获取该cluster的parent 并判断该parent是否存在
根据appId clusterName namespace 获取namespace
如果存在表示 该namespace是子命名空间
url: get /appnamespaces/{publicNamespaceName}/associated-namespaces/count
作用: 获取该namspace中公共namespace的个数
细节:
第一步 根据名称查找改命名空间的appNamespace
第二步 获取所有该名称的namespace但不是该appId的命名空间个数
ClusterController
url: post /apps/{appId}/clusters
作用: 创建cluster
细节:
第一步 验证cluster.name是否有效
第二步 判断cluster.appId cluster.name 是否唯一
第三步 判断是否为私有命名空间的cluster (私有的比公共的要多生产一些namespace)
第四步 保存cluster
第五步 插入audit
第六步 私有情况下 获取该appId下的所有AppNamespace 然后遍历生成Namespace
url: delete /apps/{appId}/clusters/{clusterName:.+}
作用:删除cluster
细节:
第一步 判断cluster.appId cluster.clusterName 是否存在 会得到cluster
第二步 根据id获取cluster
第三步 获取cluster.appId cluster.name 所有的namespace
第四步 遍历namespace
删除该namespace空间下的所有 Item
删除该namespace下的所有 commit
删除该namespace下所有的 release
获取该namespace下的所有子命名空间下的 release 和 GrayReleaseRule
创建上面删除release的releaseHistory
删除该命名空间下instanceConfig
将该命名空间解锁
删除namespace 并发送一条的命名空间删除的消息
url: get /apps/{appId}/clusters
作用: 获取appId的所有的cluster
细节:
第一步 获取所有的parentClusterId=0 且指定appId的Cluster
第二步 排序返回
url: get /apps/{appId}/clusters/{clusterName:.+}
作用: 获取指定appId和clusterName的 cluster的 详情
细节:
第一步 查询指定appId和clustername的所有信息
url: get /apps/{appId}/cluster/{clusterName}/unique
作用: 判断该appId和clusterName是否唯一
细节:
调用查询判断是否存在
CommitController
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/commit
作用: 查询指定appId clusterName namespace 下的commit
细节:
根据参数直接查询
InstanceConfigController
url: get /by-release
作用:根据releaseId 获取所有的Instance
细节:
第一步 根据releaseId 获取所有的Release
第二步 根据release.releasekey 获取前一天所有被修改过的InstanceConfig
第三步 根据上面查询出来的InstanceConfig集合,获取对应的所有Instance
第四步 返回 instance 和InstacneConfig
url: get /by-namespace-and-releases-not-in
作用: 获取所有namespace 但不包含传入的releaseIds的 Instacne 和 InstanceConfig
细节:
第一步 获取所有参数携带的release
第二步 获取所有不属于这个中的InstanceConfig
第三步 获取InstanceConfig集合对应的Instance集合
第四步 返回Instance InstanceConfig
url: get /by-namespace
作用: 获取所有namespace中的Instance
细节:
第一步 获取该指定 appId cluster namespace 中的 InstanceConfig 集合
第二步 获取所有该InstaceConfig对应的Instance
第四步 返回
url: get /by-namespace/count
作用: 查询个数
细节:
查询该 appId cluster namespace 指定的下的Instance的个数
ItemController
url: post /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items
作用:创建Item
细节:
第一步 判断该appId cluster namespaceName 对应的 Item是否存在
第二步 保存该Item
第三步 插入一条Audit
第四步 插入一条新增的Commit
url: put /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}
作用:修改Item
细节:
第一步 判断该appId cluster namespaceName 对应的 Item是否存在
第二步 保存该Item
第三步 插入一条Audit
第四步 插入一条修改的Commit
url: delete /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}
作用:删除Item
细节:
第一步 判断该appId cluster namespaceName 对应的 Item是否存在
第二步 删除该Item
第三步 插入一条Audit
第四步 插入一条删除的Commit
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items
作用:查询Item
细节:
第一步 查询appId cluster namespaceName 对应的 所有Item
url: get /items/{itemId}
作用:查询Item
细节:
第一步 查询itemId 对应Item
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{key:.+}
作用:查询该命名空间下指定key的Item
细节:
第一步 查询 appId clusterName namespacenname 对应的Namespace
第二步 查询该Namespace对应的Item中key为传入值的Item
ItemSetController
url: post /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/itemset
作用: 修改Namespace的Item
细节:
第一步 遍历changeSet中的 create update delete 集合
第二步 对对应的集合做出 创建 修改 删除 操作
第四步 保存commit
NamespaceBranchController
url: post /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches
作用: 创建namespace分支
细节:
第一步 判断 appId clusterName namespaceName 对应的Namespace是否存在
第二步 获取parentClusterName=cluster的所有cluster集合
第三步 获取所有 appId, namespaceName 的所有namespace集合
第四步 判断cluster集合中有名称跟 namespace的clusterName一致的
第五步 返回一致的 namespace/null
第六步 判断namespace是否存在 存在抛出已存在异常
第七步 获取clusterNmae=parentClusterName的cluster
第八步 创建新的cluster
第九步 保存cluster
第十步 创建namespace
第十一步 保存该namespace
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules
作用:查询指定namespace分支的灰度发布
细节:
第一步 判断 appId clusterName namespaceName 对应的Namespace是否存在
第二步 查找对应appId clusterName namespaceName branchName 对应的 GrayReleaseRule
第三步 返回 GrayReleaseRule
url: put /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}/rules
作用:修改 GrayReleaseRule 的规则 和状态
细节:
第一步 检查分支是否存在
第二步 设置灰度 GrayReleaseRule 的规则 和状态
第三步 根据 appId, clusterName, namespaceName, branchName 获取原来的 GrayReleaseRule
第四步 获取最近活跃状态的release(appId, branchName namespace)
第五步 配置新的 GrayReleaseRule 对应的 release 为上面获取到的
第六步 保存最新的 GrayReleaseRule
第七步 删除原来的老的 GrayReleaseRule
第八步 记录历史 ReleaseHistory
将老的 rules 和新的 rules 存入 ReleaseHistory
第九步 发送的RleaseMesage消息 key为appId+clusterName+namespaceName
url: delete /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches/{branchName}
作用: 删除分支
细节:
第一步 检测分支是否存在
第二步 通过 appId branchName 找到被删除的 cluster
第三步 找到 appId branchName namespaceName 对应的最新的有效的Release
第四步 创建一个rules为空的 GrayReleaseRule 灰度发布规则
第五步 找到appId, clusterName, namespaceName, branchName 对应的 GrayReleaseRule
第六步 找到appId, branchName, namespaceName 对应的 Release
第七步 设置新建的GrayReleaseRule的releaseId为 上面找到的release
第八步 保存新建的GrayReleaseRule
第九步 如果老的 GrayReleaseRule 存在 则删除老的 GrayReleaseRule
第十步 发送RleaseMesage消息 key为appId+clusterName+namespaceName
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/branches
作用:获取当前命名空间下的分支所有分支信息
细节:
第一步 检测分支是否存在
第二步 根据appId parentClusterName namespaceName 所有分支
NamespaceController
url: post /apps/{appId}/clusters/{clusterName}/namespaces
作用: 创建命名空间
细节:
第一步 验证命名空间的名称是否合法
第二步 判断当前 appId clusterName 下是否存在 名称为 name的namespaceName
第三步 保存新建的 namespace
url: delete /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName:.+}
作用:删除命名空间
细节:
第一步 检测该命名空间是否存在
第二步 删除该命名空间下的所有 Item
第三步 删除改名吗空间下的所有 commit
第四步 查找当前命名空间的分支
第五步 删除分支
第六步 删除分支的release
第七步 删除命名空间的releaseHistory
第八步 删除命名空间的InstanceConfig
第九步 删除该命名空间的锁
第十步 删除该命名空间
第十一步 发送appId+clusterName+namespaceName 为message的releaseMessage
url: get /apps/{appId}/clusters/{clusterName}/namespaces
作用: 查询该集群下的所有命名空间
细节:
根据appId clusterName 查询
url: get /namespaces/{namespaceId}
作用: 查询指定id的命名空间详情
细节:
根据namespaceId 查询
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName:.+}
作用: 查询指定 appId clusterName namespaceName 的命名空间详情
细节:
根据 appId clusterName namespaceName 查询
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/associated-public-namespace
作用: 查询指定 appId clusterName namespaceName 的命名空间详情
细节:
根据 clusterName namespaceName 查询 公共 AppNamespace
用指定的公共namespace查询namespace
url: get /apps/{appId}/namespaces/publish_info
作用: 公共命名空间的的公共信息
细节:
第一步 根据appid获取cluster集合
第二步 根据appid 和clusterName获取namespace集合
第三步 通过appNamespace验证是否为公共命名空间
第四步 返回还有公共命名空间的cluster
NamespaceLockController
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/lock
作用: 查询 指定参数下的命名空间的锁情况
ReleaseController
url: get /releases/{releaseId}
作用: 查询指定id的release
url: get /releases
作用: 查询指定id集合对应的release
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/all
作用:查询指定appId, clusterName, namespaceName参数的release
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/active
作用: 查询指定appId, clusterName, namespaceName参数的有效release
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/latest
作用: 查询指定appId, clusterName, namespaceName参数的最近的有效release
url: post /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases
作用: 创建release
细节:
第一步 检测 appId, clusterName, namespaceName 对应的namespace是否存在
第二步 检测namespace, isEmergencyPublish, operator 对应的 namespace是否已经加锁
第三步 获取当前namespace对应的配置 Item
第四步 获取当前namespace的上级namespace
第五步 获取最近的parantNamespace对应的Release
第六步 获取release的参数配置
第七步 合并relese中配置参数和namespace对应Item配置参数
第八步 获取子命名空间的最新有效的release
第九步 创建一个新的release
第十步 根据父命名空间和自命名空间 创建新的灰度发布
第十一步 创建ReleaseHistory
第十二步 合并主从公共分支命名空间
第十三步 发送appId, messageCluster, namespaceName 的releaseMessage 其中 messageCluster为当前命名空间所在的集群
url: post /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/updateAndPublish
作用: 修改release 并发布
细节:
第一步 检查 appId, clusterName, namespaceName 是否存在
第二步 检查原来的release和新的release 得到修改集合
第三步 发送appId, messageCluster, namespaceName 的releaseMessage
url: put /releases/{releaseId}/rollback
作用: 回滚release 并发布
ReleaseHistoryController
url: get /apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/releases/histories
作用: 获取 appId, clusterName namespaceName 历史发布信息
url: get /releases/histories/by_release_id_and_operation
作用: 获取 指定releaseId的历史发布
url: get /releases/histories/by_previous_release_id_and_operation
作用: 获取前一个relese 的历史发布
**五种权限 **
CreateNamespace 创建命名空间的权限
CreateCluster 创建集群的权限
AssignRole 赋值角色的权限
ModifyNamespace 修改命名空间的权限
ReleaseNamespace 发布命名空间的权限
**创建项目**
portalService
传递参数
name 应用名称
appId 应用id
orgId 组织架构id
orgName 组织架构名称
ownerName 应用负责人
保存数据到APP表
创建appNamespace
appId 应用Id
name application
comment 备注
format 配置数据格式
createBy 创建人
保存数据到AppNamespace
创建Permission
permissionType 权限类型(CreateCluster CreateNamespace AssignRole 三个都要)
targetId 权限对应的目标应用id(appId)
创建role
roleName 角色名称('Master'+appId)
createBy 创建人
创建rolePermission
roleId 角色Id
permissionId 权限id
创建userRole
roleId 角色Id
userId 用户Id
创建Permission
permissionType 权限类型(ModifyNamespace ReleaseNamespace 两个都要)
targetId 权限对应的目标应用id(appId)
创建role
roleName 角色名称('ModifyNamespace'+appId+namespaceName)/('ReleaseNamespace'+appId+namespaceName)
createBy 创建人
创建rolePermission
roleId 角色Id
permissionId 权限id
创建userRole
roleId 角色Id
userId 用户Id
通过ApplicationEventPublisher发布AppCreationEvent(继承 ApplicationEvent)事件
CreationListener 接收该事件 遍历Env(以便获取环境(dev,pro,uat...))
调用API 接口 向Adminservice 发送创建APP
adminService
保存传送过来的App数据(完整的) 插入一条审计
创建AppNamespace
appId 应用id
name 命名空间名称('application')
comment 备注
format 格式(properties)
保存数据 插入一条审计
创建Cluster
name 集群名称(default)
appId 应用id
保存数据 插入一条审计
根据appId获取AppNamespace遍历
创建Namespace
appId 应用id
clusterName 集群名称(default)
namespaceName 命名空间名称('application')
保存数据 插入一条审计
**apollo.biz.entity.ReleaseMessage**
组成:
message=appId+clusterName+namespaceName
id=JPA生成
作用: 用于配置发布的消息
**apollo.biz.grayReleaseRule.GrayReleaseRulesHolder**(处理ReleaseMessage,用缓存对外提供最新的有效GrayReleaseRule版本)
组成:
缓存:grayReleaseRuleCache(key=appId+clusterName+namespace value=GrayReleaseRuleCache)
缓存:reversedGrayReleaseRuleCache(key=appId+namespace+clientIp value=ruleId)
缓存:GrayReleaseRuleCache(ruleId branchName namespace releaseId branchStatus rules<clientAppId, set<clientIp>> loadVersion)
灰度规则: GrayReleaseRule(id branchName namespaceName releaseId branchStatus rules appId clusterName) 其中(id 对应 上面的 ruleId)
加载版本:loadVersion
定时器: 定时从数据库加载 GrayReleaseRules 进行与缓存数据合并
作用1: 对外提供判断是否存在(appId+namespace+clientIp)对应的有效灰度发布规则(GrayReleaseRule)
作用2: 对外提供获取(configAppId, configCluster, configNamespaceName| clientAppId, clientIp)releseId的接口
作用3: 监听ReleaseMessage的发布。
一旦有ReleaseMessage监听到,那么就将message切成
appId clusterName namespaceName
然后使用这个参数去数据库获取 GrayReleaseRules
将获取到的 GrayReleaseRules 跟缓存比较进行合并
作用4: 定时器不断的从数据库扫描GrayReleaseRule(每扫描一次 loadVersion+1, 每次扫描记录最新的id,然后从最新的id开始扫)
将扫描到的 GrayReleaseRule 跟缓存比较合并
合并细节:
第一步 遍历传入的 GrayReleaseRules
第二步 判断遍历的 GrayReleaseRule 的releaseId为空或者为0直接跳过
第三步 从缓存(grayReleaseRuleCache)中获取 GrayReleaseRuleCache 集合
(通过key=GrayReleaseRule.appId+GrayReleaseRule.clusterName+GrayReleaseRule.namespaceName)
第四步 遍历缓存中取出来的GrayReleaseRuleCache集合
找到其中 GrayReleaseRuleCache.branchName==GrayReleaseRule.branchName 的 GrayReleaseRuleCache
第五步 判断上面缓存中相同分支的 GrayReleaseRuleCache 不存在且当前 GrayReleaseRule 的分支状态为非有效,那么直接跳过,遍历下一个
第六步 没有找到当前GrayReleaseRule对应的缓存,那么将当前 GrayReleaseRule 加入到缓存中
首先 将当前GrayReleaseRule转为GrayReleaseRuleCache
然后 key=GrayReleaseRule.appId+GrayReleaseRule.clusterName+GrayReleaseRule.namespaceName
value=GrayReleaseRuleCache 放入grayReleaseRuleCache缓存
最后 如果发现分支状态为有效那么遍历 rules<clientAppId, set<clientIp>> 集合
再遍历 clientIp集合
然后将每次遍历到 clientAppId+namespaceName+clientIp 作为key ruleId作为value
放入reversedGrayReleaseRuleCache缓存中
如果找到当前GrayReleaseRule对应的缓存,但是当前GrayReleaseRule的id大于对应缓存的ruleId,那么需要将原有的缓存清掉
首先 根据key和GrayReleaseRuleCache 清掉grayReleaseRuleCache缓存
然后 根据grayReleaseRuleCache对应出的 clientAppId+namespaceName+clientIp,ruleId 清掉reversedGrayReleaseRuleCache缓存
如果缓存存在,且GrayReleaseRule的id不大于对应缓存的ruleId 那么
如果当前缓存的分支状态为有效 那么将缓存中的loadVersion更新为当前扫描版本
如果当前缓存的分支状态为非有效,那么如果当前loadVersion版本大于缓存的版本,则将对应的多有缓存删除
**apollo.biz.message.DatabaseMessageSender**
组成:
阻塞队列:用于缓存ReleaeMessage的id
定时器:则清理数据库中的比缓存队列中id值小但具有相同message的RleaseMessage
主要作用:
接收ReleaseMessage,并存入数据库
定时扫描删除数据库中id小于缓存队列中的id,且message相同的ReleaseMessage
作用1: 向数据库存储ReleaseMessage
作用2: 清理数据库中的ReleaseMessage
作用细节:
接收外部通过调用SendMessage接口发送的ReleaseMessage,存入数据库,并将该releaseMessage的Id放入阻塞队列
定时扫描阻塞队列,获取到Id后,删除数据库中小于当前id的同类型message的ReleaseMessage
**apollo.biz.message.ReleaseMessageScanner**
组成:
定时器:定时向数据扫描ReleaseMessage,通过监听器集合,将所有的ReleaseMessage发送给监听器
监听器集合:监听处理ReleaseMessage
作用:
将定时扫描数据库得到ReleaseMessage通过监听器发出去处理(只扫描比当前已扫描到的id大的)
**apollo.configservice.controller.ConfigFileController**
组成:
缓存:watchedKeys2CacheKey <key,value>=<ReleaseMessage.message, outputFormat+appId+clusterName+namespace+dataCenter>
=>
<key,value>=<appId+clusterName+namespace, outputFormat+appId+clusterName+namespace+dataCenter>
缓存:cacheKey2WatchedKeys <key,value>=<outputFormat+appId+clusterName+namespace+dataCenter, ReleaseMessage.message>
=>
<key,value>=<outputFormat+appId+clusterName+namespace+dataCenter, appId+clusterName+namespace>
缓存:localCache <key,value>=<outputFormat+appId+clusterName+namespace+dataCenter, 命名空间的Items配置数据的json>
监听处理器接口: 用于清理掉localCache中ReleaseMessage的message对应的数据
作用:
1,对外提供获取配置的接口(properties json 两种格式)
2,监听ReleaseMessage,如果监听到,则将上面三个缓存中对应ReleaseMessage.message<appId+clusetName+namespace>缓存清掉
详解获取配置过程:
第一步 根据appId clientIp namespace 判断当前是否存在有效的灰度发布
第二步 如果有灰度发布,
调用 ConfigController 去获取对应的配置实体,再封装成对应的格式返回
第三步 没有灰度发布,
但通过 outputFormat+appId+clusterName+namespace+dataCenter生成的key
可以在localCache中找到已有的缓存,返回缓存
第四步 没有灰度发布也没有缓存
调用 ConfigController 去获取对应的配置实体,再封装成对应的格式返回
配置为空直接返回null
配置存在,
那么再次检测是否存在灰度发布,如果有,则封装对应的格式返回
配置存在,且没有灰度发布,
那么当前获取到的配置缓存到localCache<outputFormat+appId+clusterName+namespace+dataCenter, 配置>
根据appId clusterName namespace dataCenter 生成watchedKeys集合
将这些watchedKeys和cacheKey 存入 watchedKeys2CacheKey<watchedKey, cacheKey>
同时将watchedKeys和cacheKey 存入cacheKey2WatchedKeys<cacheKey, watchedKey>
watchedKeys生成规则(appId, clusterName, namespace, dataCenter):
第一步 判断clusterName是不是default 如果不是则生成一个 watchedKey=appId+clusterName+namespace
第二步 判断dataCenter不为空,且dataCenter和cluster不一致 则生成 watchedKey=appId+dataCenter+namespace
第三步 添加一个 watchedKey=appId+"default"+namespace
第四步 判断namespace是否是application,因为每个应用都有一个默认的application的命名空间
第五步 如果不是application,那么则需要去appNamespace去校对下 namespace和appId是否匹配
第六步 如果有不匹配的,那么需要找到那些不匹配的,但却是appId关联的公共的namespace
第七步 根据一,二,三步生成新的watchedKey
详解ConfigController获取配置的过程:
第一步 判断clusterName不是default,那么从 GrayReleaseRulesHolder获取灰度发布的releaseId
如果releaseId存在,则直接获取Release Release
不存在,则通过configAppId, configClusterName, configNamespace获取Rlease 返回
第二步 判断cluster和dataCenter不一致,那么datcenter替换cluster通过GrayReleaseRulesHolder获取灰度发布的releaseId存在
如果releaseId存在,则直接获取Release
不存在,则通过configAppId, configClusterName, configNamespace获取Rlease
第三步 cluster=default,通过GrayReleaseRulesHolder获取灰度发布的releaseId存在
如果releaseId存在,则直接获取Release
不存在,则通过configAppId, configClusterName, configNamespace获取Release
第四步 判断当前的namespace是否和appId一致,
如果不一致,则获取当前namespace为公共命名空间的appId,并用这个appId重复上面三步获取Release
第五步 审核Release集合,生成InstanceConfig和Instance
第六步 合成Rlelease集合的releaseKey。
第七步 将Release集合中的配置合并
第八步 将合并后的配置以及appId, appClusterNameLoaded, originalNamespace, mergedReleaseKey 生成ApolloConfig返回
**apollo.configservice.controller.NotificationControllerV2**
组件:
定时器: 用于当需要的通知的client太多的时候进行异步处理
缓存:用于缓存DeferredResultWrapper里面包括DeferredResult
作用1: 接受client端不超过30s的长轮询,客户端每次都发送上次接收到的ApolloConfigNotification
收到客户端的ApolloConfigNotification,比较是否产生新的ReleaseMessage,如果有则填充新的
生成新的ApolloConfigNotification,使用Spring DeferredResult返回 (可以异步产生ApolloConfigNotification)
作用2: 监听ReleaseMessage,如果有新的ReleaseMessage产生并发送过来,
那么
第一步 获取ReleaseMessage中的需要改变的namespace
第二步 获取客户端长轮询中暂时还存在的DeferredResult集合 通过ReleaseMessage.message
第三步 根据ReleaseMessage生成一个新的ApolloConfigNotification
第四步 判断DeferredResult集合中的个数,是否超过一次发送通知的限额
没有 则直接发送,超过 则通过定时器异步发送
**apollo.configservice.service.ReleaseMessageServiceWithCache**
组件:
定时器:用于定时从数据库加载ReleaseMessage 只加载比当前的id大的ReleaseMessage
监听器: 用于监听ReleaseMessage的产生
缓存: releaseMessageCache<ReleaseMessage.message, ReleaseMessage>
作用1:
定时器定时加载ReleaseMessage,加载到的数据进行合并,然后存到缓存
作用2:
接收ReleaseMessage,判断接收到的 ReleaseMessage.id 是否大于等于
如果等于1 则直接合并
如果大于1 则直接使用maxIdScanned从数据库加载
**apollo.configservice.service.config.ConfigServiceWithCache**
组件:
缓存:configCache<ReleaseMessage.message, ConfigCacheEntry>
缓存:configIdCache<ReleaseMessage.id, Release>
缓存:ConfigCacheEntry<ReleaseMessage.id, Release>
监听器: 用于监听ReleaseMessage的产生 让configCache缓存区加载最新的Release
作用:
对外提供最新的Release
**apollo.configservice.util.InstanceConfigAuditUtil**
组件:
缓存队列:audits<InstanceConfigAuditModel> 阻塞队列
用于存储Rlease的实例化配置数据
<appId clusterName dataCenter ip configAppId configClusterName configNamespace releaseKey offerTime>
缓存:instanceCache<String, Long> => <appId+cluster+ip+dataCenter, instanceId>
缓存:instanceConfigReleaseKeyCache<String, String>=><instanceId+configAppId+configNamespace, releaseKey>
releaseKey=appId,cluster,namespace的哈希值 和当前机器码 以及产生的次数和日期 => 日期-xxxx
定时器:从阻塞队列中获取InstanceConfigAuditModel 刷新 instanceCache instanceConfigReleaseKeyCache
作用: 生成InstanceCOnfig 和 Instance
细节:
第一步 根据appId+cluster+ip+dataCenter生成instanceCacheKey
第二步 查看instanceCache缓存中是否存在该instanceCacheKey对应的instanceId
第三步 判断instanceId不存在,那么
去数据中取,没有取到 则创建一个Instance 并存储到数据库。
将instanceCacheKey=instance存入缓存
第四步 根据instanceId+configAppId+configNamespace生成instanceConfigCacheKey
第五步 取instanceConfigReleaseKeyCache缓存,判断是否存在对应的releaseKey
如果存在,则该次InstanceConfigAuditModel结束
第六步 根据instanceId configAppId configNamespace 从数数库获取 InstanceConfig
第七步 如果InstanceConfig存在 则
如果InstanceConfig.releaseKey跟InstanceConfigAuditModel.releaseKey不同,则更新offerTime,cluster,releaseKey
如果InstanceConfig.releaseKey跟InstanceConfigAuditModel.releaseKey相同,且在十分钟以内,直接返回
如果不在十分钟内 则更新修改时间。存储到数据库
第八步 InstanceConfig不存在 则生成性的InstanceConfig存入数据库
**apollo-core**
提供基础的核心功能:
功能1:
提供调度策略接口,提供默认的指数级扩展调度策略
功能2:
提供读取/config/下配置文件的功能
功能3:
提供获取dev fat uat lpt pro 域名地址接口(通过读取/config/app-env.properties)
功能4:
提供日志打印接口,用于外接日志打印处理
功能4:
基础信息提供 如
appId, 读取 /META-INF/app.properties配置文件
host.address
host.name
m_env m_dc
**apollo-common**
提供核心功能:
功能1:
通过AOP打印所有Repository数据库操作
功能2:
提供RefreshablePropertySource抽象类,子类可以通过refresh接口刷新所需要提供的配置参数,系统定时刷新
功能3:
提供配置tomcat接收连接数的限制 即参数 server.tomcat.accept-count
功能4:
配置springboot的一些web基本配置
如 ContentNegotiation
mimeMapping
messageConvert
全局异常处理@ControllerAdvice
字符编码设置 FilterRegistrationBean
功能4:
提供获取系统基本信息 applicationProvide ip 版本 ServerProcerder
**apollo-biz**
提供核心功能:
功能1:
配置全局 security 提供默认用户 apollo
功能2:
提供灰度发布缓存,用于缓存GrayReleaseRule
每一个RleaseMessage被接受到都会对应一个GrayReleaseRule
GrayReleaseRule对应一个Release
功能3:
提供ReleaseMessage的发送和监听以及数据库扫描接口,用于处理ReleaseMessage
功能4:
提供创建命名空间分支的功能(分支功能是由cluster实现的)
功能5:
提供配置发布功能
分为三种情况
情况1: 发布配置的命名空间带有父分支,那么 将父分支的配置跟当前分支的配置合并,对外发布GRAY_RELEASE类型的配置
情况2: 父分支不存在,则发布当前命名空间的NORMAL_RELEASE类型配置
情况3: 如果当前分支还含有子分支,那么将当前分支的配置和子分支配置合并,
发布MASTER_NORMAL_RELEASE_MERGE_TO_GRAY类型的配置
可以归纳为两种 主分支发布 子分支发布
如果当前分支有父分支,那么获取主分支的配置合并到当前分支 发布到子分支
如果只有当前分支,那么当前分支为主分支,发布到主分支
如果当前分支有子分支,那么合并当前分支的配置到子分支,发布当前分支的同时,发布子分支
**apollo-configservice**
提供核心功能:
功能1: 提供配置获取功能
功能2:功能配置文件获取功能,监听Releasemessage 更新配置文件缓存
功能3:提供http轮询功能 监听ReleaseMessage,提供DeffereResult返回
上述三个功能合并就是:
由功能3的监听到ReleaseMessage,将消息发送给长轮询的客户端,
客户端收到这个消息后,进行json化,然后去到功能1或功能2获取配置
**apollo-adminservice**
提供核心功能:
功能1: 对命名空间加锁 和解锁功能
功能2: 提供App appNamespace cluster commit InstacneConfig
Item namespacebrance namespace namespaceLock Release ReleaseHistroy
的增删改查功能
**apollo-portal**
提供核心功能:
功能1:
提供全新管控
Permission(appId 权限类型) CreateNamespace CreateCluster AssignRole ModifyNamespace ReleaseNamespace
Role(类型+appId) Master ModifyNamespace ReleaseNamespace
RolePermission
User
UserRole
来进行全新管控
功能2:
用户添加 以及改用户权限设置 token有效验证
功能3:
异步添加Namepsace App 以及 Release
功能4:
对接apollo-admin接口的功能