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

littlecui 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 df45804  supply service governance policy (#728)
df45804 is described below

commit df458044615660848c90c2e1a762cd7773e43900
Author: Shawn <[email protected]>
AuthorDate: Wed Oct 28 17:08:45 2020 +0800

    supply service governance policy (#728)
    
    * poc: governance API
    
    * supply service governance policy
---
 datasource/etcd/config.go                          |  8 +--
 datasource/etcd/etcd_suite_test.go                 |  8 ++-
 datasource/etcd/job/job.go                         | 12 ++--
 datasource/etcd/kv/kv.go                           |  8 +--
 datasource/etcd/sd/aggregate/repo.go               |  4 +-
 datasource/etcd/sd/etcd/adaptor.go                 |  6 +-
 datasource/etcd/sd/etcd/adaptor_test.go            |  6 +-
 datasource/etcd/sd/etcd/cacher_kv.go               |  4 +-
 datasource/etcd/version.go                         | 13 ++--
 examples/governance/limiter.json                   |  8 +++
 examples/governance/loadbalancer.json              |  7 ++
 examples/governance/marker.json                    | 31 ++++++++
 go.mod                                             |  1 +
 go.sum                                             |  8 +++
 .../controller/v4/v4.go => pkg/model/governance.go | 42 +++++------
 pkg/model/governance_test.go                       | 77 ++++++++++++++++++++
 .../controller/v4/v4.go => pkg/model/marker.go     | 34 ++++-----
 pkg/{types/cluster.go => model/rate_limiter.go}    | 15 ++--
 pkg/types/{cluster.go => types.go}                 |  0
 scripts/release/licenses/LICENSE-ufave-cli         | 21 ++++++
 server/api.go                                      |  7 +-
 server/bootstrap/bootstrap.go                      |  1 +
 server/broker/broker_suite_test.go                 |  7 +-
 server/broker/util.go                              | 14 ++--
 .../controller/v4/v4.go => command/command.go}     | 41 ++++++-----
 server/core/{ => config}/config.go                 | 29 +++++++-
 test/test.go => server/core/config/config_test.go  | 32 ++++++---
 .../cluster.go => server/core/config/struct.go     | 19 +++--
 server/core/core.go                                | 20 +-----
 server/handler/accesslog/handler.go                | 10 +--
 server/handler/maxbody/maxbody.go                  |  4 +-
 server/plugin/security/tlsconf/buildin/tlsconf.go  | 16 ++---
 server/plugin/tracing/pzipkin/file_collector.go    |  6 +-
 server/plugin/types.go                             |  6 +-
 .../controller/v4/v4.go => resource/register.go}   | 13 ++--
 server/resource/v1/gov_resource.go                 | 76 ++++++++++++++++++++
 server/resource/v1/gov_resource_test.go            | 45 ++++++++++++
 .../controller => resource}/v4/auth_resource.go    |  0
 .../v4/auth_resource_test.go                       |  2 +-
 server/rest/controller/v4/dependency_controller.go |  2 +-
 server/rest/controller/v4/main_controller.go       |  3 +-
 server/rest/controller/v4/schema_controller.go     |  3 +-
 server/rest/controller/v4/v4.go                    |  4 --
 server/rest/pprof.go                               |  4 +-
 server/rest/server.go                              | 14 ++--
 server/server.go                                   | 12 +++-
 server/service/event/dependency_event_handler.go   |  5 +-
 server/service/gov/config_distributor.go           | 84 ++++++++++++++++++++++
 server/service/gov/config_distributor_test.go      | 51 +++++++++++++
 server/service/gov/mock/mock.go                    | 71 ++++++++++++++++++
 server/service/rbac/rbac.go                        |  4 +-
 server/service/service_suite_test.go               |  7 +-
 test/test.go                                       |  4 +-
 53 files changed, 734 insertions(+), 195 deletions(-)

