274 lines
8.4 KiB
Go
274 lines
8.4 KiB
Go
|
/*
|
||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||
|
* contributor license agreements. See the NOTICE file distributed with
|
||
|
* this work for additional information regarding copyright ownership.
|
||
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||
|
* (the "License"); you may not use this file except in compliance with
|
||
|
* the License. You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package agollo
|
||
|
|
||
|
import (
|
||
|
"container/list"
|
||
|
"errors"
|
||
|
|
||
|
"github.com/apolloconfig/agollo/v4/agcache"
|
||
|
"github.com/apolloconfig/agollo/v4/agcache/memory"
|
||
|
"github.com/apolloconfig/agollo/v4/cluster/roundrobin"
|
||
|
"github.com/apolloconfig/agollo/v4/component"
|
||
|
"github.com/apolloconfig/agollo/v4/component/log"
|
||
|
"github.com/apolloconfig/agollo/v4/component/notify"
|
||
|
"github.com/apolloconfig/agollo/v4/component/remote"
|
||
|
"github.com/apolloconfig/agollo/v4/component/serverlist"
|
||
|
"github.com/apolloconfig/agollo/v4/constant"
|
||
|
"github.com/apolloconfig/agollo/v4/env"
|
||
|
"github.com/apolloconfig/agollo/v4/env/config"
|
||
|
jsonFile "github.com/apolloconfig/agollo/v4/env/file/json"
|
||
|
"github.com/apolloconfig/agollo/v4/extension"
|
||
|
"github.com/apolloconfig/agollo/v4/protocol/auth/sign"
|
||
|
"github.com/apolloconfig/agollo/v4/storage"
|
||
|
"github.com/apolloconfig/agollo/v4/utils"
|
||
|
"github.com/apolloconfig/agollo/v4/utils/parse/normal"
|
||
|
"github.com/apolloconfig/agollo/v4/utils/parse/properties"
|
||
|
"github.com/apolloconfig/agollo/v4/utils/parse/yaml"
|
||
|
"github.com/apolloconfig/agollo/v4/utils/parse/yml"
|
||
|
)
|
||
|
|
||
|
const separator = ","
|
||
|
|
||
|
func init() {
|
||
|
extension.SetCacheFactory(&memory.DefaultCacheFactory{})
|
||
|
extension.SetLoadBalance(&roundrobin.RoundRobin{})
|
||
|
extension.SetFileHandler(&jsonFile.FileHandler{})
|
||
|
extension.SetHTTPAuth(&sign.AuthSignature{})
|
||
|
|
||
|
// file parser
|
||
|
extension.AddFormatParser(constant.DEFAULT, &normal.Parser{})
|
||
|
extension.AddFormatParser(constant.Properties, &properties.Parser{})
|
||
|
extension.AddFormatParser(constant.YML, &yml.Parser{})
|
||
|
extension.AddFormatParser(constant.YAML, &yaml.Parser{})
|
||
|
}
|
||
|
|
||
|
var syncApolloConfig = remote.CreateSyncApolloConfig()
|
||
|
|
||
|
//Client apollo 客户端接口
|
||
|
type Client interface {
|
||
|
GetConfig(namespace string) *storage.Config
|
||
|
GetConfigAndInit(namespace string) *storage.Config
|
||
|
GetConfigCache(namespace string) agcache.CacheInterface
|
||
|
GetDefaultConfigCache() agcache.CacheInterface
|
||
|
GetApolloConfigCache() agcache.CacheInterface
|
||
|
GetValue(key string) string
|
||
|
GetStringValue(key string, defaultValue string) string
|
||
|
GetIntValue(key string, defaultValue int) int
|
||
|
GetFloatValue(key string, defaultValue float64) float64
|
||
|
GetBoolValue(key string, defaultValue bool) bool
|
||
|
GetStringSliceValue(key string, defaultValue []string) []string
|
||
|
GetIntSliceValue(key string, defaultValue []int) []int
|
||
|
AddChangeListener(listener storage.ChangeListener)
|
||
|
RemoveChangeListener(listener storage.ChangeListener)
|
||
|
GetChangeListeners() *list.List
|
||
|
UseEventDispatch()
|
||
|
Close()
|
||
|
}
|
||
|
|
||
|
// internalClient apollo 客户端实例
|
||
|
type internalClient struct {
|
||
|
initAppConfigFunc func() (*config.AppConfig, error)
|
||
|
appConfig *config.AppConfig
|
||
|
cache *storage.Cache
|
||
|
configComponent *notify.ConfigComponent
|
||
|
}
|
||
|
|
||
|
func (c *internalClient) getAppConfig() config.AppConfig {
|
||
|
return *c.appConfig
|
||
|
}
|
||
|
|
||
|
func create() *internalClient {
|
||
|
appConfig := env.InitFileConfig()
|
||
|
return &internalClient{
|
||
|
appConfig: appConfig,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Start 根据默认文件启动
|
||
|
func Start() (Client, error) {
|
||
|
return StartWithConfig(nil)
|
||
|
}
|
||
|
|
||
|
// StartWithConfig 根据配置启动
|
||
|
func StartWithConfig(loadAppConfig func() (*config.AppConfig, error)) (Client, error) {
|
||
|
// 有了配置之后才能进行初始化
|
||
|
appConfig, err := env.InitConfig(loadAppConfig)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
c := create()
|
||
|
if appConfig != nil {
|
||
|
c.appConfig = appConfig
|
||
|
}
|
||
|
|
||
|
c.cache = storage.CreateNamespaceConfig(appConfig.NamespaceName)
|
||
|
appConfig.Init()
|
||
|
|
||
|
serverlist.InitSyncServerIPList(c.getAppConfig)
|
||
|
|
||
|
//first sync
|
||
|
configs := syncApolloConfig.Sync(c.getAppConfig)
|
||
|
if len(configs) == 0 && appConfig != nil && appConfig.MustStart {
|
||
|
return nil, errors.New("start failed cause no config was read")
|
||
|
}
|
||
|
|
||
|
for _, apolloConfig := range configs {
|
||
|
c.cache.UpdateApolloConfig(apolloConfig, c.getAppConfig)
|
||
|
}
|
||
|
|
||
|
log.Debug("init notifySyncConfigServices finished")
|
||
|
|
||
|
//start long poll sync config
|
||
|
configComponent := ¬ify.ConfigComponent{}
|
||
|
configComponent.SetAppConfig(c.getAppConfig)
|
||
|
configComponent.SetCache(c.cache)
|
||
|
go component.StartRefreshConfig(configComponent)
|
||
|
c.configComponent = configComponent
|
||
|
|
||
|
log.Info("agollo start finished ! ")
|
||
|
|
||
|
return c, nil
|
||
|
}
|
||
|
|
||
|
//GetConfig 根据namespace获取apollo配置
|
||
|
func (c *internalClient) GetConfig(namespace string) *storage.Config {
|
||
|
return c.GetConfigAndInit(namespace)
|
||
|
}
|
||
|
|
||
|
//GetConfigAndInit 根据namespace获取apollo配置
|
||
|
func (c *internalClient) GetConfigAndInit(namespace string) *storage.Config {
|
||
|
if namespace == "" {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
config := c.cache.GetConfig(namespace)
|
||
|
|
||
|
if config == nil {
|
||
|
//init cache
|
||
|
storage.CreateNamespaceConfig(namespace)
|
||
|
|
||
|
//sync config
|
||
|
syncApolloConfig.SyncWithNamespace(namespace, c.getAppConfig)
|
||
|
}
|
||
|
|
||
|
config = c.cache.GetConfig(namespace)
|
||
|
|
||
|
return config
|
||
|
}
|
||
|
|
||
|
//GetConfigCache 根据namespace获取apollo配置的缓存
|
||
|
func (c *internalClient) GetConfigCache(namespace string) agcache.CacheInterface {
|
||
|
config := c.GetConfigAndInit(namespace)
|
||
|
if config == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return config.GetCache()
|
||
|
}
|
||
|
|
||
|
//GetDefaultConfigCache 获取默认缓存
|
||
|
func (c *internalClient) GetDefaultConfigCache() agcache.CacheInterface {
|
||
|
config := c.GetConfigAndInit(storage.GetDefaultNamespace())
|
||
|
if config != nil {
|
||
|
return config.GetCache()
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
//GetApolloConfigCache 获取默认namespace的apollo配置
|
||
|
func (c *internalClient) GetApolloConfigCache() agcache.CacheInterface {
|
||
|
return c.GetDefaultConfigCache()
|
||
|
}
|
||
|
|
||
|
//GetValue 获取配置
|
||
|
func (c *internalClient) GetValue(key string) string {
|
||
|
return c.GetConfig(storage.GetDefaultNamespace()).GetValue(key)
|
||
|
}
|
||
|
|
||
|
//GetStringValue 获取string配置值
|
||
|
func (c *internalClient) GetStringValue(key string, defaultValue string) string {
|
||
|
return c.GetConfig(storage.GetDefaultNamespace()).GetStringValue(key, defaultValue)
|
||
|
}
|
||
|
|
||
|
//GetIntValue 获取int配置值
|
||
|
func (c *internalClient) GetIntValue(key string, defaultValue int) int {
|
||
|
return c.GetConfig(storage.GetDefaultNamespace()).GetIntValue(key, defaultValue)
|
||
|
}
|
||
|
|
||
|
//GetFloatValue 获取float配置值
|
||
|
func (c *internalClient) GetFloatValue(key string, defaultValue float64) float64 {
|
||
|
return c.GetConfig(storage.GetDefaultNamespace()).GetFloatValue(key, defaultValue)
|
||
|
}
|
||
|
|
||
|
//GetBoolValue 获取bool 配置值
|
||
|
func (c *internalClient) GetBoolValue(key string, defaultValue bool) bool {
|
||
|
return c.GetConfig(storage.GetDefaultNamespace()).GetBoolValue(key, defaultValue)
|
||
|
}
|
||
|
|
||
|
//GetStringSliceValue 获取[]string 配置值
|
||
|
func (c *internalClient) GetStringSliceValue(key string, defaultValue []string) []string {
|
||
|
return c.GetConfig(storage.GetDefaultNamespace()).GetStringSliceValue(key, separator, defaultValue)
|
||
|
}
|
||
|
|
||
|
//GetIntSliceValue 获取[]int 配置值
|
||
|
func (c *internalClient) GetIntSliceValue(key string, defaultValue []int) []int {
|
||
|
return c.GetConfig(storage.GetDefaultNamespace()).GetIntSliceValue(key, separator, defaultValue)
|
||
|
}
|
||
|
|
||
|
func (c *internalClient) getConfigValue(key string) interface{} {
|
||
|
cache := c.GetDefaultConfigCache()
|
||
|
if cache == nil {
|
||
|
return utils.Empty
|
||
|
}
|
||
|
|
||
|
value, err := cache.Get(key)
|
||
|
if err != nil {
|
||
|
log.Errorf("get config value fail! key:%s, error:%v", key, err)
|
||
|
return utils.Empty
|
||
|
}
|
||
|
|
||
|
return value
|
||
|
}
|
||
|
|
||
|
// AddChangeListener 增加变更监控
|
||
|
func (c *internalClient) AddChangeListener(listener storage.ChangeListener) {
|
||
|
c.cache.AddChangeListener(listener)
|
||
|
}
|
||
|
|
||
|
// RemoveChangeListener 增加变更监控
|
||
|
func (c *internalClient) RemoveChangeListener(listener storage.ChangeListener) {
|
||
|
c.cache.RemoveChangeListener(listener)
|
||
|
}
|
||
|
|
||
|
// GetChangeListeners 获取配置修改监听器列表
|
||
|
func (c *internalClient) GetChangeListeners() *list.List {
|
||
|
return c.cache.GetChangeListeners()
|
||
|
}
|
||
|
|
||
|
// UseEventDispatch 添加为某些key分发event功能
|
||
|
func (c *internalClient) UseEventDispatch() {
|
||
|
c.AddChangeListener(storage.UseEventDispatch())
|
||
|
}
|
||
|
|
||
|
// Close 停止轮询
|
||
|
func (c *internalClient) Close() {
|
||
|
c.configComponent.Stop()
|
||
|
}
|