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 5aefae9  user go chassis as service center grpc development framework 
(#1166)
5aefae9 is described below

commit 5aefae96ec4829c19697d96dd6fea13c73759c79
Author: Shawn <[email protected]>
AuthorDate: Mon Nov 15 22:04:36 2021 +0800

    user go chassis as service center grpc development framework (#1166)
---
 .github/workflows/golangci-lint.yml                |   2 +-
 .gitignore                                         |   5 +-
 api/README.md                                      |  12 +
 api/go.mod                                         |   8 +
 api/go.sum                                         | 116 ++++++
 api/sync/v1/event_service.pb.go                    | 405 +++++++++++++++++++++
 api/sync/v1/event_service.proto                    |  23 ++
 api/sync/v1/event_service_grpc.pb.go               | 101 +++++
 client/set.go                                      |  31 ++
 client/set_test.go                                 |  21 ++
 etc/conf/app.yaml                                  |  17 +
 etc/conf/chassis.yaml                              |  20 +
 etc/conf/microservice.yaml                         |   4 +
 .../service_center/body/add_sync_whitelist.json    |  21 ++
 go.mod                                             |  11 +-
 go.sum                                             |   8 +
 pkg/util/net_test.go                               |   3 +-
 server/{api.go => api_server.go}                   |   0
 server/core/core.go                                |   8 +
 server/rpc/sync/server.go                          |  18 +
 server/server.go                                   |  14 +-
 test/test.go                                       |  32 ++
 22 files changed, 873 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/golangci-lint.yml 
b/.github/workflows/golangci-lint.yml
index fb91c91..f6fee38 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -10,4 +10,4 @@ jobs:
         uses: golangci/golangci-lint-action@v2
         with:
           version: v1.29
-          args: --timeout=5m 
--skip-dirs='test,.*/controller/(v3|v4)$,.*/bootstrap$,server/broker,examples,frontend,scctl,integration'
 --enable gofmt,golint,gocyclo,goimports --skip-files=.*_test.go$
+          args: --timeout=5m 
--skip-dirs='api,test,.*/controller/(v3|v4)$,.*/bootstrap$,server/broker,examples,frontend,scctl,integration'
 --enable gofmt,golint,gocyclo,goimports --skip-files=.*_test.go$
diff --git a/.gitignore b/.gitignore
index a3f95a3..9c1bd17 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,10 @@ output
 **/*.log
 syncer/syncer
 
+#binary
+scserver
+main
+
 *.iml
 .idea/
 **/*junit.xml
@@ -37,7 +41,6 @@ docs/_static
 docs/_templates
 
 .DS_Store
-main
 # go mod
 
 # VS Code Project files
diff --git a/api/README.md b/api/README.md
new file mode 100644
index 0000000..cc40108
--- /dev/null
+++ b/api/README.md
@@ -0,0 +1,12 @@
+# ServiceComb gRPC API
+This go module contains all grpc service definition of service center 
+
+### APIs
+#### sync
+service center metadata sync APIs, used in service center peer clusters data 
sync
+### Development Guide
+#### To generate grpc code
+```shell
+cd api/sync/v1
+protoc --go_out=. --go-grpc_out=. event_service.proto
+```
\ No newline at end of file
diff --git a/api/go.mod b/api/go.mod
new file mode 100644
index 0000000..1e55e9e
--- /dev/null
+++ b/api/go.mod
@@ -0,0 +1,8 @@
+module github.com/apache/servicecomb-service-center/api
+
+go 1.16
+
+require (
+       google.golang.org/grpc v1.40.0
+       google.golang.org/protobuf v1.27.1
+)
diff --git a/api/go.sum b/api/go.sum
new file mode 100644
index 0000000..19b643b
--- /dev/null
+++ b/api/go.sum
@@ -0,0 +1,116 @@
+cloud.google.com/go v0.26.0/go.mod 
h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.34.0/go.mod 
h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod 
h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/OneOfOne/xxhash v1.2.2/go.mod 
h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/antihax/optional v1.0.0/go.mod 
h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod 
h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash v1.1.0/go.mod 
h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
+github.com/client9/misspell v0.3.4/go.mod 
h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod 
h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod 
h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod 
h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/davecgh/go-spew v1.1.0/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod 
h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane 
v0.9.1-0.20191026205805-5f8ba28d4473/go.mod 
h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod 
h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane 
v0.9.9-0.20201210154907-fd9021fe5dad/go.mod 
h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane 
v0.9.9-0.20210512163311-63b5d3c536b0/go.mod 
h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod 
h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/ghodss/yaml v1.0.0/go.mod 
h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod 
h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod 
h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod 
h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod 
h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod 
h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod 
h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod 
h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod 
h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod 
h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod 
h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod 
h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2/go.mod 
h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.4.3/go.mod 
h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0 
h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
+github.com/golang/protobuf v1.5.0/go.mod 
h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/google/go-cmp v0.2.0/go.mod 
h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod 
h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod 
h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0/go.mod 
h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0/go.mod 
h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
+github.com/google/go-cmp v0.5.5/go.mod 
h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/uuid v1.1.2/go.mod 
h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod 
h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/pmezard/go-difflib v1.0.0/go.mod 
h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod 
h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod 
h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod 
h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/stretchr/objx v0.1.0/go.mod 
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.5.1/go.mod 
h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod 
h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod 
h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod 
h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod 
h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod 
h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod 
h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod 
h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod 
h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod 
h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod 
h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20200822124328-c89045814202 
h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
+golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod 
h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod 
h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod 
h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod 
h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod 
h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd 
h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod 
h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod 
h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod 
h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod 
h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod 
h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 
h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod 
h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod 
h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod 
h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod 
h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod 
h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod 
h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 
h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod 
h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/grpc v1.19.0/go.mod 
h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod 
h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod 
h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod 
h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.33.1/go.mod 
h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.36.0/go.mod 
h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
+google.golang.org/grpc v1.40.0/go.mod 
h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod 
h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod 
h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod 
h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod 
h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod 
h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod 
h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod 
h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod 
h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.25.0/go.mod 
h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod 
h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.27.1 
h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
+google.golang.org/protobuf v1.27.1/go.mod 
h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod 
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod 
h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/api/sync/v1/event_service.pb.go b/api/sync/v1/event_service.pb.go
new file mode 100644
index 0000000..4570fab
--- /dev/null
+++ b/api/sync/v1/event_service.pb.go
@@ -0,0 +1,405 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+//     protoc-gen-go v1.27.1
+//     protoc        v3.17.3
+// source: event_service.proto
+
+package v1
+
+import (
+       protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+       protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+       reflect "reflect"
+       sync "sync"
+)
+
+const (
+       // Verify that this generated code is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+       // Verify that runtime/protoimpl is sufficiently up-to-date.
+       _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type EventList struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Events []*Event `protobuf:"bytes,1,rep,name=Events,proto3" 
json:"Events,omitempty"`
+}
+
+func (x *EventList) Reset() {
+       *x = EventList{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_event_service_proto_msgTypes[0]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *EventList) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EventList) ProtoMessage() {}
+
+func (x *EventList) ProtoReflect() protoreflect.Message {
+       mi := &file_event_service_proto_msgTypes[0]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use EventList.ProtoReflect.Descriptor instead.
+func (*EventList) Descriptor() ([]byte, []int) {
+       return file_event_service_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *EventList) GetEvents() []*Event {
+       if x != nil {
+               return x.Events
+       }
+       return nil
+}
+
+type Event struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Id      string            `protobuf:"bytes,1,opt,name=id,proto3" 
json:"id,omitempty"`                                                            
                                 //entity id
+       Action  string            `protobuf:"bytes,2,opt,name=action,proto3" 
json:"action,omitempty"`                                                        
                             //create, delete, update
+       Subject string            `protobuf:"bytes,3,opt,name=subject,proto3" 
json:"subject,omitempty"`                                                       
                            //a entity name such as account, role, service, 
instance
+       Opts    map[string]string `protobuf:"bytes,4,rep,name=opts,proto3" 
json:"opts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" 
protobuf_val:"bytes,2,opt,name=value,proto3"` //metadata or options
+       Value   []byte            `protobuf:"bytes,5,opt,name=value,proto3" 
json:"value,omitempty"`                                                         
                              // the entity
+}
+
+func (x *Event) Reset() {
+       *x = Event{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_event_service_proto_msgTypes[1]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *Event) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Event) ProtoMessage() {}
+
+func (x *Event) ProtoReflect() protoreflect.Message {
+       mi := &file_event_service_proto_msgTypes[1]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use Event.ProtoReflect.Descriptor instead.
+func (*Event) Descriptor() ([]byte, []int) {
+       return file_event_service_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *Event) GetId() string {
+       if x != nil {
+               return x.Id
+       }
+       return ""
+}
+
+func (x *Event) GetAction() string {
+       if x != nil {
+               return x.Action
+       }
+       return ""
+}
+
+func (x *Event) GetSubject() string {
+       if x != nil {
+               return x.Subject
+       }
+       return ""
+}
+
+func (x *Event) GetOpts() map[string]string {
+       if x != nil {
+               return x.Opts
+       }
+       return nil
+}
+
+func (x *Event) GetValue() []byte {
+       if x != nil {
+               return x.Value
+       }
+       return nil
+}
+
+type Results struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Results map[string]*Result `protobuf:"bytes,1,rep,name=results,proto3" 
json:"results,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" 
protobuf_val:"bytes,2,opt,name=value,proto3"` //id to result
+}
+
+func (x *Results) Reset() {
+       *x = Results{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_event_service_proto_msgTypes[2]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *Results) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Results) ProtoMessage() {}
+
+func (x *Results) ProtoReflect() protoreflect.Message {
+       mi := &file_event_service_proto_msgTypes[2]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use Results.ProtoReflect.Descriptor instead.
+func (*Results) Descriptor() ([]byte, []int) {
+       return file_event_service_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *Results) GetResults() map[string]*Result {
+       if x != nil {
+               return x.Results
+       }
+       return nil
+}
+
+type Result struct {
+       state         protoimpl.MessageState
+       sizeCache     protoimpl.SizeCache
+       unknownFields protoimpl.UnknownFields
+
+       Code    int32  `protobuf:"varint,1,opt,name=code,proto3" 
json:"code,omitempty"` //reuse standard http code
+       Message string `protobuf:"bytes,2,opt,name=message,proto3" 
json:"message,omitempty"`
+}
+
+func (x *Result) Reset() {
+       *x = Result{}
+       if protoimpl.UnsafeEnabled {
+               mi := &file_event_service_proto_msgTypes[3]
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               ms.StoreMessageInfo(mi)
+       }
+}
+
+func (x *Result) String() string {
+       return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Result) ProtoMessage() {}
+
+func (x *Result) ProtoReflect() protoreflect.Message {
+       mi := &file_event_service_proto_msgTypes[3]
+       if protoimpl.UnsafeEnabled && x != nil {
+               ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+               if ms.LoadMessageInfo() == nil {
+                       ms.StoreMessageInfo(mi)
+               }
+               return ms
+       }
+       return mi.MessageOf(x)
+}
+
+// Deprecated: Use Result.ProtoReflect.Descriptor instead.
+func (*Result) Descriptor() ([]byte, []int) {
+       return file_event_service_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *Result) GetCode() int32 {
+       if x != nil {
+               return x.Code
+       }
+       return 0
+}
+
+func (x *Result) GetMessage() string {
+       if x != nil {
+               return x.Message
+       }
+       return ""
+}
+
+var File_event_service_proto protoreflect.FileDescriptor
+
+var file_event_service_proto_rawDesc = []byte{
+       0x0a, 0x13, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x76, 
0x69, 0x63, 0x65, 0x2e,
+       0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x61, 0x70, 0x69, 0x2e, 0x73, 
0x79, 0x6e, 0x63, 0x2e,
+       0x76, 0x31, 0x22, 0x37, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 
0x69, 0x73, 0x74, 0x12,
+       0x2a, 0x0a, 0x06, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 
0x03, 0x28, 0x0b, 0x32,
+       0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x79, 0x6e, 0x63, 0x2e, 0x76, 
0x31, 0x2e, 0x45, 0x76,
+       0x65, 0x6e, 0x74, 0x52, 0x06, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 
0xca, 0x01, 0x0a, 0x05,
+       0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 
0x01, 0x20, 0x01, 0x28,
+       0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 
0x69, 0x6f, 0x6e, 0x18,
+       0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 
0x6e, 0x12, 0x18, 0x0a,
+       0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 
0x28, 0x09, 0x52, 0x07,
+       0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x30, 0x0a, 0x04, 0x6f, 
0x70, 0x74, 0x73, 0x18,
+       0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 
0x73, 0x79, 0x6e, 0x63,
+       0x2e, 0x76, 0x31, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x4f, 0x70, 
0x74, 0x73, 0x45, 0x6e,
+       0x74, 0x72, 0x79, 0x52, 0x04, 0x6f, 0x70, 0x74, 0x73, 0x12, 0x14, 0x0a, 
0x05, 0x76, 0x61, 0x6c,
+       0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 
0x6c, 0x75, 0x65, 0x1a,
+       0x37, 0x0a, 0x09, 0x4f, 0x70, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 
0x12, 0x10, 0x0a, 0x03,
+       0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 
0x65, 0x79, 0x12, 0x14,
+       0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 
0x09, 0x52, 0x05, 0x76,
+       0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x97, 0x01, 0x0a, 
0x07, 0x52, 0x65, 0x73,
+       0x75, 0x6c, 0x74, 0x73, 0x12, 0x3b, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 
0x6c, 0x74, 0x73, 0x18,
+       0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 
0x73, 0x79, 0x6e, 0x63,
+       0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x2e, 
0x52, 0x65, 0x73, 0x75,
+       0x6c, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x72, 0x65, 
0x73, 0x75, 0x6c, 0x74,
+       0x73, 0x1a, 0x4f, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 
0x45, 0x6e, 0x74, 0x72,
+       0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 
0x28, 0x09, 0x52, 0x03,
+       0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 
0x18, 0x02, 0x20, 0x01,
+       0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x79, 0x6e, 
0x63, 0x2e, 0x76, 0x31,
+       0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 
0x75, 0x65, 0x3a, 0x02,
+       0x38, 0x01, 0x22, 0x36, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 
0x12, 0x12, 0x0a, 0x04,
+       0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 
0x63, 0x6f, 0x64, 0x65,
+       0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 
0x02, 0x20, 0x01, 0x28,
+       0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x46, 
0x0a, 0x0c, 0x45, 0x76,
+       0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x36, 
0x0a, 0x04, 0x53, 0x79,
+       0x6e, 0x63, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x79, 0x6e, 
0x63, 0x2e, 0x76, 0x31,
+       0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x14, 
0x2e, 0x61, 0x70, 0x69,
+       0x2e, 0x73, 0x79, 0x6e, 0x63, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 
0x75, 0x6c, 0x74, 0x73,
+       0x22, 0x00, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 
0x2e, 0x63, 0x6f, 0x6d,
+       0x2f, 0x61, 0x70, 0x61, 0x63, 0x68, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 
0x69, 0x63, 0x65, 0x63,
+       0x6f, 0x6d, 0x62, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2d, 
0x63, 0x65, 0x6e, 0x74,
+       0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x2f, 
0x76, 0x31, 0x3b, 0x76,
+       0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+       file_event_service_proto_rawDescOnce sync.Once
+       file_event_service_proto_rawDescData = file_event_service_proto_rawDesc
+)
+
+func file_event_service_proto_rawDescGZIP() []byte {
+       file_event_service_proto_rawDescOnce.Do(func() {
+               file_event_service_proto_rawDescData = 
protoimpl.X.CompressGZIP(file_event_service_proto_rawDescData)
+       })
+       return file_event_service_proto_rawDescData
+}
+
+var file_event_service_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
+var file_event_service_proto_goTypes = []interface{}{
+       (*EventList)(nil), // 0: api.sync.v1.EventList
+       (*Event)(nil),     // 1: api.sync.v1.Event
+       (*Results)(nil),   // 2: api.sync.v1.Results
+       (*Result)(nil),    // 3: api.sync.v1.Result
+       nil,               // 4: api.sync.v1.Event.OptsEntry
+       nil,               // 5: api.sync.v1.Results.ResultsEntry
+}
+var file_event_service_proto_depIdxs = []int32{
+       1, // 0: api.sync.v1.EventList.Events:type_name -> api.sync.v1.Event
+       4, // 1: api.sync.v1.Event.opts:type_name -> api.sync.v1.Event.OptsEntry
+       5, // 2: api.sync.v1.Results.results:type_name -> 
api.sync.v1.Results.ResultsEntry
+       3, // 3: api.sync.v1.Results.ResultsEntry.value:type_name -> 
api.sync.v1.Result
+       0, // 4: api.sync.v1.EventService.Sync:input_type -> 
api.sync.v1.EventList
+       2, // 5: api.sync.v1.EventService.Sync:output_type -> 
api.sync.v1.Results
+       5, // [5:6] is the sub-list for method output_type
+       4, // [4:5] is the sub-list for method input_type
+       4, // [4:4] is the sub-list for extension type_name
+       4, // [4:4] is the sub-list for extension extendee
+       0, // [0:4] is the sub-list for field type_name
+}
+
+func init() { file_event_service_proto_init() }
+func file_event_service_proto_init() {
+       if File_event_service_proto != nil {
+               return
+       }
+       if !protoimpl.UnsafeEnabled {
+               file_event_service_proto_msgTypes[0].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*EventList); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_event_service_proto_msgTypes[1].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*Event); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_event_service_proto_msgTypes[2].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*Results); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+               file_event_service_proto_msgTypes[3].Exporter = func(v 
interface{}, i int) interface{} {
+                       switch v := v.(*Result); i {
+                       case 0:
+                               return &v.state
+                       case 1:
+                               return &v.sizeCache
+                       case 2:
+                               return &v.unknownFields
+                       default:
+                               return nil
+                       }
+               }
+       }
+       type x struct{}
+       out := protoimpl.TypeBuilder{
+               File: protoimpl.DescBuilder{
+                       GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+                       RawDescriptor: file_event_service_proto_rawDesc,
+                       NumEnums:      0,
+                       NumMessages:   6,
+                       NumExtensions: 0,
+                       NumServices:   1,
+               },
+               GoTypes:           file_event_service_proto_goTypes,
+               DependencyIndexes: file_event_service_proto_depIdxs,
+               MessageInfos:      file_event_service_proto_msgTypes,
+       }.Build()
+       File_event_service_proto = out.File
+       file_event_service_proto_rawDesc = nil
+       file_event_service_proto_goTypes = nil
+       file_event_service_proto_depIdxs = nil
+}
diff --git a/api/sync/v1/event_service.proto b/api/sync/v1/event_service.proto
new file mode 100644
index 0000000..004938f
--- /dev/null
+++ b/api/sync/v1/event_service.proto
@@ -0,0 +1,23 @@
+syntax = "proto3";
+package api.sync.v1;
+option 
go_package="github.com/apache/servicecomb-service-center/api/sync/v1;v1";
+message EventList {
+  repeated Event Events= 1;
+}
+message Event {
+  string id = 1;      //entity id
+  string action = 2;  //create, delete, update
+  string subject = 3; //a entity name such as account, role, service, instance
+  map<string, string> opts = 4; //metadata or options
+  bytes value = 5; // the entity
+}
+message Results {
+  map<string, Result> results = 1; //id to result
+}
+message Result {
+  int32  code  = 1; //reuse standard http code
+  string message = 2;
+}
+service EventService {
+  rpc Sync(EventList) returns (Results) {}
+}
\ No newline at end of file
diff --git a/api/sync/v1/event_service_grpc.pb.go 
b/api/sync/v1/event_service_grpc.pb.go
new file mode 100644
index 0000000..e32d7c0
--- /dev/null
+++ b/api/sync/v1/event_service_grpc.pb.go
@@ -0,0 +1,101 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+
+package v1
+
+import (
+       context "context"
+       grpc "google.golang.org/grpc"
+       codes "google.golang.org/grpc/codes"
+       status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// EventServiceClient is the client API for EventService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please 
refer to 
https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type EventServiceClient interface {
+       Sync(ctx context.Context, in *EventList, opts ...grpc.CallOption) 
(*Results, error)
+}
+
+type eventServiceClient struct {
+       cc grpc.ClientConnInterface
+}
+
+func NewEventServiceClient(cc grpc.ClientConnInterface) EventServiceClient {
+       return &eventServiceClient{cc}
+}
+
+func (c *eventServiceClient) Sync(ctx context.Context, in *EventList, opts 
...grpc.CallOption) (*Results, error) {
+       out := new(Results)
+       err := c.cc.Invoke(ctx, "/api.sync.v1.EventService/Sync", in, out, 
opts...)
+       if err != nil {
+               return nil, err
+       }
+       return out, nil
+}
+
+// EventServiceServer is the server API for EventService service.
+// All implementations must embed UnimplementedEventServiceServer
+// for forward compatibility
+type EventServiceServer interface {
+       Sync(context.Context, *EventList) (*Results, error)
+       mustEmbedUnimplementedEventServiceServer()
+}
+
+// UnimplementedEventServiceServer must be embedded to have forward compatible 
implementations.
+type UnimplementedEventServiceServer struct {
+}
+
+func (UnimplementedEventServiceServer) Sync(context.Context, *EventList) 
(*Results, error) {
+       return nil, status.Errorf(codes.Unimplemented, "method Sync not 
implemented")
+}
+func (UnimplementedEventServiceServer) 
mustEmbedUnimplementedEventServiceServer() {}
+
+// UnsafeEventServiceServer may be embedded to opt out of forward 
compatibility for this service.
+// Use of this interface is not recommended, as added methods to 
EventServiceServer will
+// result in compilation errors.
+type UnsafeEventServiceServer interface {
+       mustEmbedUnimplementedEventServiceServer()
+}
+
+func RegisterEventServiceServer(s grpc.ServiceRegistrar, srv 
EventServiceServer) {
+       s.RegisterService(&EventService_ServiceDesc, srv)
+}
+
+func _EventService_Sync_Handler(srv interface{}, ctx context.Context, dec 
func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, 
error) {
+       in := new(EventList)
+       if err := dec(in); err != nil {
+               return nil, err
+       }
+       if interceptor == nil {
+               return srv.(EventServiceServer).Sync(ctx, in)
+       }
+       info := &grpc.UnaryServerInfo{
+               Server:     srv,
+               FullMethod: "/api.sync.v1.EventService/Sync",
+       }
+       handler := func(ctx context.Context, req interface{}) (interface{}, 
error) {
+               return srv.(EventServiceServer).Sync(ctx, req.(*EventList))
+       }
+       return interceptor(ctx, in, info, handler)
+}
+
+// EventService_ServiceDesc is the grpc.ServiceDesc for EventService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var EventService_ServiceDesc = grpc.ServiceDesc{
+       ServiceName: "api.sync.v1.EventService",
+       HandlerType: (*EventServiceServer)(nil),
+       Methods: []grpc.MethodDesc{
+               {
+                       MethodName: "Sync",
+                       Handler:    _EventService_Sync_Handler,
+               },
+       },
+       Streams:  []grpc.StreamDesc{},
+       Metadata: "event_service.proto",
+}
diff --git a/client/set.go b/client/set.go
new file mode 100644
index 0000000..1797f04
--- /dev/null
+++ b/client/set.go
@@ -0,0 +1,31 @@
+package client
+
+import (
+       "fmt"
+
+       v1sync "github.com/apache/servicecomb-service-center/api/sync/v1"
+       "github.com/apache/servicecomb-service-center/pkg/log"
+       "google.golang.org/grpc"
+)
+
+// SetConfig is client configs
+type SetConfig struct {
+       Addr string
+}
+
+// Set is set of grpc clients
+type Set struct {
+       EventServiceClient v1sync.EventServiceClient
+}
+
+// NewSetForConfig dial grpc connection and create all grpc clients
+func NewSetForConfig(c SetConfig) (*Set, error) {
+       conn, err := grpc.Dial(c.Addr, grpc.WithInsecure())
+       if err != nil {
+               log.Error(fmt.Sprintf("can not connect: %s", err), nil)
+               return nil, err
+       }
+       return &Set{
+               EventServiceClient: v1sync.NewEventServiceClient(conn),
+       }, nil
+}
diff --git a/client/set_test.go b/client/set_test.go
new file mode 100644
index 0000000..6986695
--- /dev/null
+++ b/client/set_test.go
@@ -0,0 +1,21 @@
+package client_test
+
+import (
+       "context"
+       "testing"
+
+       v1sync "github.com/apache/servicecomb-service-center/api/sync/v1"
+       "github.com/apache/servicecomb-service-center/client"
+       "github.com/stretchr/testify/assert"
+)
+
+func TestNewSetForConfig(t *testing.T) {
+       cs, err := client.NewSetForConfig(client.SetConfig{
+               Addr: "127.0.0.1:30105",
+       })
+       assert.NoError(t, err)
+       _, err = cs.EventServiceClient.Sync(context.TODO(), 
&v1sync.EventList{Events: []*v1sync.Event{
+               {Action: "create"},
+       }})
+       assert.NoError(t, err)
+}
diff --git a/etc/conf/app.yaml b/etc/conf/app.yaml
index 8dc992d..333086f 100644
--- a/etc/conf/app.yaml
+++ b/etc/conf/app.yaml
@@ -16,6 +16,22 @@
 # environment can specify the sc running env, like dev or prod
 environment: dev
 
+sync:
+  datacenter:
+    name: dc1
+  peers:
+    - name: dc2
+      kind: servicecomb
+      endpoints: ["https://127.0.0.1:30100";]
+      # only allow mode implemented in incremental approach like push, 
watch(such as pub/sub, long polling)
+      mode: [push]
+      caFile: certs/ca.crt
+      revision: 100
+    - name: dc3
+      kind: consul
+      # since consul will not push data to servcecomb, if we need set push and 
watch mode to achieve two direction sync
+      mode: [push, watch]
+      revison: 200
 server:
   host: 127.0.0.1
   port: 30100
@@ -210,6 +226,7 @@ uuid:
 auth:
   kind:
 
+
 auditlog:
   kind:
 
diff --git a/etc/conf/chassis.yaml b/etc/conf/chassis.yaml
new file mode 100755
index 0000000..13b325c
--- /dev/null
+++ b/etc/conf/chassis.yaml
@@ -0,0 +1,20 @@
+---
+servicecomb:
+  registry:
+    disabled: true
+  protocols:
+    grpc:
+      listenAddress: 127.0.0.1:30105
+  handler:
+    chain:
+      Provider:
+        default: access-log,ratelimiter-provider,monitoring
+# ssl:
+#   Provider.cipherPlugin: default
+#   Provider.verifyPeer: false
+#   Provider.cipherSuits: 
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
+#   Provider.protocol: TLSv1.2
+#   Provider.caFile:
+#   Provider.certFile:
+#   Provider.keyFile:
+#   Provider.certPwdFile:
\ No newline at end of file
diff --git a/etc/conf/microservice.yaml b/etc/conf/microservice.yaml
new file mode 100755
index 0000000..224fde3
--- /dev/null
+++ b/etc/conf/microservice.yaml
@@ -0,0 +1,4 @@
+servicecomb:
+  service:
+    name: servicecomb-service-center
+    version: 2.0.0
\ No newline at end of file
diff --git a/examples/service_center/body/add_sync_whitelist.json 
b/examples/service_center/body/add_sync_whitelist.json
new file mode 100644
index 0000000..dd3e3f6
--- /dev/null
+++ b/examples/service_center/body/add_sync_whitelist.json
@@ -0,0 +1,21 @@
+{
+  "sync_white_list": [
+    {
+      "resources": [
+        {
+          "type": "service"
+        }
+      ]
+    },
+    {
+      "resources": [
+        {
+          "type": "service",
+          "labels": {
+            "serviceName": "order-service"
+          }
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/go.mod b/go.mod
index cc958db..4fd4ef3 100644
--- a/go.mod
+++ b/go.mod
@@ -1,9 +1,13 @@
 module github.com/apache/servicecomb-service-center
 
-replace github.com/apache/thrift => github.com/apache/thrift 
v0.0.0-20180125231006-3d556248a8b9
+replace (
+       github.com/apache/servicecomb-service-center/api => ./api
+       github.com/apache/thrift => github.com/apache/thrift 
v0.0.0-20180125231006-3d556248a8b9
+)
 
 require (
        github.com/NYTimes/gziphandler v1.1.1
+       github.com/apache/servicecomb-service-center/api v0.0.0
        github.com/astaxie/beego v1.12.2
        github.com/cheggaaa/pb v1.0.25
        github.com/deckarep/golang-set v1.7.1
@@ -12,6 +16,7 @@ require (
        github.com/go-chassis/cari v0.5.1-0.20210823023004-74041d1363c4
        github.com/go-chassis/foundation v0.3.1-0.20210811025651-7f4d2b2b906c
        github.com/go-chassis/go-archaius v1.5.1
+       github.com/go-chassis/go-chassis-extension/protocol/grpc 
v0.0.0-20210902082902-eb5df922afcd // indirect
        github.com/go-chassis/go-chassis/v2 v2.3.0
        github.com/go-chassis/kie-client v0.1.1-0.20210926011742-97eed4281056
        github.com/go-chassis/openlog v1.1.3
@@ -50,8 +55,8 @@ require (
        go.uber.org/zap v1.17.0
        golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b
        golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
-       google.golang.org/grpc v1.38.0
-       google.golang.org/protobuf v1.26.0
+       google.golang.org/grpc v1.40.0
+       google.golang.org/protobuf v1.27.1
        gopkg.in/natefinch/lumberjack.v2 v2.0.0
        gopkg.in/yaml.v2 v2.4.0
        k8s.io/api v0.19.5
diff --git a/go.sum b/go.sum
index 430ec10..a49311b 100644
--- a/go.sum
+++ b/go.sum
@@ -147,6 +147,7 @@ github.com/cloudflare/golz4 
v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod 
h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 
h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod 
h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod 
h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod 
h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
 github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 
h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E=
 github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod 
h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
@@ -233,6 +234,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod 
h1:6rpuAdCZL397s3pYoYcLgu1m
 github.com/envoyproxy/go-control-plane 
v0.9.9-0.20201210154907-fd9021fe5dad/go.mod 
h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
 github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d 
h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00=
 github.com/envoyproxy/go-control-plane 
v0.9.9-0.20210217033140-668b12f5399d/go.mod 
h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane 
v0.9.9-0.20210512163311-63b5d3c536b0/go.mod 
h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
 github.com/envoyproxy/protoc-gen-validate v0.1.0 
h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod 
h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/evanphx/json-patch v4.2.0+incompatible/go.mod 
h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
@@ -273,6 +275,8 @@ github.com/go-chassis/foundation 
v0.3.1-0.20210811025651-7f4d2b2b906c h1:6ooUyys
 github.com/go-chassis/foundation v0.3.1-0.20210811025651-7f4d2b2b906c/go.mod 
h1:6NsIUaHghTFRGfCBcZN011zl196F6OR5QvD9N+P4oWU=
 github.com/go-chassis/go-archaius v1.5.1 
h1:1FrNyzzmD6o6BIjPF8uQ4Cc+u7qYIgQTpDk8uopBqfo=
 github.com/go-chassis/go-archaius v1.5.1/go.mod 
h1:QPwvvtBxvwiC48rmydoAqxopqOr93RCQ6syWsIkXPXQ=
+github.com/go-chassis/go-chassis-extension/protocol/grpc 
v0.0.0-20210902082902-eb5df922afcd 
h1:RqGW+mW6U0+3QkvGXiDZfMwRb8PwW8bb1rI9tlm/jzo=
+github.com/go-chassis/go-chassis-extension/protocol/grpc 
v0.0.0-20210902082902-eb5df922afcd/go.mod 
h1:btid7R4NKuET4BCUkR74CL5EP0hk3J0jXSByjzwd9JM=
 github.com/go-chassis/go-chassis/v2 v2.3.0 
h1:qqFeRhox9Ov0GMfkFnr/ZBkhjhyGHy+SrMyDNbXl8co=
 github.com/go-chassis/go-chassis/v2 v2.3.0/go.mod 
h1:iyJ2DWSkqfnCmad/0Il9nXWHaob7RcwPGlIDRNxccH0=
 github.com/go-chassis/go-restful-swagger20 v1.0.3 
h1:kWfeLwMwJZVkXP1zNyFpkmR41UZ55UTcOptTteXhvEs=
@@ -1261,6 +1265,8 @@ google.golang.org/grpc v1.36.0/go.mod 
h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
 google.golang.org/grpc v1.37.0/go.mod 
h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
 google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
 google.golang.org/grpc v1.38.0/go.mod 
h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
+google.golang.org/grpc v1.40.0/go.mod 
h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod 
h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod 
h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod 
h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -1274,6 +1280,8 @@ google.golang.org/protobuf v1.25.0/go.mod 
h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod 
h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0 
h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
 google.golang.org/protobuf v1.26.0/go.mod 
h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.27.1 
h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
+google.golang.org/protobuf v1.27.1/go.mod 
h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6 
h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod 
h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod 
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
diff --git a/pkg/util/net_test.go b/pkg/util/net_test.go
index 361bf6c..59e9392 100644
--- a/pkg/util/net_test.go
+++ b/pkg/util/net_test.go
@@ -17,9 +17,10 @@
 package util
 
 import (
-       "github.com/stretchr/testify/assert"
        "net/http"
        "testing"
+
+       "github.com/stretchr/testify/assert"
 )
 
 const (
diff --git a/server/api.go b/server/api_server.go
similarity index 100%
rename from server/api.go
rename to server/api_server.go
diff --git a/server/core/core.go b/server/core/core.go
index d3f006d..42e6c04 100644
--- a/server/core/core.go
+++ b/server/core/core.go
@@ -20,6 +20,11 @@ package core
 import (
        "os"
 
+       "github.com/go-chassis/go-chassis/v2"
+
+       //grpc plugin
+       _ "github.com/go-chassis/go-chassis-extension/protocol/grpc/server"
+
        // import the grace package and parse grace cmd line
        _ "github.com/apache/servicecomb-service-center/pkg/grace"
 
@@ -29,6 +34,9 @@ import (
 )
 
 func Initialize() {
+       if err := chassis.Init(); err != nil {
+               log.Warn(err.Error())
+       }
        // initialize configuration
        config.Init()
        // Logging
diff --git a/server/rpc/sync/server.go b/server/rpc/sync/server.go
new file mode 100644
index 0000000..8dd0d43
--- /dev/null
+++ b/server/rpc/sync/server.go
@@ -0,0 +1,18 @@
+package sync
+
+import (
+       "context"
+       "fmt"
+
+       v1sync "github.com/apache/servicecomb-service-center/api/sync/v1"
+       "github.com/apache/servicecomb-service-center/pkg/log"
+)
+
+type Server struct {
+       v1sync.UnimplementedEventServiceServer
+}
+
+func (s *Server) Sync(ctx context.Context, events *v1sync.EventList) 
(*v1sync.Results, error) {
+       log.Info(fmt.Sprintf("Received: %v", events.Events[0].Action))
+       return &v1sync.Results{}, nil
+}
diff --git a/server/server.go b/server/server.go
index 4e4dfc3..6608dd8 100644
--- a/server/server.go
+++ b/server/server.go
@@ -26,6 +26,7 @@ import (
        "strings"
        "time"
 
+       syncv1 "github.com/apache/servicecomb-service-center/api/sync/v1"
        "github.com/apache/servicecomb-service-center/datasource"
        nf "github.com/apache/servicecomb-service-center/pkg/event"
        "github.com/apache/servicecomb-service-center/pkg/log"
@@ -39,10 +40,13 @@ import (
        "github.com/apache/servicecomb-service-center/server/event"
        "github.com/apache/servicecomb-service-center/server/metrics"
        
"github.com/apache/servicecomb-service-center/server/plugin/security/tlsconf"
+       "github.com/apache/servicecomb-service-center/server/rpc/sync"
        "github.com/apache/servicecomb-service-center/server/service/gov"
        "github.com/apache/servicecomb-service-center/server/service/rbac"
        snf "github.com/apache/servicecomb-service-center/server/syncernotify"
        "github.com/go-chassis/foundation/gopool"
+       "github.com/go-chassis/go-chassis/v2"
+       chassisServer "github.com/go-chassis/go-chassis/v2/core/server"
        "github.com/little-cui/etcdadpt"
 )
 
@@ -56,7 +60,6 @@ func Run() {
        if err := command.ParseConfig(os.Args); err != nil {
                log.Fatal(err.Error(), err)
        }
-
        server.Run()
 }
 
@@ -77,6 +80,15 @@ func (s *ServiceCenterServer) Run() {
 
        s.startServices()
 
+       chassis.RegisterSchema("grpc", &sync.Server{},
+               
chassisServer.WithRPCServiceDesc(&syncv1.EventService_ServiceDesc))
+
+       go func() {
+               if err := chassis.Run(); err != nil {
+                       log.Warn(err.Error())
+               }
+       }()
+
        signal.RegisterListener()
 
        s.waitForQuit()
diff --git a/test/test.go b/test/test.go
index 6caee42..d5d651e 100644
--- a/test/test.go
+++ b/test/test.go
@@ -19,9 +19,16 @@
 package test
 
 import (
+       "io"
+       "os"
+       "path/filepath"
+
+       "github.com/apache/servicecomb-service-center/pkg/util"
        _ "github.com/apache/servicecomb-service-center/server/init"
 
        _ "github.com/apache/servicecomb-service-center/server/bootstrap"
+       //grpc plugin
+       _ "github.com/go-chassis/go-chassis-extension/protocol/grpc/server"
 
        "github.com/apache/servicecomb-service-center/datasource"
        "github.com/apache/servicecomb-service-center/server/core"
@@ -51,7 +58,32 @@ func init() {
 
        core.ServiceAPI = disco.AssembleResources()
 }
+func createChassisConfig() {
+       b := []byte(`
+servicecomb:
+  registry:
+    disabled: true
+  protocols:
+    grpc:
+      listenAddress: 127.0.0.1:30105
+`)
+       dir := filepath.Join(util.GetAppRoot(), "conf")
+       os.Mkdir(dir, 0700)
+       file := filepath.Join(dir, "chassis.yaml")
+       f1, _ := os.Create(file)
+       _, _ = io.WriteString(f1, string(b))
 
+       b2 := []byte(`
+servicecomb:
+  service:
+    name: service-center
+    app: servicecomb
+    version: 2.0.0
+`)
+       file2 := filepath.Join(dir, "chassis.yaml")
+       f2, _ := os.Create(file2)
+       _, _ = io.WriteString(f2, string(b2))
+}
 func IsETCD() bool {
        t := archaius.Get("TEST_MODE")
        if t == nil {

Reply via email to