異構微服務數據無損通信:Apache ServiceComb syncer完整示例實踐

Apache ServiceComb ServiceCenter 1.3.0版本已於2019年11月07日發佈,在這次版本中帶來了異構、多服務中心同步工具 Syncer,在這裏將從我們的已有的實踐經驗出發,帶來對Syncer的介紹。
項目地址:https://github.com/apache/servicecomb-service-center/tree/master/syncer
1.3.0版本下載:http://servicecomb.apache.org/release/service-center-downloads/

 

爲什麼使用服務中心同步工具


從傳統架構到微服務,爲了解決微服務之間動態變更帶來的問題,各微服務框架百花齊放,從而衍生出Service-center、eureka、consul等一系列服務中心;在雲環境大行其道的今天,公/私有云並存、混合雲部署在企業實踐中似乎已成爲趨勢。在這過程中不得不面臨一些問題:

  • 異構服務中心間的實例如何發現?
  • 跨區域間的實例信息怎麼同步?
  • 統一企業內部微服務架構過程中,如何平滑遷移?

 

中心化解決方案帶來的思考


在最初的項目中,我們應用了ServiceCenter的中心化解決方案 ServiceCenter Aggregate,詳細介紹請參考:https://github.com/apache/servicecomb-service-center/blob/master/docs/multidcs.md
在使用這樣的中心化解決方案後,異構服務中心的實例被同步到 Aggregate 中,服務只需指定服務發現地址到 Aggregate,即可實現對異構、跨區域實例的發現,同時也支持了微服務架構之間的平滑遷移。
經過一段時間的使用,集中式、中心化方案的不足逐漸顯現,於是便有了如下的思考:

  • 對業務服務不透明,需要修改服務發現地址
  • 設計理念傾向於對自身服務中心的遷入,對異構服務中心並存支持不夠友好
  • 中心化的架構,單點故障會造成同步的暫停,影響依賴服務的正常運行
  • 同步、數據結構轉換的工作集中在單個服務中,容易造成性能瓶頸
  • 增加新的服務中心支持時,需要重新編譯、啓動同步服務
  • 維護成本增加,運維人員配置規則時需要理解所有服務中心的信息

 

Apache ServiceComb Syncer


針對以上的問題與思考,我們帶來了無中心化的解決方案 Apche ServiceComb Syncer。Syncer是一個多服務中心的同步工具,專爲大型微服務架構設計,用於在網絡互通的情況下,不同技術棧服務中心、跨區域的實例同步,未來將對跨網絡、跨雲等場景提供支持。

 

Syncer的架構設計

 


Syncer以服務中心的伴生系統的形式而存在,主要負責從當前服務中心發現實例,並向網絡其他成員進行廣播;接收其他成員的廣播,並拉取實例信息向當前服務中心進行註冊。Syncer 有如下特點:

  • 業務架構零侵入,Syncer 以透明的形式爲服務中心同步實例信息,不參與原業務流程,服務無需感知其存在。
  • 不綁定服務中心,兼容生態,支持不同技術棧服務中心的接入。
  • 基於Serf(gossip 協議的實現)構建無中心的對等網絡,成員的自由加入與退出,對 Syncer 網絡、服務中心均無影響。
  • 以統一的數據結構在網絡中進行傳遞,數據結構的轉換被分散到各個 Syncer 中,其只需要處理當前服務中心數據結構與 SyncData 之間的轉換,即可做到數據的最大兼容。
  • 以 golang 插件的形式對服務中心提供支持,用戶可自由的擴展需要接入的服務中心。新的服務中心加入,只需在其伴生的 Syncer 進行向 SyncerData 的轉換,數據即可在 Syncer 網絡中進行同步,無需其他成員配合。
  • 服務的配置、部署、升級、維護等仍在單服務中心內完成,沒有額外的業務維護成本增加。

下面我們通過具體的業務流程來進一步瞭解 Syncer。

 

組網流程

