Apollo配置中心分析和详解

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接口的功能


        
                            
                        


                        
                        

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值