golang集成apollo

417 阅读2分钟

本文以github.com/apolloconfig/agollo/v4 这个库举例子

1、构建及启动

启动命令:

client, err := agollo.StartWithConfig(func() (*config.AppConfig, error) {
   return c, nil
})

启动相关apollo配置填充

type AppConfig struct {
   AppID             string `json:"appId"`
   Cluster           string `json:"cluster"`
   NamespaceName     string `json:"namespaceName"`
   IP                string `json:"ip"`
   IsBackupConfig    bool   `default:"true" json:"isBackupConfig"`
   BackupConfigPath  string `json:"backupConfigPath"`
   Secret            string `json:"secret"`
   Label             string `json:"label"`
   SyncServerTimeout int    `json:"syncServerTimeout"`
   // MustStart 可用于控制第一次同步必须成功
   MustStart               bool `default:"false"`
   notificationsMap        *notificationsMap
   currentConnApolloConfig *CurrentApolloConfig
}

获取val

client.GetApolloConfigCache().Set()

监听器更新本地的缓存

type CustomChangeListener struct {
   wg sync.WaitGroup
}

func (c *CustomChangeListener) OnChange(changeEvent *storage.ChangeEvent) {
   //write your code here
   for key, value := range changeEvent.Changes {
      localConfig.configMap[key] = fmt.Sprintf("%v", value.NewValue)
   }
}

func (c *CustomChangeListener) OnNewestChange(event *storage.FullChangeEvent) {
   //write your code here
}


// storage.ChangeListener, 实现这个监听器
type ChangeListener interface {
   //OnChange 增加变更监控
   OnChange(event *ChangeEvent)

   //OnNewestChange 监控最新变更
   OnNewestChange(event *FullChangeEvent)
}

func main() {
    c2 := &CustomChangeListener{}
    c2.wg.Add(5)
    client.apolloClient.AddChangeListener(c2)
    c2.wg.Wait()
}

设置发布、远程的配置 www.apolloconfig.com/#/zh/usage/…

image.png

2、完整代码demo

package apollo-manager

import (
   "fmt"
   "github.com/apolloconfig/agollo/v4/storage"
   "sync"
    "context"
    "github.com/apolloconfig/agollo/v4"
    "github.com/apolloconfig/agollo/v4/env/config"
    "gitlab.spatio-inc.com/image/lego/components/httplib"
    "gitlab.spatio-inc.com/image/lego/pkg/app"
)

var cocenter *ConfClient
var localConfig = new(cacheConfig)


type ConfClient struct {
   apolloClient  agollo.Client
   appConfig     *config.AppConfig
   env           string
   portalAddress string
}

type ConfClient struct {
   apolloClient  agollo.Client
   appConfig     *config.AppConfig
   env           string
   portalAddress string
}

func BuildClient(appID, nameSpace, Cluster string, options ...OptionFunc) error {
   localConfig.configMap = map[string]string{}
   c := &config.AppConfig{
      AppID:         appID,
      Cluster:       Cluster,
      NamespaceName: nameSpace,
   }
   appEnv := ""
   portalAddress := ""
   if os.Getenv("env")=="dev" {
      c.IP = DefaultHostDev
      appEnv = "DEV"
      portalAddress = PortalAddressDev
   } else if os.Getenv("env")=="test {
      c.IP = DefaultHostTest
      appEnv = "FAT"
      portalAddress = PortalAddressTest
   } else if os.Getenv("env")=="perf {
      c.IP = DefaultHostPerf
      appEnv = "UAT"
      portalAddress = PortalAddressPerf
   } else if os.Getenv("env")=="prod {
      c.IP = DefaultHostPerf
      appEnv = "PRO"
      portalAddress = PortalAddressProd
   }

   for _, f := range options {
      f(c)
   }

   tmp, err := agollo.StartWithConfig(func() (*config.AppConfig, error) {
      return c, nil
   })

   if err != nil {
      return err
   }
   go func() {
      c2 := &CustomChangeListener{}
      c2.wg.Add(5)
      cocenter = &ConfClient{tmp, c, appEnv, portalAddress}
      cocenter.apolloClient.AddChangeListener(c2)
      c2.wg.Wait()
   }()
   return nil
}

func (c *ConfClient) Get(ctx context.Context, key string) (string, error) {
   return localConfig.configMap[key], nil
}

func (c *ConfClient) Set(ctx context.Context, key string, value string, token string, modifiedBy string) (bool, error) {
   if c == nil || c.apolloClient == nil {
      return false, fmt.Errorf("client must be initialized")
   }

   url := fmt.Sprintf("%s/openapi/v1/envs/%s/apps/%s/clusters/%s/namespaces/%s/items/%s",
      c.portalAddress, c.env, c.appConfig.AppID, c.appConfig.Cluster, c.appConfig.NamespaceName, key)

   params := make(map[string]string)
   params["key"] = key
   params["value"] = value
   params["dataChangeLastModifiedBy"] = modifiedBy

   req := httplib.Put(url).Body(params).
      Header("Content-Type", "application/json;charset=UTF-8").
      Header("Authorization", token)
   _, err := req.DoRequest()
   if err != nil {
      return false, fmt.Errorf("update fail")
   }
   rls, err := release(c, token, modifiedBy)
   if err != nil {
      return false, fmt.Errorf("release fail")
   }
   return rls, nil
}

func release(c *ConfClient, token string, modifiedBy string) (bool, error) {
   if c == nil || c.apolloClient == nil {
      return false, fmt.Errorf("client must be initialized")
   }

   url := fmt.Sprintf("%s/openapi/v1/envs/%s/apps/%s/clusters/%s/namespaces/%s/releases",
      c.portalAddress, c.env, c.appConfig.AppID, c.appConfig.Cluster, c.appConfig.NamespaceName)

   params := make(map[string]string)
   params["releaseTitle"] = "update by code"
   params["releasedBy"] = modifiedBy
   req := httplib.Put(url).Body(params).
      Header("Content-Type", "application/json;charset=UTF-8").
      Header("Authorization", token)
   _, err := req.DoRequest()
   if err != nil {
      return false, fmt.Errorf("update by code fail")
   }
   return true, nil
}

type cacheConfig struct {
   sync.Mutex
   configMap map[string]string
}

type CustomChangeListener struct {
   wg sync.WaitGroup
}

func (c *CustomChangeListener) OnChange(changeEvent *storage.ChangeEvent) {
   //write your code here
   for key, value := range changeEvent.Changes {
      localConfig.configMap[key] = fmt.Sprintf("%v", value.NewValue)
   }
}

func (c *CustomChangeListener) OnNewestChange(event *storage.FullChangeEvent) {
   //write your code here
}