You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2020/10/30 09:14:59 UTC

[servicecomb-service-center] branch master updated: SCB-2094 Refactor config (#732)

This is an automated email from the ASF dual-hosted git repository.

tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git


The following commit(s) were added to refs/heads/master by this push:
     new e4887bc  SCB-2094 Refactor config (#732)
e4887bc is described below

commit e4887bcc51d8c2447dd6cf9f3146d2d88513eb89
Author: little-cui <su...@qq.com>
AuthorDate: Fri Oct 30 17:14:49 2020 +0800

    SCB-2094 Refactor config (#732)
---
 etc/conf/app.yaml                                  |  31 ++++++
 go.mod                                             |   1 +
 go.sum                                             |   2 +
 pkg/util/common.go                                 |   7 ++
 .../release/licenses/LICENSE-iancoleman-strcase    |  22 ++++
 server/command/command.go                          |   9 --
 server/config/config.go                            | 122 +++++++++++----------
 server/config/config_test.go                       |  13 ++-
 server/config/{types.go => options.go}             |  34 ++++--
 server/config/types.go                             |   5 +-
 server/config/util.go                              | 101 +++++++++++++++++
 server/config/{config_test.go => util_test.go}     |  29 ++---
 12 files changed, 273 insertions(+), 103 deletions(-)

diff --git a/etc/conf/app.yaml b/etc/conf/app.yaml
new file mode 100644
index 0000000..0e402a7
--- /dev/null
+++ b/etc/conf/app.yaml
@@ -0,0 +1,31 @@
+# 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.
+
+server:
+
+log:
+  level: DEBUG
+
+ssl:
+  mode: 0
+
+registry:
+
+  etcd:
+    cluster:
+      name: default
+      endpoints: http://127.0.0.1:2379
+      # (Optional) The endpoint of embedded etcd listen
+      managerEndpoint:
diff --git a/go.mod b/go.mod
index b7f5b12..ac58dc0 100644
--- a/go.mod
+++ b/go.mod
@@ -17,6 +17,7 @@ require (
 	github.com/golang/protobuf v1.3.2
 	github.com/gorilla/websocket v1.4.0
 	github.com/hashicorp/serf v0.8.3
+	github.com/iancoleman/strcase v0.1.2
 	github.com/karlseguin/ccache v2.0.3-0.20170217060820-3ba9789cfd2c+incompatible
 	github.com/labstack/echo v3.2.2-0.20180316170059-a5d81b8d4a62+incompatible
 	github.com/labstack/echo/v4 v4.1.17
diff --git a/go.sum b/go.sum
index 54b0055..950b1a4 100644
--- a/go.sum
+++ b/go.sum
@@ -179,6 +179,8 @@ github.com/hashicorp/serf v0.8.3/go.mod h1:UpNcs7fFbpKIyZaUuSW6EPiH+eZC7OuyFD+wc
 github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/iancoleman/strcase v0.1.2 h1:gnomlvw9tnV3ITTAxzKSgTF+8kFWcU/f+TgttpXGz1U=
+github.com/iancoleman/strcase v0.1.2/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE=
 github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
 github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
diff --git a/pkg/util/common.go b/pkg/util/common.go
index 93ed11a..3927bce 100644
--- a/pkg/util/common.go
+++ b/pkg/util/common.go
@@ -17,6 +17,8 @@
 
 package util
 
+import "os"
+
 type CtxKey string
 
 const (
@@ -27,3 +29,8 @@ const (
 	CtxRequestRevision  CtxKey = "requestRev"
 	CtxResponseRevision CtxKey = "responseRev"
 )
+
+func GetAppRoot() string {
+	workDir, _ := os.Getwd()
+	return GetEnvString("APP_ROOT", workDir)
+}
diff --git a/scripts/release/licenses/LICENSE-iancoleman-strcase b/scripts/release/licenses/LICENSE-iancoleman-strcase
new file mode 100644
index 0000000..3e87ff7
--- /dev/null
+++ b/scripts/release/licenses/LICENSE-iancoleman-strcase
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Ian Coleman
+Copyright (c) 2018 Ma_124, <github.com/Ma124>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, Subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or Substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/server/command/command.go b/server/command/command.go
index f46386b..e08ee75 100644
--- a/server/command/command.go
+++ b/server/command/command.go
@@ -18,7 +18,6 @@
 package command
 
 import (
-	"github.com/apache/servicecomb-service-center/server/config"
 	"github.com/apache/servicecomb-service-center/version"
 	"github.com/urfave/cli"
 )
@@ -29,14 +28,6 @@ func ParseConfig(args []string) (err error) {
 	app.Version = version.VERSION
 	app.Usage = "servicecomb service center server cmd line."
 	app.Name = "servicecomb service center"
-	app.Flags = []cli.Flag{
-		cli.StringFlag{
-			Name:        "config",
-			Usage:       "config file, example: --config=sc-conf.yaml",
-			Destination: &config.Configurations.ConfigFile,
-			Value:       "",
-		},
-	}
 	app.Action = func(c *cli.Context) error {
 		return nil
 	}
diff --git a/server/config/config.go b/server/config/config.go
index 05c810b..35fe5d7 100644
--- a/server/config/config.go
+++ b/server/config/config.go
@@ -19,8 +19,6 @@ package config
 
 import (
 	"github.com/go-chassis/go-archaius"
-	util2 "github.com/go-chassis/go-archaius/source/util"
-	"gopkg.in/yaml.v2"
 	"os"
 	"path/filepath"
 	"runtime"
@@ -30,7 +28,6 @@ import (
 	"github.com/apache/servicecomb-service-center/pkg/plugin"
 	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/version"
-	"github.com/astaxie/beego"
 )
 
 const (
@@ -57,27 +54,40 @@ var ServerInfo = NewServerInformation()
 func GetGov() Gov {
 	return Configurations.Gov
 }
+
+//GetServer return the http server configs
+func GetServer() ServerConfig {
+	return Configurations.Server.Config
+}
+
+//GetSSL return the ssl configs
+func GetSSL() ServerConfig {
+	return Configurations.Server.Config
+}
+
+//GetLog return the log configs
+func GetLog() ServerConfig {
+	return Configurations.Server.Config
+}
+
+//GetRegistry return the registry configs
+func GetRegistry() ServerConfig {
+	return Configurations.Server.Config
+}
+
 func Init() {
+	setCPUs()
+
 	err := archaius.Init(archaius.WithMemorySource(), archaius.WithENVSource(),
-		archaius.WithOptionalFiles([]string{""}))
+		archaius.WithOptionalFiles([]string{filepath.Join(util.GetAppRoot(), "conf", "app.yaml")}))
 	if err != nil {
 		log.Fatal("can not init archaius", err)
 	}
-
-	if Configurations.ConfigFile != "" {
-		if err := archaius.AddFile(Configurations.ConfigFile, archaius.WithFileHandler(util2.UseFileNameAsKeyContentAsValue)); err != nil {
-			log.Fatal("can not read config file: "+Configurations.ConfigFile, err)
-		}
-		_, filename := filepath.Split(Configurations.ConfigFile)
-		content := archaius.GetString(filename, "")
-		if err := yaml.Unmarshal([]byte(content), Configurations); err != nil {
-			log.Fatal("can not read config file: "+Configurations.ConfigFile, err)
-		}
-
+	err = archaius.UnmarshalConfig(Configurations)
+	if err != nil {
+		log.Fatal("archaius unmarshal config failed", err)
 	}
-
-	setCPUs()
-
+	Configurations.Server = ServerInfo
 	*ServerInfo = newInfo()
 
 	plugin.SetPluginDir(ServerInfo.Config.PluginsDir)
@@ -85,84 +95,80 @@ func Init() {
 	initLogger()
 
 	version.Ver().Log()
-
 }
 
 func newInfo() ServerInformation {
-	maxLogFileSize := beego.AppConfig.DefaultInt64("log_rotate_size", 20)
+	maxLogFileSize := GetInt64("log.rotateSize", 20, WithStandby("log_rotate_size"))
 	if maxLogFileSize <= 0 || maxLogFileSize > 50 {
 		maxLogFileSize = 20
 	}
-	maxLogBackupCount := beego.AppConfig.DefaultInt64("log_backup_count", 50)
+	maxLogBackupCount := GetInt64("log.backupCount", 50, WithStandby("log_backup_count"))
 	if maxLogBackupCount < 0 || maxLogBackupCount > 100 {
 		maxLogBackupCount = 50
 	}
 
-	serviceClearInterval, err := time.ParseDuration(os.Getenv("SERVICE_CLEAR_INTERVAL"))
-	if err != nil || serviceClearInterval < minServiceClearInterval || serviceClearInterval > maxServiceClearInterval {
+	serviceClearInterval := GetDuration("registry.service.clearInterval", defaultServiceClearInterval, WithENV("SERVICE_CLEAR_INTERVAL"))
+	if serviceClearInterval < minServiceClearInterval || serviceClearInterval > maxServiceClearInterval {
 		serviceClearInterval = defaultServiceClearInterval
 	}
 
-	serviceTTL, err := time.ParseDuration(os.Getenv("SERVICE_TTL"))
-	if err != nil || serviceTTL < minServiceTTL || serviceTTL > maxServiceTTL {
+	serviceTTL := GetDuration("registry.service.ttl", defaultServiceTTL, WithENV("SERVICE_TTL"))
+	if serviceTTL < minServiceTTL || serviceTTL > maxServiceTTL {
 		serviceTTL = defaultServiceTTL
 	}
 
-	cacheTTL, err := time.ParseDuration(
-		util.GetEnvString("CACHE_TTL", beego.AppConfig.DefaultString("cache_ttl", "")))
-	if err == nil && cacheTTL < minCacheTTL {
+	cacheTTL := GetDuration("registry.cache.ttl", minCacheTTL, WithENV("CACHE_TTL"), WithStandby("cache_ttl"))
+	if cacheTTL < minCacheTTL {
 		cacheTTL = minCacheTTL
 	}
-	accessLogFileFromConfig := beego.AppConfig.DefaultString("access_log_file", "./access.log")
-	accessLogFile := util.GetEnvString("SC_ACCESS_LOG_FILE", accessLogFileFromConfig)
+	accessLogFile := GetString("log.accessFile", "./access.log", WithENV("SC_ACCESS_LOG_FILE"), WithStandby("access_log_file"))
 
 	return ServerInformation{
 		Version: InitVersion,
 		Config: ServerConfig{
-			MaxHeaderBytes: int64(beego.AppConfig.DefaultInt("max_header_bytes", 16384)),
-			MaxBodyBytes:   beego.AppConfig.DefaultInt64("max_body_bytes", 2097152),
+			MaxHeaderBytes:    GetInt64("server.request.maxHeaderBytes", 16384, WithStandby("max_header_bytes")),
+			MaxBodyBytes:      GetInt64("server.request.maxBodyBytes", 2097152, WithStandby("max_body_bytes")),
+			ReadHeaderTimeout: GetString("server.request.headerTimeout", "60s", WithStandby("read_header_timeout")),
+			ReadTimeout:       GetString("server.request.timeout", "60s", WithStandby("read_timeout")),
+			IdleTimeout:       GetString("server.idle.timeout", "60s", WithStandby("idle_timeout")),
+			WriteTimeout:      GetString("server.response.timeout", "60s", WithStandby("write_timeout")),
 
-			ReadHeaderTimeout: beego.AppConfig.DefaultString("read_header_timeout", "60s"),
-			ReadTimeout:       beego.AppConfig.DefaultString("read_timeout", "60s"),
-			IdleTimeout:       beego.AppConfig.DefaultString("idle_timeout", "60s"),
-			WriteTimeout:      beego.AppConfig.DefaultString("write_timeout", "60s"),
+			LimitTTLUnit:     GetString("server.limit.ttl", "s", WithStandby("limit_ttl")),
+			LimitConnections: GetInt64("server.limit.connections", 0, WithStandby("limit_conns")),
+			LimitIPLookup:    GetString("server.limit.ipLookups", "RemoteAddr,X-Forwarded-For,X-Real-IP", WithStandby("limit_iplookups")),
 
-			LimitTTLUnit:     beego.AppConfig.DefaultString("limit_ttl", "s"),
-			LimitConnections: int64(beego.AppConfig.DefaultInt("limit_conns", 0)),
-			LimitIPLookup: beego.AppConfig.DefaultString("limit_iplookups",
-				"RemoteAddr,X-Forwarded-For,X-Real-IP"),
+			EnablePProf: GetInt("server.pprof.mode", 0, WithStandby("enable_pprof")) != 0,
 
-			SslEnabled:    beego.AppConfig.DefaultInt("ssl_mode", 1) != 0,
-			SslMinVersion: beego.AppConfig.DefaultString("ssl_min_version", "TLSv1.2"),
-			SslVerifyPeer: beego.AppConfig.DefaultInt("ssl_verify_client", 1) != 0,
-			SslCiphers:    beego.AppConfig.String("ssl_ciphers"),
+			SslEnabled:    GetInt("ssl.mode", 1, WithStandby("ssl_mode")) != 0,
+			SslMinVersion: GetString("ssl.minVersion", "TLSv1.2", WithStandby("ssl_min_version")),
+			SslVerifyPeer: GetInt("ssl.verifyClient", 1, WithStandby("ssl_verify_client")) != 0,
+			SslCiphers:    GetString("ssl.ciphers", "", WithStandby("ssl_ciphers")),
 
-			AutoSyncInterval:  beego.AppConfig.DefaultString("auto_sync_interval", "30s"),
-			CompactIndexDelta: beego.AppConfig.DefaultInt64("compact_index_delta", 100),
-			CompactInterval:   beego.AppConfig.String("compact_interval"),
+			AutoSyncInterval:  GetString("registry.autoSyncInterval", "30s", WithStandby("auto_sync_interval")),
+			CompactIndexDelta: GetInt64("registry.compact.indexDelta", 100, WithStandby("compact_index_delta")),
+			CompactInterval:   GetString("registry.compact.interval", "", WithStandby("compact_interval")),
 
 			LogRotateSize:   maxLogFileSize,
 			LogBackupCount:  maxLogBackupCount,
-			LogFilePath:     beego.AppConfig.String("logfile"),
-			LogLevel:        beego.AppConfig.String("loglevel"),
-			LogFormat:       beego.AppConfig.DefaultString("log_format", "text"),
-			LogSys:          beego.AppConfig.DefaultBool("log_sys", false),
-			EnableAccessLog: beego.AppConfig.String("enable_access_log") == "true",
+			LogFilePath:     GetString("log.file", "", WithStandby("logfile")),
+			LogLevel:        GetString("log.level", "", WithStandby("loglevel")),
+			LogFormat:       GetString("log.format", "text", WithStandby("log_format")),
+			LogSys:          GetBool("log.system", false, WithStandby("log_sys")),
+			EnableAccessLog: GetBool("log.accessEnable", false, WithStandby("enable_access_log")),
 			AccessLogFile:   accessLogFile,
 
-			PluginsDir: beego.AppConfig.DefaultString("plugins_dir", "./plugins"),
+			PluginsDir: GetString("plugin.dir", "./plugins", WithStandby("plugins_dir")),
 			Plugins:    util.NewJSONObject(),
 
-			EnablePProf:  beego.AppConfig.DefaultInt("enable_pprof", 0) != 0,
-			EnableCache:  beego.AppConfig.DefaultInt("enable_cache", 1) != 0,
+			EnableCache:  GetInt("registry.cache.mode", 1, WithStandby("enable_cache")) != 0,
 			CacheTTL:     cacheTTL,
-			SelfRegister: beego.AppConfig.DefaultInt("self_register", 1) != 0,
+			SelfRegister: GetInt("registry.selfRegister", 1, WithStandby("self_register")) != 0,
 
-			ServiceClearEnabled:  os.Getenv("SERVICE_CLEAR_ENABLED") == "true",
+			ServiceClearEnabled:  GetBool("registry.service.clearEnable", false, WithENV("SERVICE_CLEAR_ENABLED")),
 			ServiceClearInterval: serviceClearInterval,
 			ServiceTTL:           serviceTTL,
 
-			SchemaDisable: os.Getenv("SCHEMA_DISABLE") == "true",
+			SchemaDisable: GetBool("registry.schema.readonly", false, WithENV("SCHEMA_DISABLE")),
 		},
 	}
 }
diff --git a/server/config/config_test.go b/server/config/config_test.go
index 8d4cf2f..b7e5ed7 100644
--- a/server/config/config_test.go
+++ b/server/config/config_test.go
@@ -18,14 +18,18 @@
 package config_test
 
 import (
+	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/config"
+	"github.com/go-chassis/go-archaius"
 	"github.com/stretchr/testify/assert"
 	"io"
 	"os"
+	"path/filepath"
 	"testing"
 )
 
 func TestInit(t *testing.T) {
+	defer archaius.Clean()
 	b := []byte(`
 gov:
   plugins:
@@ -34,12 +38,15 @@ gov:
     - type: istio
 
 `)
-	defer os.Remove("test.yaml")
-	f1, err := os.Create("test.yaml")
+	dir := filepath.Join(util.GetAppRoot(), "conf")
+	defer os.Remove(dir)
+	os.Mkdir(dir, 0750)
+	file := filepath.Join(dir, "app.yaml")
+	defer os.Remove(file)
+	f1, err := os.Create(file)
 	assert.NoError(t, err)
 	_, err = io.WriteString(f1, string(b))
 	assert.NoError(t, err)
-	config.Configurations.ConfigFile = "test.yaml"
 	config.Init()
 	assert.NoError(t, err)
 	assert.Equal(t, "mock", config.GetGov().DistOptions[0].Type)
diff --git a/server/config/types.go b/server/config/options.go
similarity index 67%
copy from server/config/types.go
copy to server/config/options.go
index 05636a0..0a29575 100644
--- a/server/config/types.go
+++ b/server/config/options.go
@@ -17,17 +17,29 @@
 
 package config
 
-//Config is yaml file struct
-type Config struct {
-	Gov Gov `yaml:"gov"`
-	//config from cli
-	ConfigFile string
+type Options struct {
+	ENV     string
+	Standby string
 }
-type Gov struct {
-	DistOptions []DistributorOptions `yaml:"plugins"`
+
+type Option func(options *Options)
+
+func WithENV(env string) Option {
+	return func(options *Options) {
+		options.ENV = env
+	}
 }
-type DistributorOptions struct {
-	Name     string `yaml:"name"`
-	Type     string `yaml:"type"`
-	Endpoint string `yaml:"endpoint"`
+
+func WithStandby(key string) Option {
+	return func(options *Options) {
+		options.Standby = key
+	}
+}
+
+func NewOptions(opts ...Option) *Options {
+	o := &Options{}
+	for _, opt := range opts {
+		opt(o)
+	}
+	return o
 }
diff --git a/server/config/types.go b/server/config/types.go
index 05636a0..4c74827 100644
--- a/server/config/types.go
+++ b/server/config/types.go
@@ -19,9 +19,8 @@ package config
 
 //Config is yaml file struct
 type Config struct {
-	Gov Gov `yaml:"gov"`
-	//config from cli
-	ConfigFile string
+	Gov    Gov                `yaml:"gov"`
+	Server *ServerInformation `yaml:"server"`
 }
 type Gov struct {
 	DistOptions []DistributorOptions `yaml:"plugins"`
diff --git a/server/config/util.go b/server/config/util.go
new file mode 100644
index 0000000..761818d
--- /dev/null
+++ b/server/config/util.go
@@ -0,0 +1,101 @@
+/*
+ * 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 config
+
+import (
+	"github.com/astaxie/beego"
+	"github.com/go-chassis/go-archaius"
+	"github.com/iancoleman/strcase"
+	"strings"
+	"time"
+)
+
+func newOptions(key string, opts []Option) *Options {
+	options := NewOptions(opts...)
+	key = strings.ReplaceAll(key, ".", "_")
+	if options.ENV == "" {
+		options.ENV = strcase.ToScreamingSnake(key)
+	}
+	if options.Standby == "" {
+		options.Standby = strcase.ToSnake(key)
+	}
+	return options
+}
+
+// GetString return the string type value by specified key
+func GetString(key, def string, opts ...Option) string {
+	options := newOptions(key, opts)
+	val := strings.TrimSpace(archaius.GetString(options.ENV, ""))
+	if val != "" {
+		return val
+	}
+	val = strings.TrimSpace(archaius.GetString(key, ""))
+	if val != "" {
+		return val
+	}
+	return strings.TrimSpace(beego.AppConfig.DefaultString(options.Standby, def))
+}
+
+// GetBool return the boolean type value by specified key
+func GetBool(key string, def bool, opts ...Option) bool {
+	options := newOptions(key, opts)
+	if archaius.Exist(options.ENV) {
+		return archaius.GetBool(options.ENV, def)
+	}
+	if archaius.Exist(key) {
+		return archaius.GetBool(key, def)
+	}
+	return beego.AppConfig.DefaultBool(options.Standby, def)
+}
+
+// GetInt return the int type value by specified key
+func GetInt(key string, def int, opts ...Option) int {
+	options := newOptions(key, opts)
+	if archaius.Exist(options.ENV) {
+		return archaius.GetInt(options.ENV, def)
+	}
+	if archaius.Exist(key) {
+		return archaius.GetInt(key, def)
+	}
+	return beego.AppConfig.DefaultInt(options.Standby, def)
+}
+
+// GetInt64 return the int64 type value by specified key
+func GetInt64(key string, def int64, opts ...Option) int64 {
+	options := newOptions(key, opts)
+	if archaius.Exist(options.ENV) {
+		return archaius.GetInt64(options.ENV, def)
+	}
+	if archaius.Exist(key) {
+		return archaius.GetInt64(key, def)
+	}
+	return beego.AppConfig.DefaultInt64(options.Standby, def)
+}
+
+// GetDuration return the time.Duration type value by specified key
+func GetDuration(key string, def time.Duration, opts ...Option) time.Duration {
+	str := GetString(key, "", opts...)
+	if str == "" {
+		return def
+	}
+	d, err := time.ParseDuration(str)
+	if err != nil {
+		return def
+	}
+	return d
+}
diff --git a/server/config/config_test.go b/server/config/util_test.go
similarity index 63%
copy from server/config/config_test.go
copy to server/config/util_test.go
index 8d4cf2f..04efd07 100644
--- a/server/config/config_test.go
+++ b/server/config/util_test.go
@@ -18,29 +18,20 @@
 package config_test
 
 import (
+	"github.com/apache/servicecomb-service-center/pkg/util"
 	"github.com/apache/servicecomb-service-center/server/config"
+	"github.com/go-chassis/go-archaius"
 	"github.com/stretchr/testify/assert"
-	"io"
 	"os"
+	"path/filepath"
 	"testing"
 )
 
-func TestInit(t *testing.T) {
-	b := []byte(`
-gov:
-  plugins:
-    - type: mock
-    - type: kie
-    - type: istio
-
-`)
-	defer os.Remove("test.yaml")
-	f1, err := os.Create("test.yaml")
-	assert.NoError(t, err)
-	_, err = io.WriteString(f1, string(b))
-	assert.NoError(t, err)
-	config.Configurations.ConfigFile = "test.yaml"
-	config.Init()
-	assert.NoError(t, err)
-	assert.Equal(t, "mock", config.GetGov().DistOptions[0].Type)
+func TestGetString(t *testing.T) {
+	os.Setenv("TEST_GET_STRING", "test")
+	defer archaius.Clean()
+	archaius.Init(archaius.WithMemorySource(), archaius.WithENVSource(),
+		archaius.WithOptionalFiles([]string{filepath.Join(util.GetAppRoot(), "conf", "app.yaml")}))
+	assert.Equal(t, "test", config.GetString("test.getString", "none"))
+	assert.Equal(t, "test", config.GetString("other.getString", "none", config.WithENV("TEST_GET_STRING")))
 }