diff --git a/datasource/etcd/config.go b/datasource/etcd/config.go
index a16ec9a..bb4c645 100644
--- a/datasource/etcd/config.go
+++ b/datasource/etcd/config.go
@@ -21,7 +21,7 @@ import (
        "context"
        "github.com/apache/servicecomb-service-center/datasource/etcd/client"
        "github.com/apache/servicecomb-service-center/pkg/log"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/astaxie/beego"
        "strings"
        "sync"
@@ -42,7 +42,7 @@ func Configuration() *client.Config {
                defaultRegistryConfig.InitClusterInfo()
 
                registryAddresses := 
strings.Join(defaultRegistryConfig.RegistryAddresses(), ",")
-               defaultRegistryConfig.SslEnabled = 
core.ServerInfo.Config.SslEnabled &&
+               defaultRegistryConfig.SslEnabled = 
config.ServerInfo.Config.SslEnabled &&
                        strings.Contains(strings.ToLower(registryAddresses), 
"https://";)
 
                defaultRegistryConfig.DialTimeout, err = 
time.ParseDuration(beego.AppConfig.DefaultString("connect_timeout", "10s"))
@@ -55,12 +55,12 @@ func Configuration() *client.Config {
                        log.Errorf(err, "registry_timeout is invalid, use 
default time %s", client.DefaultRequestTimeout)
                        defaultRegistryConfig.RequestTimeOut = 
client.DefaultRequestTimeout
                }
-               defaultRegistryConfig.AutoSyncInterval, err = 
time.ParseDuration(core.ServerInfo.Config.AutoSyncInterval)
+               defaultRegistryConfig.AutoSyncInterval, err = 
time.ParseDuration(config.ServerInfo.Config.AutoSyncInterval)
                if err != nil {
                        log.Errorf(err, "auto_sync_interval is invalid")
                }
 
-               core.ServerInfo.Config.Plugins.Object("discovery").
+               config.ServerInfo.Config.Plugins.Object("discovery").
                        Set("config", defaultRegistryConfig)
        })
        return &defaultRegistryConfig
diff --git a/datasource/etcd/etcd_suite_test.go 
b/datasource/etcd/etcd_suite_test.go
index 6883921..7ed611d 100644
--- a/datasource/etcd/etcd_suite_test.go
+++ b/datasource/etcd/etcd_suite_test.go
@@ -17,12 +17,14 @@
 package etcd_test
 
 // initialize
-import _ "github.com/apache/servicecomb-service-center/server/bootstrap"
+import (
+       _ "github.com/apache/servicecomb-service-center/server/bootstrap"
+       "github.com/apache/servicecomb-service-center/server/core/config"
+)
 import (
        "context"
        "github.com/apache/servicecomb-service-center/datasource"
        "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/core"
        "github.com/astaxie/beego"
        . "github.com/onsi/ginkgo"
        "github.com/onsi/ginkgo/reporters"
@@ -40,7 +42,7 @@ func init() {
 
 var _ = BeforeSuite(func() {
        //init plugin
-       core.ServerInfo.Config.EnableCache = false
+       config.ServerInfo.Config.EnableCache = false
        //clear service created in last test
        time.Sleep(timeLimit)
        _ = datasource.Instance().ClearNoInstanceServices(context.Background(), 
timeLimit)
diff --git a/datasource/etcd/job/job.go b/datasource/etcd/job/job.go
index 91aeffb..8f0aec0 100644
--- a/datasource/etcd/job/job.go
+++ b/datasource/etcd/job/job.go
@@ -23,31 +23,31 @@ import (
        "github.com/apache/servicecomb-service-center/datasource/etcd/mux"
        "github.com/apache/servicecomb-service-center/pkg/gopool"
        "github.com/apache/servicecomb-service-center/pkg/log"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "time"
 )
 
 // clear services who have no instance
 func ClearNoInstanceServices() {
-       if !core.ServerInfo.Config.ServiceClearEnabled {
+       if !config.ServerInfo.Config.ServiceClearEnabled {
                return
        }
        log.Infof("service clear enabled, interval: %s, service TTL: %s",
-               core.ServerInfo.Config.ServiceClearInterval,
-               core.ServerInfo.Config.ServiceTTL)
+               config.ServerInfo.Config.ServiceClearInterval,
+               config.ServerInfo.Config.ServiceTTL)
 
        gopool.Go(func(ctx context.Context) {
                for {
                        select {
                        case <-ctx.Done():
                                return
-                       case 
<-time.After(core.ServerInfo.Config.ServiceClearInterval):
+                       case 
<-time.After(config.ServerInfo.Config.ServiceClearInterval):
                                lock, err := mux.Try(mux.ServiceClearLock)
                                if err != nil {
                                        log.Errorf(err, "can not clear no 
instance services by this service center instance now")
                                        continue
                                }
-                               err = 
datasource.Instance().ClearNoInstanceServices(ctx, 
core.ServerInfo.Config.ServiceTTL)
+                               err = 
datasource.Instance().ClearNoInstanceServices(ctx, 
config.ServerInfo.Config.ServiceTTL)
                                if err := lock.Unlock(); err != nil {
                                        log.Error("", err)
                                }
diff --git a/datasource/etcd/kv/kv.go b/datasource/etcd/kv/kv.go
index 5917c7e..d4844a6 100644
--- a/datasource/etcd/kv/kv.go
+++ b/datasource/etcd/kv/kv.go
@@ -25,7 +25,7 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/gopool"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "time"
 )
 
@@ -100,16 +100,16 @@ func (s *TypeStore) store(ctx context.Context) {
 }
 
 func (s *TypeStore) autoClearCache(ctx context.Context) {
-       if core.ServerInfo.Config.CacheTTL == 0 {
+       if config.ServerInfo.Config.CacheTTL == 0 {
                return
        }
 
-       log.Infof("start auto clear cache in %v", 
core.ServerInfo.Config.CacheTTL)
+       log.Infof("start auto clear cache in %v", 
config.ServerInfo.Config.CacheTTL)
        for {
                select {
                case <-ctx.Done():
                        return
-               case <-time.After(core.ServerInfo.Config.CacheTTL):
+               case <-time.After(config.ServerInfo.Config.CacheTTL):
                        for _, t := range sd.Types {
                                cache, ok := 
s.getOrCreateAdaptor(t).Cache().(sd.Cache)
                                if !ok {
diff --git a/datasource/etcd/sd/aggregate/repo.go 
b/datasource/etcd/sd/aggregate/repo.go
index 1234f38..f3d58b1 100644
--- a/datasource/etcd/sd/aggregate/repo.go
+++ b/datasource/etcd/sd/aggregate/repo.go
@@ -17,7 +17,7 @@ package aggregate
 
 import (
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
 )
 
 func init() {
@@ -37,6 +37,6 @@ func NewRepository(opts sd.Options) sd.AdaptorRepository {
 }
 
 func InitConfigs() {
-       core.ServerInfo.Config.Plugins.Object("discovery").
+       config.ServerInfo.Config.Plugins.Object("discovery").
                Set("aggregateMode", repos)
 }
diff --git a/datasource/etcd/sd/etcd/adaptor.go 
b/datasource/etcd/sd/etcd/adaptor.go
index acf74c0..7a8e55a 100644
--- a/datasource/etcd/sd/etcd/adaptor.go
+++ b/datasource/etcd/sd/etcd/adaptor.go
@@ -20,7 +20,7 @@ package etcd
 import (
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
        "github.com/apache/servicecomb-service-center/pkg/log"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
 )
 
 // Adaptor implements sd.Adaptor.
@@ -52,14 +52,14 @@ func (se *Adaptor) Ready() <-chan struct{} {
 func NewEtcdAdaptor(name string, cfg *sd.Config) *Adaptor {
        var adaptor Adaptor
        switch {
-       case core.ServerInfo.Config.EnableCache && cfg.InitSize > 0:
+       case config.ServerInfo.Config.EnableCache && cfg.InitSize > 0:
                kvCache := sd.NewKvCache(name, cfg)
                adaptor.Cacher = NewKvCacher(cfg, kvCache)
                adaptor.Indexer = NewCacheIndexer(cfg, kvCache)
        default:
                log.Infof(
                        "core will not cache '%s' and ignore all events of it, 
cache enabled: %v, init size: %d",
-                       name, core.ServerInfo.Config.EnableCache, cfg.InitSize)
+                       name, config.ServerInfo.Config.EnableCache, 
cfg.InitSize)
                adaptor.Cacher = sd.NullCacher
                adaptor.Indexer = NewEtcdIndexer(cfg.Key, cfg.Parser)
        }
diff --git a/datasource/etcd/sd/etcd/adaptor_test.go 
b/datasource/etcd/sd/etcd/adaptor_test.go
index 7005401..0cc3952 100644
--- a/datasource/etcd/sd/etcd/adaptor_test.go
+++ b/datasource/etcd/sd/etcd/adaptor_test.go
@@ -19,17 +19,17 @@ package etcd
 
 import (
        "github.com/apache/servicecomb-service-center/datasource/etcd/sd"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "testing"
 )
 
 func TestNewKvEntity(t *testing.T) {
-       core.ServerInfo.Config.EnableCache = false
+       config.ServerInfo.Config.EnableCache = false
        i := NewEtcdAdaptor("a", sd.Configure().WithInitSize(1))
        if _, ok := i.Indexer.(*Indexer); !ok {
                t.Fatalf("TestNewIndexer failed")
        }
-       core.ServerInfo.Config.EnableCache = true
+       config.ServerInfo.Config.EnableCache = true
 
        i.Run()
        <-i.Ready()
diff --git a/datasource/etcd/sd/etcd/cacher_kv.go 
b/datasource/etcd/sd/etcd/cacher_kv.go
index c052ff7..c37ad17 100644
--- a/datasource/etcd/sd/etcd/cacher_kv.go
+++ b/datasource/etcd/sd/etcd/cacher_kv.go
@@ -28,7 +28,7 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/log"
        rmodel "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/coreos/etcd/mvcc/mvccpb"
        "sync"
        "time"
@@ -493,7 +493,7 @@ func (c *KvCacher) IsReady() bool {
 }
 
 func (c *KvCacher) reportMetrics(ctx context.Context) {
-       if !core.ServerInfo.Config.EnablePProf {
+       if !config.ServerInfo.Config.EnablePProf {
                return
        }
        timer := time.NewTimer(DefaultMetricsInterval)
diff --git a/datasource/etcd/version.go b/datasource/etcd/version.go
index a6f048b..1aace20 100644
--- a/datasource/etcd/version.go
+++ b/datasource/etcd/version.go
@@ -26,6 +26,7 @@ import (
        serviceUtil 
"github.com/apache/servicecomb-service-center/datasource/etcd/util"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/apache/servicecomb-service-center/version"
        "os"
 )
@@ -40,7 +41,7 @@ func (ds *DataSource) LoadServerVersion(ctx context.Context) 
error {
                return nil
        }
 
-       err = json.Unmarshal(resp.Kvs[0].Value, &core.ServerInfo)
+       err = json.Unmarshal(resp.Kvs[0].Value, &config.ServerInfo)
        if err != nil {
                log.Errorf(err, "load server version failed, maybe 
incompatible")
                return nil
@@ -49,7 +50,7 @@ func (ds *DataSource) LoadServerVersion(ctx context.Context) 
error {
 }
 
 func (ds *DataSource) UpgradeServerVersion(ctx context.Context) error {
-       bytes, err := json.Marshal(core.ServerInfo)
+       bytes, err := json.Marshal(config.ServerInfo)
        if err != nil {
                return err
        }
@@ -69,7 +70,7 @@ func (ds *DataSource) UpgradeVersion(ctx context.Context) 
error {
                return err
        }
        if ds.needUpgrade(ctx) {
-               core.ServerInfo.Version = version.Ver().Version
+               config.ServerInfo.Version = version.Ver().Version
 
                if err := ds.UpgradeServerVersion(ctx); err != nil {
                        log.Errorf(err, "upgrade server version failed")
@@ -90,12 +91,12 @@ func (ds *DataSource) needUpgrade(ctx context.Context) bool 
{
                return false
        }
 
-       update := !serviceUtil.VersionMatchRule(core.ServerInfo.Version,
+       update := !serviceUtil.VersionMatchRule(config.ServerInfo.Version,
                fmt.Sprintf("%s+", version.Ver().Version))
-       if !update && version.Ver().Version != core.ServerInfo.Version {
+       if !update && version.Ver().Version != config.ServerInfo.Version {
                log.Warnf(
                        "there is a higher version '%s' in cluster, now running 
'%s' version may be incompatible",
-                       core.ServerInfo.Version, version.Ver().Version)
+                       config.ServerInfo.Version, version.Ver().Version)
        }
 
        return update
diff --git a/examples/governance/limiter.json b/examples/governance/limiter.json
new file mode 100644
index 0000000..e4ae6b0
--- /dev/null
+++ b/examples/governance/limiter.json
@@ -0,0 +1,8 @@
+{
+  "name": "limitTraffic2adminAPI",
+  "spec": {
+    "match": "traffic2adminAPI",
+    "rate": 100,
+    "burst": 10
+  }
+}
\ No newline at end of file
diff --git a/examples/governance/loadbalancer.json 
b/examples/governance/loadbalancer.json
new file mode 100644
index 0000000..17e4f68
--- /dev/null
+++ b/examples/governance/loadbalancer.json
@@ -0,0 +1,7 @@
+{
+  "name": "adminAPIRetry",
+  "spec": {
+    "match": "traffic2adminAPI",
+    "retryNext": 3
+  }
+}
\ No newline at end of file
diff --git a/examples/governance/marker.json b/examples/governance/marker.json
new file mode 100644
index 0000000..0d09672
--- /dev/null
+++ b/examples/governance/marker.json
@@ -0,0 +1,31 @@
+{
+  "name": "traffic2adminAPI",
+  "spec": {
+    "matches": [
+      {
+        "headers": {
+          "X-User": {
+            "regex": "ja.*"
+          }
+        },
+        "apiPath": {
+          "exact": "/metrics"
+        },
+        "methods": [
+          "GET",
+          "POST"
+        ]
+      },
+      {
+        "apiPath": {
+          "exact": "/health"
+        },
+        "methods": [
+          "GET",
+          "POST"
+        ]
+      }
+    ]
+  }
+}
+
diff --git a/go.mod b/go.mod
index 76f2622..b7f5b12 100644
--- a/go.mod
+++ b/go.mod
@@ -35,6 +35,7 @@ require (
        github.com/spf13/cobra v0.0.0-20170624150100-4d647c8944eb
        github.com/spf13/pflag v1.0.5
        github.com/stretchr/testify v1.4.0
+       github.com/urfave/cli v1.22.4
        github.com/widuu/gojson v0.0.0-20170212122013-7da9d2cd949b
        go.uber.org/zap v1.10.0
        golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
diff --git a/go.sum b/go.sum
index 6393c95..54b0055 100644
--- a/go.sum
+++ b/go.sum
@@ -50,6 +50,8 @@ github.com/coreos/go-systemd 
v0.0.0-20180828140353-eee3db372b31 h1:wRzCUSYhBIk1K
 github.com/coreos/go-systemd v0.0.0-20180828140353-eee3db372b31/go.mod 
h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea 
h1:n2Ltr3SrfQlf/9nOna1DoGKxLx3qTSI8Ttl6Xrqp6mw=
 github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod 
h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d 
h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
+github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod 
h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
 github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.0/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 
h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -287,11 +289,15 @@ github.com/rcrowley/go-metrics 
v0.0.0-20180503174638-e2704e165165 h1:nkcn14uNmFE
 github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod 
h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
 github.com/rs/cors v0.0.0-20170608165155-8dd4211afb5d 
h1:573lGU02rfWK16h656qmmul1zPul8WPPCDekyq+keVs=
 github.com/rs/cors v0.0.0-20170608165155-8dd4211afb5d/go.mod 
h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/russross/blackfriday/v2 v2.0.1 
h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
+github.com/russross/blackfriday/v2 v2.0.1/go.mod 
h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod 
h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/satori/go.uuid v1.1.0 
h1:B9KXyj+GzIpJbV7gmr873NsY6zpbxNy24CBtGrk7jHo=
 github.com/satori/go.uuid v1.1.0/go.mod 
h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 
h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod 
h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/shurcooL/sanitized_anchor_name v1.0.0 
h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
+github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod 
h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/sirupsen/logrus v1.2.0/go.mod 
h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2 
h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
 github.com/sirupsen/logrus v1.4.2/go.mod 
h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@@ -319,6 +325,8 @@ github.com/stretchr/testify v1.4.0/go.mod 
h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 
h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
 github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod 
h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 github.com/ugorji/go v1.1.4/go.mod 
h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
+github.com/urfave/cli v1.22.4/go.mod 
h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
 github.com/valyala/bytebufferpool v1.0.0 
h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
 github.com/valyala/bytebufferpool v1.0.0/go.mod 
h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 github.com/valyala/fasttemplate v0.0.0-20170224212429-dcecefd839c4/go.mod 
h1:50wTf68f99/Zt14pr046Tgt3Lp2vLyFZKzbFXTOabXw=
diff --git a/server/rest/controller/v4/v4.go b/pkg/model/governance.go
similarity index 50%
copy from server/rest/controller/v4/v4.go
copy to pkg/model/governance.go
index ad513d9..65f8a41 100644
--- a/server/rest/controller/v4/v4.go
+++ b/pkg/model/governance.go
@@ -15,27 +15,29 @@
  * limitations under the License.
  */
 
-package v4
+package model
 
-import (
-       roa "github.com/apache/servicecomb-service-center/pkg/rest"
-       "github.com/apache/servicecomb-service-center/server/service/rbac"
-)
-
-func init() {
-       initRouter()
+//GovernancePolicy is a unified struct
+//all governance policy must extend this struct
+//Name is the policy name, for example: "rate-limit-payment-api"
+//MD is metadata.
+type GovernancePolicy struct {
+       Name string            `json:"name,omitempty"`
+       MD   map[string]string `json:"metadata,omitempty"`
 }
 
-func initRouter() {
-       if rbac.Enabled() {
-               roa.RegisterServant(&AuthResource{})
-       }
-       roa.RegisterServant(&MainService{})
-       roa.RegisterServant(&MicroServiceService{})
-       roa.RegisterServant(&SchemaService{})
-       roa.RegisterServant(&DependencyService{})
-       roa.RegisterServant(&TagService{})
-       roa.RegisterServant(&RuleService{})
-       roa.RegisterServant(&MicroServiceInstanceService{})
-       roa.RegisterServant(&WatchService{})
+//LoadBalancer define policy and fault tolerant policy
+type LoadBalancer struct {
+       *GovernancePolicy
+       Spec *LBSpec `json:"spec,omitempty"`
+}
+type LBSpec struct {
+       MarkerName string         `json:"match"`
+       RetrySame  int            `json:"retrySame,omitempty"`
+       RetryNext  int            `json:"retryNext,omitempty"`
+       Bo         *BackOffPolicy `json:"backoff,omitempty"`
+}
+type BackOffPolicy struct {
+       InitialInterval int `json:"initInterval"`
+       MaxInterval     int `json:"maxInterval"`
 }
diff --git a/pkg/model/governance_test.go b/pkg/model/governance_test.go
new file mode 100644
index 0000000..76093f6
--- /dev/null
+++ b/pkg/model/governance_test.go
@@ -0,0 +1,77 @@
+/*
+ * 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 model_test
+
+import (
+       "encoding/json"
+       "github.com/apache/servicecomb-service-center/pkg/model"
+       "testing"
+)
+
+func TestNewInstance3(t *testing.T) {
+       b, _ := json.MarshalIndent(&model.LoadBalancer{
+               GovernancePolicy: &model.GovernancePolicy{
+                       Name: "Traffic2adminAPI",
+               },
+               Spec: &model.LBSpec{RetryNext: 3, MarkerName: 
"traffic2adminAPI"},
+       }, "", "  ")
+       t.Log(string(b))
+}
+func TestNewInstance2(t *testing.T) {
+       b, _ := json.MarshalIndent(&model.RateLimiter{
+               GovernancePolicy: &model.GovernancePolicy{
+                       Name: "limitTraffic2adminAPI",
+               },
+               Spec: &model.LimiterSpec{Burst: 10, Rate: 100, MarkerName: 
"traffic2adminAPI"},
+       }, "", "  ")
+       t.Log(string(b))
+}
+func TestNewInstance(t *testing.T) {
+       b, _ := json.MarshalIndent(&model.TrafficMarker{
+               GovernancePolicy: &model.GovernancePolicy{
+                       Name: "traffic2adminAPI",
+                       MD: map[string]string{
+                               "service":     "payment",
+                               "version":     "1.0.0",
+                               "app":         "default",
+                               "environment": "development",
+                       },
+               },
+               Spec: &model.MatchSpec{
+                       TrafficMarkPolicy: "perService",
+                       MatchPolicies: []*model.MatchPolicy{
+                               {
+                                       Headers: map[string]map[string]string{
+                                               "X-User": {"regex": "ja.*"},
+                                       },
+                                       APIPaths: map[string]string{
+                                               "exact": "/metrics",
+                                       },
+                                       Methods: []string{"GET", "POST"},
+                               },
+                               {
+                                       APIPaths: map[string]string{
+                                               "exact": "/health",
+                                       },
+                                       Methods: []string{"GET", "POST"},
+                               },
+                       },
+               },
+       }, "", "  ")
+       t.Log(string(b))
+}
diff --git a/server/rest/controller/v4/v4.go b/pkg/model/marker.go
similarity index 57%
copy from server/rest/controller/v4/v4.go
copy to pkg/model/marker.go
index ad513d9..280348b 100644
--- a/server/rest/controller/v4/v4.go
+++ b/pkg/model/marker.go
@@ -15,27 +15,21 @@
  * limitations under the License.
  */
 
-package v4
+package model
 
-import (
-       roa "github.com/apache/servicecomb-service-center/pkg/rest"
-       "github.com/apache/servicecomb-service-center/server/service/rbac"
-)
-
-func init() {
-       initRouter()
+//TrafficMarker marks request, it assign a name to request in runtime
+type TrafficMarker struct {
+       *GovernancePolicy
+       Spec *MatchSpec `json:"spec,omitempty"`
+}
+type MatchSpec struct {
+       MatchPolicies     []*MatchPolicy `json:"matches,omitempty"`
+       TrafficMarkPolicy string         `json:"trafficMarkPolicy,omitempty"`
 }
 
-func initRouter() {
-       if rbac.Enabled() {
-               roa.RegisterServant(&AuthResource{})
-       }
-       roa.RegisterServant(&MainService{})
-       roa.RegisterServant(&MicroServiceService{})
-       roa.RegisterServant(&SchemaService{})
-       roa.RegisterServant(&DependencyService{})
-       roa.RegisterServant(&TagService{})
-       roa.RegisterServant(&RuleService{})
-       roa.RegisterServant(&MicroServiceInstanceService{})
-       roa.RegisterServant(&WatchService{})
+//MatchPolicy specify a request mach policy
+type MatchPolicy struct {
+       Headers  map[string]map[string]string `json:"headers,omitempty"`
+       APIPaths map[string]string            `json:"apiPath,omitempty"`
+       Methods  []string                     `json:"methods,omitempty"`
 }
diff --git a/pkg/types/cluster.go b/pkg/model/rate_limiter.go
similarity index 75%
copy from pkg/types/cluster.go
copy to pkg/model/rate_limiter.go
index 9e13338..12e2cc6 100644
--- a/pkg/types/cluster.go
+++ b/pkg/model/rate_limiter.go
@@ -15,8 +15,15 @@
  * limitations under the License.
  */
 
-package types
+package model
 
-type Clusters map[string][]string
-
-type EventType string
+//RateLimiter limit request rate
+type RateLimiter struct {
+       *GovernancePolicy
+       Spec *LimiterSpec `json:"spec,omitempty"`
+}
+type LimiterSpec struct {
+       MarkerName string `json:"match"`
+       Rate       int    `json:"rate"`
+       Burst      int    `json:"burst"`
+}
diff --git a/pkg/types/cluster.go b/pkg/types/types.go
similarity index 100%
copy from pkg/types/cluster.go
copy to pkg/types/types.go
diff --git a/scripts/release/licenses/LICENSE-ufave-cli 
b/scripts/release/licenses/LICENSE-ufave-cli
new file mode 100644
index 0000000..17356d3
--- /dev/null
+++ b/scripts/release/licenses/LICENSE-ufave-cli
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2016 Jeremy Saenz & Contributors
+
+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.
\ No newline at end of file
diff --git a/server/api.go b/server/api.go
index 3743188..2c19e78 100644
--- a/server/api.go
+++ b/server/api.go
@@ -26,6 +26,7 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rest"
        "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        rs "github.com/apache/servicecomb-service-center/server/rest"
        "github.com/apache/servicecomb-service-center/server/service"
        "net"
@@ -108,7 +109,7 @@ func (s *APIServer) populateEndpoint(t APIType, ipPort 
string) {
                return
        }
        address := fmt.Sprintf("%s://%s/", t, ipPort)
-       if core.ServerInfo.Config.SslEnabled {
+       if config.ServerInfo.Config.SslEnabled {
                address += "?sslEnabled=true"
        }
        core.Instance.Endpoints = append(core.Instance.Endpoints, address)
@@ -156,7 +157,7 @@ func (s *APIServer) Start() {
 
        defer log.Info("api server is ready")
 
-       if !core.ServerInfo.Config.SelfRegister {
+       if !config.ServerInfo.Config.SelfRegister {
                log.Warnf("self register disabled")
                return
        }
@@ -171,7 +172,7 @@ func (s *APIServer) Stop() {
        }
        s.isClose = true
 
-       if !s.forked && core.ServerInfo.Config.SelfRegister {
+       if !s.forked && config.ServerInfo.Config.SelfRegister {
                s.selfUnregister()
        }
 
diff --git a/server/bootstrap/bootstrap.go b/server/bootstrap/bootstrap.go
index b5b0cd4..fec6615 100644
--- a/server/bootstrap/bootstrap.go
+++ b/server/bootstrap/bootstrap.go
@@ -24,6 +24,7 @@ import _ 
"github.com/apache/servicecomb-service-center/server/rest/controller/v3
 
 //rest v4 api
 import _ 
"github.com/apache/servicecomb-service-center/server/rest/controller/v4"
+import _ "github.com/apache/servicecomb-service-center/server/resource"
 
 //cipher
 import _ 
"github.com/apache/servicecomb-service-center/server/plugin/security/cipher/buildin"
diff --git a/server/broker/broker_suite_test.go 
b/server/broker/broker_suite_test.go
index 24a5341..a93d9c5 100644
--- a/server/broker/broker_suite_test.go
+++ b/server/broker/broker_suite_test.go
@@ -16,7 +16,10 @@
  */
 package broker_test
 
-import _ "github.com/apache/servicecomb-service-center/server/bootstrap"
+import (
+       _ "github.com/apache/servicecomb-service-center/server/bootstrap"
+       "github.com/apache/servicecomb-service-center/server/core/config"
+)
 import (
        "github.com/apache/servicecomb-service-center/server/broker"
        "github.com/apache/servicecomb-service-center/server/core"
@@ -38,7 +41,7 @@ var brokerResource = broker.ServiceAPI
 
 var _ = BeforeSuite(func() {
        //init plugin
-       core.ServerInfo.Config.EnableCache = false
+       config.ServerInfo.Config.EnableCache = false
        core.ServiceAPI, core.InstanceAPI = service.AssembleResources()
 })
 
diff --git a/server/broker/util.go b/server/broker/util.go
index 3ba2164..3732fd4 100644
--- a/server/broker/util.go
+++ b/server/broker/util.go
@@ -20,6 +20,7 @@ package broker
 import (
        "context"
        "encoding/json"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/apache/servicecomb-service-center/server/core/proto"
        "math"
        "net/url"
@@ -32,7 +33,6 @@ import (
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/broker/brokerpb"
-       "github.com/apache/servicecomb-service-center/server/core"
        scerr "github.com/apache/servicecomb-service-center/server/scerror"
        "path/filepath"
 )
@@ -86,15 +86,15 @@ var brokerAPILinksTitles = map[string]string{
 func init() {
        //define Broker logger
        name := ""
-       if len(core.ServerInfo.Config.LogFilePath) != 0 {
-               name = 
filepath.Join(filepath.Dir(core.ServerInfo.Config.LogFilePath), 
"broker_srvc.log")
+       if len(config.ServerInfo.Config.LogFilePath) != 0 {
+               name = 
filepath.Join(filepath.Dir(config.ServerInfo.Config.LogFilePath), 
"broker_srvc.log")
        }
        PactLogger = log.NewLogger(log.Config{
-               LoggerLevel:    core.ServerInfo.Config.LogLevel,
+               LoggerLevel:    config.ServerInfo.Config.LogLevel,
                LoggerFile:     name,
-               LogFormatText:  core.ServerInfo.Config.LogFormat == "text",
-               LogRotateSize:  int(core.ServerInfo.Config.LogRotateSize),
-               LogBackupCount: int(core.ServerInfo.Config.LogBackupCount),
+               LogFormatText:  config.ServerInfo.Config.LogFormat == "text",
+               LogRotateSize:  int(config.ServerInfo.Config.LogRotateSize),
+               LogBackupCount: int(config.ServerInfo.Config.LogBackupCount),
        })
 }
 
diff --git a/server/rest/controller/v4/v4.go b/server/command/command.go
similarity index 54%
copy from server/rest/controller/v4/v4.go
copy to server/command/command.go
index ad513d9..25e0c43 100644
--- a/server/rest/controller/v4/v4.go
+++ b/server/command/command.go
@@ -15,27 +15,32 @@
  * limitations under the License.
  */
 
-package v4
+package command
 
 import (
-       roa "github.com/apache/servicecomb-service-center/pkg/rest"
-       "github.com/apache/servicecomb-service-center/server/service/rbac"
+       "github.com/apache/servicecomb-service-center/server/core/config"
+       "github.com/apache/servicecomb-service-center/version"
+       "github.com/urfave/cli"
 )
 
-func init() {
-       initRouter()
-}
-
-func initRouter() {
-       if rbac.Enabled() {
-               roa.RegisterServant(&AuthResource{})
+// ParseConfig from cli
+func ParseConfig(args []string) (err error) {
+       app := cli.NewApp()
+       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:       "",
+               },
        }
-       roa.RegisterServant(&MainService{})
-       roa.RegisterServant(&MicroServiceService{})
-       roa.RegisterServant(&SchemaService{})
-       roa.RegisterServant(&DependencyService{})
-       roa.RegisterServant(&TagService{})
-       roa.RegisterServant(&RuleService{})
-       roa.RegisterServant(&MicroServiceInstanceService{})
-       roa.RegisterServant(&WatchService{})
+       app.Action = func(c *cli.Context) error {
+               return nil
+       }
+
+       err = app.Run(args)
+       return
 }
diff --git a/server/core/config.go b/server/core/config/config.go
similarity index 87%
rename from server/core/config.go
rename to server/core/config/config.go
index b1ffa29..124a969 100644
--- a/server/core/config.go
+++ b/server/core/config/config.go
@@ -15,12 +15,15 @@
  * limitations under the License.
  */
 
-package core
+package config
 
 import (
        "github.com/apache/servicecomb-service-center/server/core/proto"
        "github.com/go-chassis/go-archaius"
+       util2 "github.com/go-chassis/go-archaius/source/util"
+       "gopkg.in/yaml.v2"
        "os"
+       "path/filepath"
        "runtime"
        "time"
 
@@ -46,14 +49,34 @@ const (
 
 )
 
+//Configurations is kie config items
+var Configurations = &Config{}
+
 var ServerInfo = proto.NewServerInformation()
 
-func Configure() {
-       err := archaius.Init(archaius.WithMemorySource(), 
archaius.WithENVSource())
+//GetGov return governance configs
+func GetGov() Gov {
+       return Configurations.Gov
+}
+func Init() {
+       err := archaius.Init(archaius.WithMemorySource(), 
archaius.WithENVSource(),
+               archaius.WithOptionalFiles([]string{""}))
        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)
+               }
+
+       }
+
        setCPUs()
 
        *ServerInfo = newInfo()
diff --git a/test/test.go b/server/core/config/config_test.go
similarity index 59%
copy from test/test.go
copy to server/core/config/config_test.go
index e7cf9d7..e17cc45 100644
--- a/test/test.go
+++ b/server/core/config/config_test.go
@@ -15,16 +15,32 @@
  * limitations under the License.
  */
 
-//Package test prepare service center required module before UT
-package test
+package config_test
 
 import (
-       _ "github.com/apache/servicecomb-service-center/server/bootstrap"
-       "github.com/apache/servicecomb-service-center/server/core"
-       "github.com/astaxie/beego"
+       "github.com/apache/servicecomb-service-center/server/core/config"
+       "github.com/stretchr/testify/assert"
+       "io"
+       "os"
+       "testing"
 )
 
-func init() {
-       beego.AppConfig.Set("registry_plugin", "etcd")
-       core.ServerInfo.Config.MaxBodyBytes = 2097152
+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)
 }
diff --git a/pkg/types/cluster.go b/server/core/config/struct.go
similarity index 70%
rename from pkg/types/cluster.go
rename to server/core/config/struct.go
index 9e13338..05636a0 100644
--- a/pkg/types/cluster.go
+++ b/server/core/config/struct.go
@@ -15,8 +15,19 @@
  * limitations under the License.
  */
 
-package types
+package config
 
-type Clusters map[string][]string
-
-type EventType string
+//Config is yaml file struct
+type Config struct {
+       Gov Gov `yaml:"gov"`
+       //config from cli
+       ConfigFile string
+}
+type Gov struct {
+       DistOptions []DistributorOptions `yaml:"plugins"`
+}
+type DistributorOptions struct {
+       Name     string `yaml:"name"`
+       Type     string `yaml:"type"`
+       Endpoint string `yaml:"endpoint"`
+}
diff --git a/server/core/core.go b/server/core/core.go
index 69d00ff..3aef763 100644
--- a/server/core/core.go
+++ b/server/core/core.go
@@ -18,11 +18,11 @@
 package core
 
 import (
-       "flag"
+       "github.com/apache/servicecomb-service-center/server/core/config"
+
        // import the grace package and parse grace cmd line
        _ "github.com/apache/servicecomb-service-center/pkg/grace"
        "github.com/apache/servicecomb-service-center/pkg/log"
-       "github.com/apache/servicecomb-service-center/version"
        "os"
        "os/signal"
        "syscall"
@@ -30,26 +30,12 @@ import (
 )
 
 func Initialize() {
-       // parse the cmd line
-       ParseCommandLine()
-
        // initialize configuration
-       Configure()
+       config.Init()
 
        go handleSignals()
 }
 
-func ParseCommandLine() {
-       var printVer bool
-       flag.BoolVar(&printVer, "v", false, "Print the version and exit.")
-       flag.Parse()
-
-       if printVer {
-               version.Ver().Print()
-               os.Exit(0)
-       }
-}
-
 func handleSignals() {
        defer log.Sync()
 
diff --git a/server/handler/accesslog/handler.go 
b/server/handler/accesslog/handler.go
index 46df0b1..16c65fe 100644
--- a/server/handler/accesslog/handler.go
+++ b/server/handler/accesslog/handler.go
@@ -19,6 +19,7 @@ package accesslog
 
 import (
        "fmt"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "net/http"
        "os"
        "time"
@@ -27,7 +28,6 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rest"
        "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/core"
        svr "github.com/apache/servicecomb-service-center/server/rest"
 )
 
@@ -97,14 +97,14 @@ func NewAccessLogHandler(l *log.Logger) *Handler {
 
 // RegisterHandlers registers an access log handler to the handler chain
 func RegisterHandlers() {
-       if !core.ServerInfo.Config.EnableAccessLog {
+       if !config.ServerInfo.Config.EnableAccessLog {
                return
        }
        logger := log.NewLogger(log.Config{
-               LoggerFile:     
os.ExpandEnv(core.ServerInfo.Config.AccessLogFile),
+               LoggerFile:     
os.ExpandEnv(config.ServerInfo.Config.AccessLogFile),
                LogFormatText:  true,
-               LogRotateSize:  int(core.ServerInfo.Config.LogRotateSize),
-               LogBackupCount: int(core.ServerInfo.Config.LogBackupCount),
+               LogRotateSize:  int(config.ServerInfo.Config.LogRotateSize),
+               LogBackupCount: int(config.ServerInfo.Config.LogBackupCount),
                NoCaller:       true,
                NoTime:         true,
                NoLevel:        true,
diff --git a/server/handler/maxbody/maxbody.go 
b/server/handler/maxbody/maxbody.go
index 58c08ad..a786b75 100644
--- a/server/handler/maxbody/maxbody.go
+++ b/server/handler/maxbody/maxbody.go
@@ -20,7 +20,7 @@ package maxbody
 import (
        "github.com/apache/servicecomb-service-center/pkg/chain"
        "github.com/apache/servicecomb-service-center/pkg/rest"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "net/http"
 )
 
@@ -54,7 +54,7 @@ func (c *Handler) Handle(i *chain.Invocation) {
                i.Context().Value(rest.CtxMatchPattern).(string)
        v, ok := resourcesMap[pattern]
        if !ok {
-               v = core.ServerInfo.Config.MaxBodyBytes
+               v = config.ServerInfo.Config.MaxBodyBytes
        }
 
        r.Body = http.MaxBytesReader(w, r.Body, v)
diff --git a/server/plugin/security/tlsconf/buildin/tlsconf.go 
b/server/plugin/security/tlsconf/buildin/tlsconf.go
index 5df008e..0b25619 100644
--- a/server/plugin/security/tlsconf/buildin/tlsconf.go
+++ b/server/plugin/security/tlsconf/buildin/tlsconf.go
@@ -22,7 +22,7 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/tlsutil"
        "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        
"github.com/apache/servicecomb-service-center/server/plugin/security/cipher"
        "github.com/astaxie/beego"
        "io/ioutil"
@@ -74,11 +74,11 @@ func GetClientTLSConfig() (_ *tls.Config, err error) {
        passphase := GetPassphase()
 
        opts := append(tlsutil.DefaultClientTLSOptions(),
-               tlsutil.WithVerifyPeer(core.ServerInfo.Config.SslVerifyPeer),
+               tlsutil.WithVerifyPeer(config.ServerInfo.Config.SslVerifyPeer),
                tlsutil.WithVerifyHostName(false),
                tlsutil.WithVersion(
                        tlsutil.ParseSSLProtocol(
-                               
beego.AppConfig.DefaultString("ssl_client_min_version", 
core.ServerInfo.Config.SslMinVersion)),
+                               
beego.AppConfig.DefaultString("ssl_client_min_version", 
config.ServerInfo.Config.SslMinVersion)),
                        tlsutil.MaxSupportedTLSVersion),
                
tlsutil.WithCipherSuits(tlsutil.ParseDefaultSSLCipherSuites(beego.AppConfig.String("ssl_client_ciphers"))),
                tlsutil.WithKeyPass(passphase),
@@ -90,7 +90,7 @@ func GetClientTLSConfig() (_ *tls.Config, err error) {
 
        if clientTLSConfig != nil {
                log.Infof("client ssl configs enabled, verifyclient %t, minv 
%#x, cipers %d, pphase %d.",
-                       core.ServerInfo.Config.SslVerifyPeer,
+                       config.ServerInfo.Config.SslVerifyPeer,
                        clientTLSConfig.MinVersion,
                        len(clientTLSConfig.CipherSuites),
                        len(passphase))
@@ -108,9 +108,9 @@ func GetServerTLSConfig() (_ *tls.Config, err error) {
        passphase := GetPassphase()
 
        opts := append(tlsutil.DefaultServerTLSOptions(),
-               tlsutil.WithVerifyPeer(core.ServerInfo.Config.SslVerifyPeer),
-               
tlsutil.WithVersion(tlsutil.ParseSSLProtocol(core.ServerInfo.Config.SslMinVersion),
 tlsutil.MaxSupportedTLSVersion),
-               
tlsutil.WithCipherSuits(tlsutil.ParseDefaultSSLCipherSuites(core.ServerInfo.Config.SslCiphers)),
+               tlsutil.WithVerifyPeer(config.ServerInfo.Config.SslVerifyPeer),
+               
tlsutil.WithVersion(tlsutil.ParseSSLProtocol(config.ServerInfo.Config.SslMinVersion),
 tlsutil.MaxSupportedTLSVersion),
+               
tlsutil.WithCipherSuits(tlsutil.ParseDefaultSSLCipherSuites(config.ServerInfo.Config.SslCiphers)),
                tlsutil.WithKeyPass(passphase),
                tlsutil.WithCA(GetSSLPath("trust.cer")),
                tlsutil.WithCert(GetSSLPath("server.cer")),
@@ -121,7 +121,7 @@ func GetServerTLSConfig() (_ *tls.Config, err error) {
 
        if serverTLSConfig != nil {
                log.Infof("server ssl configs enabled, verifyClient %t, minv 
%#x, ciphers %d, phase %d.",
-                       core.ServerInfo.Config.SslVerifyPeer,
+                       config.ServerInfo.Config.SslVerifyPeer,
                        serverTLSConfig.MinVersion,
                        len(serverTLSConfig.CipherSuites),
                        len(passphase))
diff --git a/server/plugin/tracing/pzipkin/file_collector.go 
b/server/plugin/tracing/pzipkin/file_collector.go
index b77adec..947f482 100644
--- a/server/plugin/tracing/pzipkin/file_collector.go
+++ b/server/plugin/tracing/pzipkin/file_collector.go
@@ -25,7 +25,7 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/gopool"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/openzipkin/zipkin-go-opentracing/thrift/gen-go/zipkincore"
        "os"
        "strings"
@@ -164,8 +164,8 @@ func (f *FileCollector) Run() {
                        case <-t.C:
                                if time.Now().After(nr) {
                                        log.RotateFile(f.Fd.Name(),
-                                               
int(core.ServerInfo.Config.LogRotateSize),
-                                               
int(core.ServerInfo.Config.LogBackupCount),
+                                               
int(config.ServerInfo.Config.LogRotateSize),
+                                               
int(config.ServerInfo.Config.LogBackupCount),
                                        )
                                        nr = time.Now().Add(i)
                                }
diff --git a/server/plugin/types.go b/server/plugin/types.go
index 489fb70..24c6f18 100644
--- a/server/plugin/types.go
+++ b/server/plugin/types.go
@@ -17,7 +17,7 @@ package plugin
 
 import (
        "github.com/apache/servicecomb-service-center/pkg/util"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
 )
 
 // Kind is an alias, it represents a plugin interface.
@@ -37,12 +37,12 @@ func (pn Kind) String() string {
 
 // ActiveConfigs returns all the server's plugin config
 func (pn Kind) ActiveConfigs() util.JSONObject {
-       return core.ServerInfo.Config.Plugins.Object(pn.String())
+       return config.ServerInfo.Config.Plugins.Object(pn.String())
 }
 
 // ClearConfigs clears the server's plugin config
 func (pn Kind) ClearConfigs() {
-       core.ServerInfo.Config.Plugins.Set(pn.String(), nil)
+       config.ServerInfo.Config.Plugins.Set(pn.String(), nil)
 }
 
 // Plugin generates a plugin instance
diff --git a/server/rest/controller/v4/v4.go b/server/resource/register.go
similarity index 73%
copy from server/rest/controller/v4/v4.go
copy to server/resource/register.go
index ad513d9..a062ee8 100644
--- a/server/rest/controller/v4/v4.go
+++ b/server/resource/register.go
@@ -19,6 +19,8 @@ package v4
 
 import (
        roa "github.com/apache/servicecomb-service-center/pkg/rest"
+       v1 "github.com/apache/servicecomb-service-center/server/resource/v1"
+       v4 "github.com/apache/servicecomb-service-center/server/resource/v4"
        "github.com/apache/servicecomb-service-center/server/service/rbac"
 )
 
@@ -28,14 +30,7 @@ func init() {
 
 func initRouter() {
        if rbac.Enabled() {
-               roa.RegisterServant(&AuthResource{})
+               roa.RegisterServant(&v4.AuthResource{})
        }
-       roa.RegisterServant(&MainService{})
-       roa.RegisterServant(&MicroServiceService{})
-       roa.RegisterServant(&SchemaService{})
-       roa.RegisterServant(&DependencyService{})
-       roa.RegisterServant(&TagService{})
-       roa.RegisterServant(&RuleService{})
-       roa.RegisterServant(&MicroServiceInstanceService{})
-       roa.RegisterServant(&WatchService{})
+       roa.RegisterServant(&v1.Governance{})
 }
diff --git a/server/resource/v1/gov_resource.go 
b/server/resource/v1/gov_resource.go
new file mode 100644
index 0000000..9eb3f43
--- /dev/null
+++ b/server/resource/v1/gov_resource.go
@@ -0,0 +1,76 @@
+/*
+ * 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 v1
+
+import (
+       "github.com/apache/servicecomb-service-center/pkg/log"
+       "github.com/apache/servicecomb-service-center/server/rest/controller"
+       "github.com/apache/servicecomb-service-center/server/scerror"
+       "github.com/apache/servicecomb-service-center/server/service/gov"
+       "io/ioutil"
+       "net/http"
+
+       "github.com/apache/servicecomb-service-center/pkg/rest"
+)
+
+type Governance struct {
+}
+
+//Create gov config
+func (t *Governance) Create(w http.ResponseWriter, req *http.Request) {
+       kind := req.URL.Query().Get(":kind")
+       body, err := ioutil.ReadAll(req.Body)
+       if err != nil {
+               log.Error("read body err", err)
+               controller.WriteError(w, scerror.ErrInternal, err.Error())
+               return
+       }
+       err = gov.Create(kind, body)
+       if err != nil {
+               log.Error("create gov err", err)
+               controller.WriteError(w, scerror.ErrInternal, err.Error())
+               return
+       }
+       w.WriteHeader(http.StatusOK)
+}
+
+//Put gov config
+func (t *Governance) Put(w http.ResponseWriter, req *http.Request) {
+
+}
+
+//List return all gov config
+func (t *Governance) List(w http.ResponseWriter, req *http.Request) {
+
+}
+
+//Delete delete gov config
+func (t *Governance) Delete(w http.ResponseWriter, req *http.Request) {
+
+}
+func (t *Governance) URLPatterns() []rest.Route {
+       return []rest.Route{
+               //servicecomb.marker.{name}
+               //servicecomb.rateLimiter.{name}
+               //....
+               {Method: http.MethodPost, Path: "/v1/:project/gov/:kind", Func: 
t.Create},
+               {Method: http.MethodGet, Path: "/v1/:project/gov/:kind", Func: 
t.List},
+               {Method: http.MethodPut, Path: "/v1/:project/gov/:kind/:name", 
Func: t.Put},
+               {Method: http.MethodDelete, Path: 
"/v1/:project/gov/:kind/:name", Func: t.Delete},
+       }
+}
diff --git a/server/resource/v1/gov_resource_test.go 
b/server/resource/v1/gov_resource_test.go
new file mode 100644
index 0000000..30889d1
--- /dev/null
+++ b/server/resource/v1/gov_resource_test.go
@@ -0,0 +1,45 @@
+package v1_test
+
+import (
+       "bytes"
+       "encoding/json"
+       "github.com/apache/servicecomb-service-center/pkg/log"
+       "github.com/apache/servicecomb-service-center/pkg/model"
+       "github.com/apache/servicecomb-service-center/pkg/rest"
+       "github.com/apache/servicecomb-service-center/server/resource/v1"
+       "github.com/apache/servicecomb-service-center/server/service/gov"
+       "github.com/go-chassis/go-archaius"
+       "github.com/stretchr/testify/assert"
+       "net/http"
+       "net/http/httptest"
+       "testing"
+
+       _ "github.com/apache/servicecomb-service-center/server/service/gov/mock"
+)
+
+func init() {
+       err := gov.Init()
+       if err != nil {
+               log.Fatal("", err)
+       }
+}
+func TestAuthResource_Login(t *testing.T) {
+       err := archaius.Init(archaius.WithMemorySource(), 
archaius.WithENVSource())
+       assert.NoError(t, err)
+
+       gov.Init()
+       rest.RegisterServant(&v1.Governance{})
+
+       t.Run("create policy", func(t *testing.T) {
+               b, _ := json.Marshal(&model.LoadBalancer{
+                       GovernancePolicy: &model.GovernancePolicy{Name: "test"},
+                       Spec: &model.LBSpec{
+                               Bo: &model.BackOffPolicy{InitialInterval: 1}}})
+
+               r, _ := http.NewRequest(http.MethodPost, 
"/v1/default/gov/loadBalancer", bytes.NewBuffer(b))
+               w := httptest.NewRecorder()
+               rest.GetRouter().ServeHTTP(w, r)
+               assert.Equal(t, http.StatusOK, w.Code)
+       })
+
+}
diff --git a/server/rest/controller/v4/auth_resource.go 
b/server/resource/v4/auth_resource.go
similarity index 100%
rename from server/rest/controller/v4/auth_resource.go
rename to server/resource/v4/auth_resource.go
diff --git a/server/rest/controller/v4/auth_resource_test.go 
b/server/resource/v4/auth_resource_test.go
similarity index 99%
rename from server/rest/controller/v4/auth_resource_test.go
rename to server/resource/v4/auth_resource_test.go
index 3b483df..3cce791 100644
--- a/server/rest/controller/v4/auth_resource_test.go
+++ b/server/resource/v4/auth_resource_test.go
@@ -6,7 +6,7 @@ import (
        "encoding/json"
        "github.com/apache/servicecomb-service-center/pkg/rbacframe"
        "github.com/apache/servicecomb-service-center/pkg/rest"
-       v4 
"github.com/apache/servicecomb-service-center/server/rest/controller/v4"
+       v4 "github.com/apache/servicecomb-service-center/server/resource/v4"
        "github.com/apache/servicecomb-service-center/server/service/rbac"
        "github.com/apache/servicecomb-service-center/server/service/rbac/dao"
        "github.com/astaxie/beego"
diff --git a/server/rest/controller/v4/dependency_controller.go 
b/server/rest/controller/v4/dependency_controller.go
index d4e2f18..ffcd7c4 100644
--- a/server/rest/controller/v4/dependency_controller.go
+++ b/server/rest/controller/v4/dependency_controller.go
@@ -31,7 +31,6 @@ import (
 )
 
 type DependencyService struct {
-       //
 }
 
 func (s *DependencyService) URLPatterns() []rest.Route {
@@ -43,6 +42,7 @@ func (s *DependencyService) URLPatterns() []rest.Route {
        }
 }
 
+//Deprecated
 func (s *DependencyService) AddDependenciesForMicroServices(w 
http.ResponseWriter, r *http.Request) {
        requestBody, err := ioutil.ReadAll(r.Body)
        if err != nil {
diff --git a/server/rest/controller/v4/main_controller.go 
b/server/rest/controller/v4/main_controller.go
index e69f989..e8a98c7 100644
--- a/server/rest/controller/v4/main_controller.go
+++ b/server/rest/controller/v4/main_controller.go
@@ -22,6 +22,7 @@ import (
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/pkg/rest"
        "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/apache/servicecomb-service-center/server/core/proto"
        "github.com/apache/servicecomb-service-center/server/rest/controller"
        "github.com/apache/servicecomb-service-center/version"
@@ -66,7 +67,7 @@ func (s *MainService) GetVersion(w http.ResponseWriter, r 
*http.Request) {
                result := Result{
                        version.Ver(),
                        APIVersion,
-                       &core.ServerInfo.Config,
+                       &config.ServerInfo.Config,
                }
                versionJSONCache, _ = json.Marshal(result)
                versionResp = proto.CreateResponse(proto.ResponseSuccess, "get 
version successfully")
diff --git a/server/rest/controller/v4/schema_controller.go 
b/server/rest/controller/v4/schema_controller.go
index cefc20d..4762dcf 100644
--- a/server/rest/controller/v4/schema_controller.go
+++ b/server/rest/controller/v4/schema_controller.go
@@ -24,6 +24,7 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/rest"
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/apache/servicecomb-service-center/server/rest/controller"
        scerr "github.com/apache/servicecomb-service-center/server/scerror"
        "io/ioutil"
@@ -43,7 +44,7 @@ func (s *SchemaService) URLPatterns() []rest.Route {
                {Method: rest.HTTPMethodGet, Path: 
"/v4/:project/registry/microservices/:serviceId/schemas", Func: 
s.GetAllSchemas},
        }
 
-       if !core.ServerInfo.Config.SchemaDisable {
+       if !config.ServerInfo.Config.SchemaDisable {
                r = append(r, rest.Route{Method: rest.HTTPMethodPut, Path: 
"/v4/:project/registry/microservices/:serviceId/schemas/:schemaId", Func: 
s.ModifySchema})
        } else {
                r = append(r, rest.Route{Method: rest.HTTPMethodPut, Path: 
"/v4/:project/registry/microservices/:serviceId/schemas/:schemaId", Func: 
s.DisableSchema})
diff --git a/server/rest/controller/v4/v4.go b/server/rest/controller/v4/v4.go
index ad513d9..4944ff8 100644
--- a/server/rest/controller/v4/v4.go
+++ b/server/rest/controller/v4/v4.go
@@ -19,7 +19,6 @@ package v4
 
 import (
        roa "github.com/apache/servicecomb-service-center/pkg/rest"
-       "github.com/apache/servicecomb-service-center/server/service/rbac"
 )
 
 func init() {
@@ -27,9 +26,6 @@ func init() {
 }
 
 func initRouter() {
-       if rbac.Enabled() {
-               roa.RegisterServant(&AuthResource{})
-       }
        roa.RegisterServant(&MainService{})
        roa.RegisterServant(&MicroServiceService{})
        roa.RegisterServant(&SchemaService{})
diff --git a/server/rest/pprof.go b/server/rest/pprof.go
index 22d401d..47e03bd 100644
--- a/server/rest/pprof.go
+++ b/server/rest/pprof.go
@@ -18,13 +18,13 @@
 package rest
 
 import (
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "net/http"
        "net/http/pprof"
 )
 
 func init() {
-       if core.ServerInfo.Config.EnablePProf {
+       if config.ServerInfo.Config.EnablePProf {
                RegisterServerHandleFunc("/debug/pprof/", 
http.HandlerFunc(pprof.Index))
                RegisterServerHandleFunc("/debug/pprof/profile", 
http.HandlerFunc(pprof.Profile))
                RegisterServerHandleFunc("/debug/pprof/symbol", 
http.HandlerFunc(pprof.Symbol))
diff --git a/server/rest/server.go b/server/rest/server.go
index 69b0bb0..0827385 100644
--- a/server/rest/server.go
+++ b/server/rest/server.go
@@ -20,20 +20,20 @@ package rest
 import (
        "crypto/tls"
        "github.com/apache/servicecomb-service-center/pkg/rest"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        
"github.com/apache/servicecomb-service-center/server/plugin/security/tlsconf"
        "time"
 )
 
 func LoadConfig() (srvCfg *rest.ServerConfig, err error) {
        srvCfg = rest.DefaultServerConfig()
-       readHeaderTimeout, _ := 
time.ParseDuration(core.ServerInfo.Config.ReadHeaderTimeout)
-       readTimeout, _ := time.ParseDuration(core.ServerInfo.Config.ReadTimeout)
-       idleTimeout, _ := time.ParseDuration(core.ServerInfo.Config.IdleTimeout)
-       writeTimeout, _ := 
time.ParseDuration(core.ServerInfo.Config.WriteTimeout)
-       maxHeaderBytes := int(core.ServerInfo.Config.MaxHeaderBytes)
+       readHeaderTimeout, _ := 
time.ParseDuration(config.ServerInfo.Config.ReadHeaderTimeout)
+       readTimeout, _ := 
time.ParseDuration(config.ServerInfo.Config.ReadTimeout)
+       idleTimeout, _ := 
time.ParseDuration(config.ServerInfo.Config.IdleTimeout)
+       writeTimeout, _ := 
time.ParseDuration(config.ServerInfo.Config.WriteTimeout)
+       maxHeaderBytes := int(config.ServerInfo.Config.MaxHeaderBytes)
        var tlsConfig *tls.Config
-       if core.ServerInfo.Config.SslEnabled {
+       if config.ServerInfo.Config.SslEnabled {
                tlsConfig, err = tlsconf.ServerConfig()
                if err != nil {
                        return
diff --git a/server/server.go b/server/server.go
index 7c2f01d..beaaf7b 100644
--- a/server/server.go
+++ b/server/server.go
@@ -23,9 +23,12 @@ import (
        "github.com/apache/servicecomb-service-center/pkg/gopool"
        "github.com/apache/servicecomb-service-center/pkg/log"
        nf "github.com/apache/servicecomb-service-center/pkg/notify"
+       "github.com/apache/servicecomb-service-center/server/command"
        "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/apache/servicecomb-service-center/server/notify"
        "github.com/apache/servicecomb-service-center/server/plugin"
+       "github.com/apache/servicecomb-service-center/server/service/gov"
        "github.com/apache/servicecomb-service-center/server/service/rbac"
        "github.com/astaxie/beego"
        "os"
@@ -34,6 +37,10 @@ import (
 var server ServiceCenterServer
 
 func Run() {
+       if err := command.ParseConfig(os.Args); err != nil {
+               log.Fatal(err.Error(), err)
+       }
+
        server.Run()
 }
 
@@ -71,8 +78,11 @@ func (s *ServiceCenterServer) startServices() {
        // load server plugins
        plugin.LoadPlugins()
        rbac.Init()
+       if err := gov.Init(); err != nil {
+               log.Fatal("init gov failed", err)
+       }
        // check version
-       if core.ServerInfo.Config.SelfRegister {
+       if config.ServerInfo.Config.SelfRegister {
                if err := 
datasource.Instance().UpgradeVersion(context.Background()); err != nil {
                        os.Exit(1)
                }
diff --git a/server/service/event/dependency_event_handler.go 
b/server/service/event/dependency_event_handler.go
index 2bf980c..303d8b4 100644
--- a/server/service/event/dependency_event_handler.go
+++ b/server/service/event/dependency_event_handler.go
@@ -32,6 +32,7 @@ import (
        pb "github.com/apache/servicecomb-service-center/pkg/registry"
        "github.com/apache/servicecomb-service-center/pkg/util"
        "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/apache/servicecomb-service-center/server/core/proto"
        "time"
 )
@@ -101,8 +102,8 @@ func (h *DependencyEventHandler) eventLoop() {
        gopool.Go(func(ctx context.Context) {
                // the events will lose, need to handle dependence records 
periodically
                period := defaultEventHandleInterval
-               if core.ServerInfo.Config.CacheTTL > 0 {
-                       period = core.ServerInfo.Config.CacheTTL
+               if config.ServerInfo.Config.CacheTTL > 0 {
+                       period = config.ServerInfo.Config.CacheTTL
                }
                timer := time.NewTimer(period)
                retries := 0
diff --git a/server/service/gov/config_distributor.go 
b/server/service/gov/config_distributor.go
new file mode 100644
index 0000000..58f0f07
--- /dev/null
+++ b/server/service/gov/config_distributor.go
@@ -0,0 +1,84 @@
+/*
+ * 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 gov
+
+import (
+       "github.com/apache/servicecomb-service-center/pkg/log"
+       "github.com/apache/servicecomb-service-center/server/core/config"
+)
+
+const (
+       ConfigDistributorKie   = "kie"
+       ConfigDistributorIstio = "istio"
+       ConfigDistributorMock  = "mock"
+)
+
+type NewDistributors func(opts config.DistributorOptions) (ConfigDistributor, 
error)
+
+var distributors = map[string]ConfigDistributor{}
+var distributorPlugins = map[string]NewDistributors{}
+
+//ConfigDistributor persist and distribute Governance policy
+//typically, a ConfigDistributor interact with a config server, like ctrip 
apollo, kie.
+//or service mesh system like istio, linkerd.
+//ConfigDistributor will convert standard servicecomb gov config to concrete 
spec, that data plane can recognize.
+type ConfigDistributor interface {
+       Create(kind string, spec []byte) error
+       Update(kind string, spec []byte) error
+       Delete(name, kind string) error
+       List(kind string) ([]byte, error)
+       Type() string
+       Name() string
+}
+
+//InstallDistributor install a plugin to distribute and persist config
+func InstallDistributor(t string, newDistributors NewDistributors) {
+       distributorPlugins[t] = newDistributors
+}
+
+//Init create distributors according to gov config.
+//it may creates multiple distributors. and distribute policy one by one
+func Init() error {
+       distOptions := config.GetGov().DistOptions
+       for _, opts := range distOptions {
+               if opts.Type == "" {
+                       log.Warn("empty plugin, skip")
+               }
+               f, ok := distributorPlugins[opts.Type]
+               if !ok {
+                       log.Warn("unsupported plugin " + opts.Type)
+               }
+               cd, err := f(opts)
+               if err != nil {
+                       log.Error("can not init config distributor", err)
+                       return err
+               }
+               distributors[opts.Name+"::"+opts.Type] = cd
+       }
+       return nil
+}
+func Create(kind string, spec []byte) error {
+       var err error
+       for _, cd := range distributors {
+               err = cd.Create(kind, spec)
+               if err != nil {
+                       return err
+               }
+       }
+       return nil
+}
diff --git a/server/service/gov/config_distributor_test.go 
b/server/service/gov/config_distributor_test.go
new file mode 100644
index 0000000..9d63932
--- /dev/null
+++ b/server/service/gov/config_distributor_test.go
@@ -0,0 +1,51 @@
+/*
+ * 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 gov_test
+
+import (
+       "encoding/json"
+       "github.com/apache/servicecomb-service-center/pkg/model"
+       "github.com/apache/servicecomb-service-center/server/core/config"
+       "github.com/apache/servicecomb-service-center/server/service/gov"
+       _ "github.com/apache/servicecomb-service-center/server/service/gov/mock"
+       "github.com/stretchr/testify/assert"
+       "testing"
+)
+
+func TestCreate(t *testing.T) {
+       config.Configurations = &config.Config{
+               Gov: config.Gov{
+                       DistOptions: []config.DistributorOptions{
+                               {
+                                       Name: "mockServer",
+                                       Type: "mock",
+                               },
+                       },
+               },
+       }
+       err := gov.Init()
+       assert.NoError(t, err)
+       b, _ := json.MarshalIndent(&model.LoadBalancer{
+               GovernancePolicy: &model.GovernancePolicy{
+                       Name: "Traffic2adminAPI",
+               },
+               Spec: &model.LBSpec{RetryNext: 3, MarkerName: 
"traffic2adminAPI"},
+       }, "", "  ")
+       err = gov.Create("lb", b)
+       assert.NoError(t, err)
+}
diff --git a/server/service/gov/mock/mock.go b/server/service/gov/mock/mock.go
new file mode 100644
index 0000000..6bb7b83
--- /dev/null
+++ b/server/service/gov/mock/mock.go
@@ -0,0 +1,71 @@
+/*
+ * 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 mock
+
+import (
+       "encoding/json"
+       "fmt"
+       "github.com/apache/servicecomb-service-center/pkg/model"
+       "github.com/apache/servicecomb-service-center/server/core/config"
+       "github.com/apache/servicecomb-service-center/server/service/gov"
+       "log"
+)
+
+type Distributor struct {
+       lbPolicies map[string]*model.LoadBalancer
+       name       string
+}
+
+func (d *Distributor) Create(kind string, spec []byte) error {
+       p := &model.LoadBalancer{}
+       err := json.Unmarshal(spec, p)
+       log.Println(fmt.Sprintf("create %v", &p))
+       d.lbPolicies[p.GovernancePolicy.Name] = p
+       return err
+}
+func (d *Distributor) Update(kind string, spec []byte) error {
+       p := &model.LoadBalancer{}
+       err := json.Unmarshal(spec, p)
+       log.Println("update ", p)
+       d.lbPolicies[p.GovernancePolicy.Name] = p
+       return err
+}
+func (d *Distributor) Delete(name, kind string) error {
+       delete(d.lbPolicies, name)
+       return nil
+}
+func (d *Distributor) List(kind string) ([]byte, error) {
+       r := make([]*model.LoadBalancer, len(d.lbPolicies))
+       for _, g := range d.lbPolicies {
+               r = append(r, g)
+       }
+       b, _ := json.MarshalIndent(r, "", "  ")
+       return b, nil
+}
+func (d *Distributor) Type() string {
+       return gov.ConfigDistributorMock
+}
+func (d *Distributor) Name() string {
+       return d.name
+}
+func new(opts config.DistributorOptions) (gov.ConfigDistributor, error) {
+       return &Distributor{name: opts.Name, lbPolicies: 
map[string]*model.LoadBalancer{}}, nil
+}
+func init() {
+       gov.InstallDistributor(gov.ConfigDistributorMock, new)
+}
diff --git a/server/service/rbac/rbac.go b/server/service/rbac/rbac.go
index bff6c6c..1d793d3 100644
--- a/server/service/rbac/rbac.go
+++ b/server/service/rbac/rbac.go
@@ -23,7 +23,7 @@ import (
        "errors"
        "github.com/apache/servicecomb-service-center/pkg/log"
        "github.com/apache/servicecomb-service-center/pkg/rbacframe"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        
"github.com/apache/servicecomb-service-center/server/plugin/security/cipher"
        "github.com/apache/servicecomb-service-center/server/service"
        "github.com/apache/servicecomb-service-center/server/service/rbac/dao"
@@ -72,7 +72,7 @@ func Init() {
        readPrivateKey()
        readPublicKey()
        rbacframe.Add2WhiteAPIList("/v4/token")
-       core.ServerInfo.Config.EnableRBAC = true
+       config.ServerInfo.Config.EnableRBAC = true
        log.Info("rbac is enabled")
 }
 func initResourceMap() {
diff --git a/server/service/service_suite_test.go 
b/server/service/service_suite_test.go
index f0157c7..850a3ce 100644
--- a/server/service/service_suite_test.go
+++ b/server/service/service_suite_test.go
@@ -17,7 +17,10 @@
 package service_test
 
 // initialize
-import _ "github.com/apache/servicecomb-service-center/server/bootstrap"
+import (
+       _ "github.com/apache/servicecomb-service-center/server/bootstrap"
+       "github.com/apache/servicecomb-service-center/server/core/config"
+)
 import (
        "context"
        "github.com/apache/servicecomb-service-center/pkg/util"
@@ -42,7 +45,7 @@ func init() {
 
 var _ = BeforeSuite(func() {
        //init plugin
-       core.ServerInfo.Config.EnableCache = false
+       config.ServerInfo.Config.EnableCache = false
        serviceResource, instanceResource = service.AssembleResources()
 })
 
diff --git a/test/test.go b/test/test.go
index e7cf9d7..b183ec2 100644
--- a/test/test.go
+++ b/test/test.go
@@ -20,11 +20,11 @@ package test
 
 import (
        _ "github.com/apache/servicecomb-service-center/server/bootstrap"
-       "github.com/apache/servicecomb-service-center/server/core"
+       "github.com/apache/servicecomb-service-center/server/core/config"
        "github.com/astaxie/beego"
 )
 
 func init() {
        beego.AppConfig.Set("registry_plugin", "etcd")
-       core.ServerInfo.Config.MaxBodyBytes = 2097152
+       config.ServerInfo.Config.MaxBodyBytes = 2097152
 }

Reply via email to