上圖左側綠色 SyncerN 是一個待加入網絡的成員。

  1. SyncerN 在啓動之後,通過向 JoinAddr 所指向的 SyncerB 發起 Join 請求
  2. 通過 serf 的自動發現與廣播機制,一段時間後,SyncerN 的信息會傳播到網絡中所有成員處,組網成功
  3. 若 Syncer 是以 cluster 模式啓動的,Syncer 通過標記的 cluster tag 將相同的 cluster 歸爲一組,從而實現內部的高可用集羣


數據同步流程


Syncer的同步流程同步流程並不複雜,下圖具體描述了兩個Syncer將不同服務中心的實例進行同步的過程。


適用場景

 

  • 網絡互通的異構、多服務中心實例信息同步,支持異構服務中的並存、多服務中心實例共享


上圖左,兩套服務中心(ServiceCenter 和 Eureka)各自爲政,各自轄區的服務無法跨越架構邊界,無法發現對方服務實例,從而無法進行通訊。上圖右,兩套服務中心的實例將通過 Syncer 同步,在兩個服務中心裏,最後都將呈現出所有的實例,服務之間無障礙發現,從而實現實例的共享通訊。

  • 支持異構服務中心實例任意方向的平滑改造遷移


Syncer統一了同步數據結構 SyncData,並以插件的形式提供對各服務中心的支持,各服務中心只需實現實例數據與 SyncData 的轉換,即可完成異構服務中心數據的轉換。從而在架構遷移的過程中,可以使用 syncer 實現系統的逐步遷移,平穩過渡。

  • 多微服務技術棧並存時,微服務依據自身訴求自由選型


在企業的發展道路中,經常會出現由於某個核心服務使用了某個技術棧,導致與其對接的服務只能遷就,從而放棄更適合的選型。Syncer 支持異構同步的特性,

可以有效衝破這個限制,使業務選型遵從業務本身訴求。


下面我們將通過一個異構服務中心同步的示例,從實踐出發進一步瞭解 Syncer。

 

ServiceComb-ServiceCenter 與 SpringCloud Eureka 實例互通實踐


示例代碼:https://github.com/apache/servicecomb-service-center/blob/master/syncer/samples/multi-servicecenters
本案例模擬了異構服務中心之間的通訊場景,包括以下四個部分:

  • EurekaServer: Eureka服務中心
  • AccountServer:註冊到Eureka的賬號服務
  • Servicecomb-ServiceCenter:Servicecomb-ServiceCenter服務中心
  • HelloServer:註冊到Servicecomb-ServiceCenter,需要使用AccountServer的服務

 

運行環境

 

  1. 2臺linux機器: (假設爲:10.0.0.10 和 10.0.0.11)
  2. JDK 1.8
  3. Maven 3.x
  4. Go 1.11.4
  5. ServiceComb Service-Center 1.3.0

運行前的準備(兩臺機器都需運行)
下載並解壓 ServiceCenter 1.3.0 版本包

$ project_dir=`pwd`
$ wget -O http://us.mirrors.quenda.co/apache/servicecomb/servicecomb-service-center/1.3.0/apache-servicecomb-service-center-1.3.0-linux-amd64.tar.gz
$ tar -zxvf  apache-servicecomb-service-center-1.3.0-linux-amd64.tar.gz

下載樣例源碼

git clone https://github.com/apache/servicecomb-service-center.git
cd ${project_dir}/servicecomb-service-center/syncer

 

步驟1:啓動Eureka環境和服務


機器: 10.0.0.10

1. 編譯項目

# 編譯 EurekaServer 和 AccountServer
$ cd samples/multi-servicecenters/eureka
$ mvn clean install

2. 啓動EurekaServer:
修改啓動配置
文件位置:${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/eureka/eureka-server/src/main/resources/application.yaml

spring:
  application:
    name: eureka-server
server:
  port : 8761
#  servlet:
#    context-path: /eureka
eureka:
  instance:
    hostname : 10.0.0.10
  client:
    registerWithEureka : false
    fetchRegistry : false
    serviceUrl:
      defaultZone : http://${eureka.instance.hostname}:${server.port}/eureka/
management:
  endpoints:
    web:
      exposure:
        include: "*"

啓動服務

# 啓動 EurekaServer
$ cd ${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/eureka/eureka-server/
$ nohup mvn spring-boot:run & >> eureka-server.log 2>&1 &

瀏覽器打開http://10.0.0.10:8761 ,若出現如下頁面,則啓動成功

 

3. 啓動AccountServer

 

  • 修改啓動配置

文件位置:${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/eureka/account-server/src/main/resources/application.yaml

spring:
  application:
    name: account-server
server:
  port: 8090
eureka:
  instance:
    hostname: 10.0.0.10
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:8761/eureka/
management:
  endpoints:
    web:
      exposure:
        include: "*"
  • 啓動服務
# 啓動 AccountServer
$ cd ${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/eureka/account-server
$ mvn spring-boot:run#啓動 AccountServer
$ cd ${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/eureka/account-server
$ mvn spring-boot:run
# 出現如下字樣則爲成功
2019-09-19 17:20:35.534  INFO 20890 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8090 (http) with context path ''
2019-09-19 17:20:35.548  INFO 20890 --- [           main] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8090
2019-09-19 17:20:35.551  INFO 20890 --- [           main] o.a.s.s.account.AccountApplication       : Started AccountApplication in 3.92 seconds (JVM running for 6.754)
2019-09-19 17:20:35.617  INFO 20890 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_ACCOUNT-SERVER/10.0.0.10:account-server:8090 - registration status: 2042019-09-19 17:20:35.534  INFO 20890 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8090 (http) with context path ''
2019-09-19 17:20:35.548  INFO 20890 --- [           main] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8090
2019-09-19 17:20:35.551  INFO 20890 --- [           main] o.a.s.s.account.AccountApplication       : Started AccountApplication in 3.92 seconds (JVM running for 6.754)
2019-09-19 17:20:35.617  INFO 20890 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_ACCOUNT-SERVER/10.0.0.10:account-server:8090 - registration status: 204

此時打開http://10.0.0.10:8761 ,可以看到AccountServer已經註冊成功

 

4. 啓動Syncer

 

$ cd ${project_dir}/apache-servicecomb-service-center-1.3.0-linux-amd64/
$ ./syncer daemon --sc-addr http://10.0.0.10:8761/eureka --bind-addr 10.0.0.10:30190 --rpc-addr 10.0.0.10:30191 --sc-plugin=eureka
# 出現如下字樣則爲成功
2019-09-19T17:28:28.809+0800  INFO  etcd/agent.go:55  start etcd success
2019-09-19T17:28:28.809+0800  INFO  grpc/server.go:94 start grpc success
2019-09-19T17:28:28.809+0800  DEBUG server/handler.go:39  is leader: true
2019-09-19T17:28:28.809+0800  DEBUG server/handler.go:43  Handle Tick

 

步驟2:啓動Servicecenter環境和服務


機器: 10.0.0.111.

1. 編譯項目

# 編譯 HelloServer

$ cd samples/multi-servicecenters/servicecenter/hello-server/
$ GO111MODULE=on go build

2. 啓動Servicecenter

  • 修改啓動配置:

文件位置:${project_dir}/apache-servicecomb-service-center-1.3.0-linux-amd64/conf/app.conf

frontend_host_ip = 10.0.0.11
frontend_host_port = 30103

###################################################################
# sever options
###################################################################
# if you want to listen at ipv6 address, then set the httpaddr value like:
# httpaddr = 2400:A480:AAAA:200::159        (global scope)
# httpaddr = fe80::f816:3eff:fe17:c38b%eth0 (link-local scope)
httpaddr = 10.0.0.11
httpport = 30100
# ...以下省略...
  • 啓動 ServiceCenter 和 Frontend
$ cd ${project_dir}/apache-servicecomb-service-center-1.3.0-linux-amd64/
# 啓動 ServiceCenter
$ ./start-service-center.sh
# 啓動 前端頁面 Frontend
$ ./start-frontend.sh

瀏覽器打開http://10.0.0.11:30103 ,若出現如下頁面,則啓動成功

3. 啓動HelloServer

 

  • 修改啓動配置:

文件位置:${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/servicecenter/hello-server/conf/microservice.yaml

service: # 微服務配置
  appId: eureka # eureka 中同步的實例appID均爲:eureka
  name: hello-server
  version: 0.0.1
  instance: # 實例信息
    protocol: rest
    listenAddress: 10.0.0.11:8091 #實例監聽地址
provider: # 服務端信息
  appId: eureka
  name: account-server
  version: 0.0.1
registry:
  address: http://10.0.0.11:30100

 

  • 啓動服務
# 啓動 HelloServer
$ cd ${project_dir}/servicecomb-service-center/syncer/samples/multi-servicecenters/servicecenter/hello-server
$ ./hello-server
# 出現如下字樣則爲成功
2019-09-19T18:37:50.645+0800  DEBUG servicecenter/servicecenter.go:163  send heartbeat success
2019-09-19T18:37:50.645+0800  WARN  servicecenter/servicecenter.go:85 discovery provider failed, appID = eureka, name = account-server, version = 0.0.1
2019-09-19T18:37:50.645+0800  INFO  servicecenter/servicecenter.go:87 waiting for retry

此時打開http://10.0.0.11:30103 ,可以看到HelloServer已經註冊成功

但由於無法發現屬於Eureka服務中心的AccountServer實例,HelloServer處於重試狀態


(注:重試次數爲3次,每次間隔30秒,所以我們需要在90秒內完成後面的操作)

 

4. 啓動Syncer

$ cd ${project_dir}/apache-servicecomb-service-center-1.3.0-linux-amd64/
$ ./syncer daemon --sc-addr http://10.0.0.11:30100 --bind-addr 10.0.0.11:30190 --rpc-addr 10.0.0.11:30191 --sc-plugin=servicecenter --join-addr 10.0.0.10:30190

 

# 出現以下內容則爲Syncer成功啓動,並同步了對方的實例
2019-09-19T18:44:35.536+0800  DEBUG server/handler.go:62  is leader: true
2019-09-19T18:44:35.536+0800  DEBUG server/handler.go:79  Receive serf user event
2019-09-19T18:44:35.536+0800  DEBUG serf/agent.go:130 member = xxxxxa, groupName = 0204d59328090c2f4449a088d4e0f1d8
2019-09-19T18:44:35.536+0800  DEBUG serf/agent.go:130 member = xxxxxb, groupName = 34f53a9520a11c01f02f58f733e856b3
2019-09-19T18:44:35.536+0800  DEBUG server/handler.go:97  Going to pull data from xxxxxb 10.0.0.10:30191
2019-09-19T18:44:35.536+0800  INFO  grpc/client.go:76 Create new grpc connection to 10.0.0.10:30191
2019-09-19T18:44:35.538+0800  DEBUG servicecenter/servicecenter.go:87 create service success orgServiceID= account-server, curServiceID = 80784229255ec96d90353e3c041bdf3586fdbbae
2019-09-19T18:44:35.538+0800  DEBUG servicecenter/servicecenter.go:90 trying to do registration of instance, instanceID = 10.0.0.10:account-server:8090
2019-09-19T18:44:35.540+0800  DEBUG servicecenter/sync.go:63  Registered instance successful, instanceID = 78bca3e2daca11e99638fa163eca30e0


步驟3:結果驗證

1.此時的HelloServer獲取實例成功,並調用了AccountServer的CheckHealth接口

2.分別打開Euraka和ServiceCenter的網頁,兩個服務中心裏均包含了所有的實例信息

3.curl命令調用HelloServer的Login接口

$ curl -X POST \
http://10.0.0.11:8091/login \
-H 'Content-Type: application/json' \
-d '{
  "user":"Jack",
  "password":"123456"
}'
welcome Jack


HelloServer與AccountServer分別會打印如下的信息

AccountServer :


HelloServer:

 

未來展望


ServiceComb Syncer在異構層面,目前已支持ServiceCenter、Eureka兩個服務中心,在後面的工作中將對接更多的生態,將增加對跨網絡的場景的支持。

以上就是今天對Syncer的介紹,後面會持續對Syncer的新特性進行分享,同時也歡迎感興趣的小夥伴加入我們,一起做些有意思的事情。

發佈了184 篇原創文章 · 獲贊 15 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章