基于Docker + Consul + Nginx + Consul-Template的服務負載均衡實現

前言

上一篇文章使用 ConsulRegistratordocker 的容器環境中搭建了服務注冊和發現集群。在服務發現和注冊的基礎上,本文將引入 Nginx反向代理服務器和 Consul-template 組件,實現動態的服務負載均衡


正文

1. 工具介紹

1.1. Nginx

一個高性能的 HTTP反向代理服務器,用于前端訪問流量到后臺應用服務器負載均衡請求轉發

1.2. Consul-template

Consul-templateHashiCorp 基于 Consul 所提供的可擴展的工具,通過監聽 Consul 中的數據變化,動態地修改一些配置文件中地模板。常用于在 NginxHAProxy 上動態配置健康狀態下的客戶端反向代理信息。

2. 實現原理

  • 通過 Nginx 自身實現負載均衡請求轉發
  • 通過 Consul-templateconfig 功能實時監控 Consul 集群節點的服務數據的變化;
  • 實時的用 Consul 節點的信息替換 Nginx 配置文件的模板,并重新加載配置文件;

Consul-templatenginx 必須安裝在同一臺機器上,因為 Consul-template 需要動態修改 nginx 的配置文件 nginx.conf,然后執行 nginx -s reload 命令進行路由更新,達到動態負載均衡的目的。

2.1. 傳統負載均衡

傳統的負載均衡,就是 Client 支姐訪問 Nginx,然后被轉發到后端某一臺 Web Server。如果后端有添加/刪除 Web Server,運維需要手動改下 nginx.conf ,然后重新載入配置,就可以動態的調整負載均衡。

image

2.2. 自動負載均衡

再看看基于服務自動發現和注冊的負載均衡,負載均衡的方式沒有變,只是多了一些外圍組件,當然這些組件對 Client 是不可見的,client 依然只能看到 Nginx 入口,訪問方式也沒變化。

image

Nginx 的動態負載均衡實現流程如下:

  1. 以相同的 Consul 標簽Web Server 進行服務標記分類新增或者刪除 Web Server 服務器節點;
  2. Registrator 監控Web Server 的狀態更新,自動在 Consul服務注冊中心將它注冊或者注銷
  3. Consul-template 訂閱了 Consul 服務注冊中心的服務消息,接收到 Consul 的消息推送,即 Web Server 服務節點狀態發生改變。
  4. Consul-template 自動去修改和替換 Nginx 服務器下的 nginx配置文件中的模板,并重新加載服務達到自動負載均衡的目的。

3. 環境準備

3.1. 系統環境

軟件 版本
操作系統 Ubuntu:16.04 x86_64,內核:4.8.0-58-generic
docker Docker version 1.12.6, build 78d1802
docker-compose docker-compose version 1.8.0

3.2. 節點規劃

主機IP 組件
192.168.1.181 Consul Server, Registrator, Nginx, Consul-template
192.168.1.186 Consul Server, Registrator, Nginx, Consul-template
192.168.1.182 Consul Client, Registrator, Client WebApp1, Server WebApp1, Server WebApp2
192.168.1.183 Consul Client, Registrator, Client WebApp2, Server WebApp3, Server WebApp4
192.168.1.185 Consul Client, Registrator, Client WebApp3, Server WebApp5, Server WebApp6
  • Client WebApp:提供基于ThriftRPC客戶端和基于Http協議的RESTful客戶端,用于訪問 Server 程序。
  • Server WebApp:提供基于ThriftRPC服務端和基于Http協議的RESTful服務端,供 Client 程序調用。

這里的3臺主機 - 192.168.1.182192.168.1.183192.168.1.185,每臺主機部署兩個 Client WebApp 容器和一個 Client Server 容器,用于模擬服務層的負載均衡。

3.3. 鏡像構建

  • Consul:consul:latest
  • Registrator:gliderlabs/registrator:latest
  • NginxConsul-template:liberalman/nginx-consul-template:latest
  • Client WebApp:test-client:latest
  • Server WebApp:test-server:latest

這里先說說 test-clienttest-server 的鏡像構建:

  1. 克隆項目到本地項目環境: https://github.com/ostenant/spring-cloud-starter-thrift
  2. 切換到子模塊 spring-cloud-starter-thrift-examples 下的 test 目錄,執行命令 mvn clean package 進行程序打包。
  3. 分別將 test-clienttest-server 項目根目錄下的 Dockerfile 文件和target目錄下的 target/*.jar程序拷貝到 192.168.1.182192.168.1.183192.168.1.185 目錄下。
  4. 進入客戶端 Dockerfile 所在目錄,對客戶端程序 test-client 進行鏡像構建,命令如下:docker build . -t test-client:latest
  5. 進入服務端 Dockerfile 所在目錄,對服務端程序 test-server 進行鏡像構建,命令如下:docker build . -t test-server:latest

構建完成后查看本地鏡像庫:

image

3.4. 部署模型

五臺主機,其中 192.168.1.181192.168.1.186 兩臺主機的主要作用如下:

  1. 作為負載均衡轉發器 (這里只是演示,可以通過 KeepAlived 實現 NginxHA),將前端訪問流量經過負載算法一次轉發到后臺 Client WebApp
  2. Server模式啟動 Consul節點,其中一臺作為整個服務發現與注冊集群leader, 用于同步持久化其余三臺 Client 模式的 Consul 節點的數據狀態信息

其余三臺主機 - 192.168.1.182192.168.1.183192.168.1.185,充當的角色如下:

  1. 每臺分別以 Client 模式部署 Consul 節點,用于注冊發現本機 docker 容器暴露的服務,同時和 Consul Serverleader 節點進行服務狀態同步
  2. 分別啟動一個 Client WebApp 容器實例和兩個 Server WebApp 容器實例,將 Client WebApp 的請求根據服務層的負載算法二次轉發Server WebApp 中的任意一臺上完成具體的業務處理。
image

這里有兩次服務轉發操作:

  • 接入層的轉發:兩臺 Nginx 服務器將客戶流量,經由一次轉發至三個 Client WebApp 服務實例中任意一個做處理。
  • 服務層的轉發:三個 Client WebApp服務實例其中之一,根據從服務注冊中心拉取的健康的服務緩存列表,將請求二次轉發至六個 Server WebApp服務實例其中之一做處理。

3.5. 開始搭建

3.5.1. Consul Server主機

(a). 分別編寫 docker-compose.yml,注意 Registrator 需要配置各自的 IP地址。

  • 主機:192.168.1.181

docker-compose.yml

version: '2'
services:
  load_balancer:
    image: liberalman/nginx-consul-template:latest
    hostname: lb
    links:
      - consul_server_master:consul
    ports:
      - "80:80"

  consul_server_master:
    image: consul:latest
    hostname: consul_server_master
    ports:
      - "8300:8300"
      - "8301:8301"
      - "8302:8302"
      - "8400:8400"
      - "8500:8500"
      - "8600:8600"
    command: consul agent -server -bootstrap-expect 1 -advertise 192.168.1.181 -node consul_server_master -data-dir /tmp/data-dir -client 0.0.0.0 -ui

  registrator:
    image: gliderlabs/registrator:latest
    hostname: registrator
    links:
      - consul_server_master:consul
    volumes:
      - "/var/run/docker.sock:/tmp/docker.sock"
    command:  -ip 192.168.1.181 consul://192.168.1.181:8500
  • 主機:192.168.1.186

docker-compose.yml

version: '2'
services:
  load_balancer:
    image: liberalman/nginx-consul-template:latest
    hostname: lb
    links:
      - consul_server_slave:consul
    ports:
      - "80:80"

  consul_server_slave:
    image: consul:latest
    hostname: consul_server_slave
    ports:
      - "8300:8300"
      - "8301:8301"
      - "8302:8302"
      - "8400:8400"
      - "8500:8500"
      - "8600:8600"
    command: consul agent -server -join=192.168.1.181 -advertise 192.168.1.186 -node consul_server_slave -data-dir /tmp/data-dir -client 0.0.0.0 -ui

  registrator:
    image: gliderlabs/registrator:latest
    hostname: registrator
    links:
      - consul_server_slave:consul
    volumes:
      - "/var/run/docker.sock:/tmp/docker.sock"
    command:  -ip 192.168.1.186 consul://192.168.1.186:8500

(b). 在兩臺主機上分別通過 docker-compose 啟動多容器應用,命令如下:

docker-compose up -d

這是在主機 192.168.1.181 上運行啟動命令時的輸出,可以看到 docker-compose 啟動時會先去檢查目標鏡像文件是否拉取到本地,然后依次創建啟動 docker-compose.yml 文件配置的容器實例

image

(c). 查看正常啟動的容器進程,觀察ConsulRegistratorNginx/Consul-template的容器都正常啟動。

image

(d). 利用 docker-compose,以相同的方式在主機 192.168.1.186 上啟動所配置的容器服務實例,查看啟動狀態如下:

image

(e). 訪問 http://IP:8500 查看 Consul Server節點信息服務注冊列表

  • 節點信息:
image
  • 服務狀態列表:
image

兩臺 Consul Server 主機上的容器服務實例均正常啟動!

3.5.2. Consul Client主機

一般情況下,我們把 Consul 作為服務注冊與發現中心,會使用它提供的服務定義 (Service Definition) 和健康檢查定義 (Health Check Definition) 功能,相關配置說明參考如下:

服務定義

環境變量Key 環境變量Value 說明
SERVICE_ID web-001 可以為GUID或者可讀性更強變量,保證不重復
SERVICE_NAME web 如果ID沒有設置,Consul會將name作為id,則有可能注冊失敗
SERVICE_TAGS nodejs,web 服務的標簽,用逗號分隔,開發者可以根據標簽來查詢一些信息
SERVICE_IP 內網IP 要使用Consul,可訪問的IP
SERVICE_PORT 50001 應用的IP, 如果應用監聽了多個端口,理應被視為多個應用
SERVICE_IGNORE Boolean 是否忽略本Container,可以為一些不需要注冊的Container添加此屬性

服健康檢查定義

配置原則為: SERVICE_XXX_*。如果你的應用監聽的是 5000 端口,則改為 SERVICE_5000_CHECK_HTTP,其它環境變量配置同理。

環境變量Key 環境變量Value 說明
--- 以下為HTTP模式 --- ---
SERVICE_80_CHECK_HTTP /path_to_health_check 你的健康狀態檢查的路徑如 /status
SERVICE_80_CHECK_INTERVAL 15s 15秒檢查一次
SERVICE_80_CHECK_TIMEOUT 2s 狀態檢查超時時間
--- 以下為HTTPS模式 --- ---
SERVICE_443_CHECK_HTTPS /path_to_health_check 你的健康狀態檢查的路徑如 /status
SERVICE_443_CHECK_INTERVAL 15s 15秒檢查一次
SERVICE_443_CHECK_TIMEOUT 2s 狀態檢查超時時間
--- 以下為TCP模式 --- ---
SERVICE_443_CHECK_TCP /path_to_health_check 你的健康狀態檢查的路徑如 /status
SERVICE_443_CHECK_INTERVAL 15s 15秒檢查一次
SERVICE_443_CHECK_TIMEOUT 2s 狀態檢查超時時間
--- 使用腳本檢查 --- ---
SERVICE_CHECK_SCRIPT curl --silent --fail example.com 如官方例子中的check_redis.py
--- 其他 --- ---
SERVICE_CHECK_INITIAL_STATUS passing Consul默認注冊后的服務為failed

配置說明

(a). 分別編寫 docker-compose.yml,同樣注意 Registrator 需要配置各自的 IP 地址。test-servertest-client服務實例在配置時需要指定相關的環境變量

  • 主機:192.168.1.182

docker-compose.yml

version: '2'
services:
  consul_client_01:
    image: consul:latest
    ports:
      - "8300:8300"
      - "8301:8301"
      - "8301:8301/udp"
      - "8302:8302"
      - "8302:8302/udp"
      - "8400:8400"
      - "8500:8500"
      - "8600:8600"
    command: consul agent -retry-join 192.168.1.181 -advertise 192.168.1.182 -node consul_client_01 -data-dir /tmp/data-dir -client 0.0.0.0 -ui

  registrator:
    image: gliderlabs/registrator:latest
    volumes:
      - "/var/run/docker.sock:/tmp/docker.sock"
    command:  -ip 192.168.1.182 consul://192.168.1.182:8500

  test_server_1:
    image: test-server:latest
    environment:
      - SERVICE_8080_NAME=test-server-http-service
      - SERVICE_8080_TAGS=test-server-http-service-01
      - SERVICE_8080_CHECK_INTERVAL=10s
      - SERVICE_8080_CHECK_TIMEOUT=2s
      - SERVICE_8080_CHECK_HTTP=/health
      - SERVICE_25000_NAME=test-server-thrift-service
      - SERVICE_25000_TAGS=test-server-thrift-service-01
      - SERVICE_25000_CHECK_INTERVAL=10s
      - SERVICE_25000_CHECK_TIMEOUT=2s
      - SERVICE_25000_CHECK_TCP=/
    ports:
      - "16000:8080"
      - "30000:25000"

  test_server_2:
    image: test-server:latest
    environment:
      - SERVICE_8080_NAME=test-server-http-service
      - SERVICE_8080_TAGS=test-server-http-service-02
      - SERVICE_8080_CHECK_INTERVAL=10s
      - SERVICE_8080_CHECK_TIMEOUT=2s
      - SERVICE_8080_CHECK_HTTP=/health
      - SERVICE_25000_NAME=test-server-thrift-service
      - SERVICE_25000_TAGS=test-server-thrift-service-02
      - SERVICE_25000_CHECK_INTERVAL=10s
      - SERVICE_25000_CHECK_TIMEOUT=2s
      - SERVICE_25000_CHECK_TCP=/
    ports:
      - "18000:8080"
      - "32000:25000"

  test_client_1:
    image: test-client:latest
    environment:
      - SERVICE_8080_NAME=my-web-server
      - SERVICE_8080_TAGS=test-client-http-service-01
      - SERVICE_8080_CHECK_INTERVAL=10s
      - SERVICE_8080_CHECK_TIMEOUT=2s
      - SERVICE_8080_CHECK_HTTP=/features
    ports:
      - "80:8080"
  • 主機:192.168.1.183

docker-compose.yml

version: '2'
services:
  consul_client_02:
    image: consul:latest
    ports:
      - "8300:8300"
      - "8301:8301"
      - "8301:8301/udp"
      - "8302:8302"
      - "8302:8302/udp"
      - "8400:8400"
      - "8500:8500"
      - "8600:8600"
    command: consul agent -retry-join 192.168.1.181 -advertise 192.168.1.183 -node consul_client_02 -data-dir /tmp/data-dir -client 0.0.0.0 -ui

  registrator:
    image: gliderlabs/registrator:latest
    volumes:
      - "/var/run/docker.sock:/tmp/docker.sock"
    command:  -ip 192.168.1.183 consul://192.168.1.183:8500

  test_server_1:
    image: test-server:latest
    environment:
      - SERVICE_8080_NAME=test-server-http-service
      - SERVICE_8080_TAGS=test-server-http-service-03
      - SERVICE_8080_CHECK_INTERVAL=10s
      - SERVICE_8080_CHECK_TIMEOUT=2s
      - SERVICE_8080_CHECK_HTTP=/health
      - SERVICE_25000_NAME=test-server-thrift-service
      - SERVICE_25000_TAGS=test-server-thrift-service-03
      - SERVICE_25000_CHECK_INTERVAL=10s
      - SERVICE_25000_CHECK_TIMEOUT=2s
      - SERVICE_25000_CHECK_TCP=/
    ports:
      - "16000:8080"
      - "30000:25000"

  test_server_2:
    image: test-server:latest
    environment:
      - SERVICE_8080_NAME=test-server-http-service
      - SERVICE_8080_TAGS=test-server-http-service-04
      - SERVICE_8080_CHECK_INTERVAL=10s
      - SERVICE_8080_CHECK_TIMEOUT=2s
      - SERVICE_8080_CHECK_HTTP=/health
      - SERVICE_25000_NAME=test-server-thrift-service
      - SERVICE_25000_TAGS=test-server-thrift-service-04
      - SERVICE_25000_CHECK_INTERVAL=10s
      - SERVICE_25000_CHECK_TIMEOUT=2s
      - SERVICE_25000_CHECK_TCP=/
    ports:
      - "18000:8080"
      - "32000:25000"

  test_client_1:
    image: test-client:latest
    environment:
      - SERVICE_8080_NAME=my-web-server
      - SERVICE_8080_TAGS=test-client-http-service-02
      - SERVICE_8080_CHECK_INTERVAL=10s
      - SERVICE_8080_CHECK_TIMEOUT=2s
      - SERVICE_8080_CHECK_HTTP=/features
    ports:
      - "80:8080"
  • 主機:192.168.1.185

docker-compose.yml

version: '2'
services:
  consul_client_03:
    image: consul:latest
    ports:
      - "8300:8300"
      - "8301:8301"
      - "8301:8301/udp"
      - "8302:8302"
      - "8302:8302/udp"
      - "8400:8400"
      - "8500:8500"
      - "8600:8600"
    command: consul agent -retry-join 192.168.1.181 -advertise 192.168.1.185 -node consul_client_03 -data-dir /tmp/data-dir -client 0.0.0.0 -ui

  registrator:
    image: gliderlabs/registrator:latest
    volumes:
      - "/var/run/docker.sock:/tmp/docker.sock"
    command:  -ip 192.168.1.185 consul://192.168.1.185:8500

  test_server_1:
    image: test-server:latest
    environment:
      - SERVICE_8080_NAME=test-server-http-service
      - SERVICE_8080_TAGS=test-server-http-service-05
      - SERVICE_8080_CHECK_INTERVAL=10s
      - SERVICE_8080_CHECK_TIMEOUT=2s
      - SERVICE_8080_CHECK_HTTP=/health
      - SERVICE_25000_NAME=test-server-thrift-service
      - SERVICE_25000_TAGS=test-server-thrift-service-05
      - SERVICE_25000_CHECK_INTERVAL=10s
      - SERVICE_25000_CHECK_TIMEOUT=2s
      - SERVICE_25000_CHECK_TCP=/
    ports:
      - "16000:8080"
      - "30000:25000"

  test_server_2:
    image: test-server:latest
    environment:
      - SERVICE_8080_NAME=test-server-http-service
      - SERVICE_8080_TAGS=test-server-http-service-06
      - SERVICE_8080_CHECK_INTERVAL=10s
      - SERVICE_8080_CHECK_TIMEOUT=2s
      - SERVICE_8080_CHECK_HTTP=/health
      - SERVICE_25000_NAME=test-server-thrift-service
      - SERVICE_25000_TAGS=test-server-thrift-service-06
      - SERVICE_25000_CHECK_INTERVAL=10s
      - SERVICE_25000_CHECK_TIMEOUT=2s
      - SERVICE_25000_CHECK_TCP=/
    ports:
      - "18000:8080"
      - "32000:25000"

  test_client_1:
    image: test-client:latest
    environment:
      - SERVICE_8080_NAME=my-web-server
      - SERVICE_8080_TAGS=test-client-http-service-03
      - SERVICE_8080_CHECK_INTERVAL=10s
      - SERVICE_8080_CHECK_TIMEOUT=2s
      - SERVICE_8080_CHECK_HTTP=/features
    ports:
      - "80:8080"

注意:我們使用的第三方鏡像 liberalman/nginx-consul-templateNginx 會把名稱為 my-web-server服務容器作為后臺轉發的目標服務器,因此,在 test-client 的配置項中,需要指定 SERVICE_XXX_NAMEmy-web-server。當然你也可以自己制作鏡像指定模板

(b). 在三臺主機上使用 docker-compose 啟動多容器應用:

docker-compose up -d

以主機 192.168.1.182 為例 (其余兩臺類似),控制臺日志顯示,創建并啟動 docker-compose.yml 文件配置的5個容器實例

image

(c). 查看正常啟動的容器進程,觀察到 Consul、一臺test-client 和 兩臺test-server的容器都正常啟動。

image

(d). 在 b 操作中的控制臺輸出可以看到:docker-compose 并非按照 docker-compose.yml 文件中服務配置的先后順序啟動。 registrator 容器的啟動依賴于 consul 容器,而此時 consul 還并未啟動,就出現了 registrator 優先啟動而異常退出的現象。解決方法是再運行一次 docker-compose up -d 命令。

image

(e). 再次查看容器進程,此時 Registrator 容器就已經正常啟動了。

image

(f). 以相同的方式在其余兩臺主機上重復以上操作,再次訪問 http://IP:8500 查看 Consul Server節點信息服務注冊列表

  • Consul 集群節點信息,包括兩臺 Consul Server 節點和一臺 Consul Client 節點,節點右側可以看到所有的服務注冊列表和相關的健康檢查結果

[圖片上傳失敗...(image-af895-1536936846870)]

  • nginx 服務狀態列表,服務名稱 nginx-consul-template,提供 http 服務,共有2個服務實例:
image
  • test-client 服務狀態列表,服務名稱為 my-web-server,提供 http 服務,共有3個服務實例:
image
  • test-server 服務狀態列表,服務名稱為 test-server-http-servicetest-server-thrift-service,分別對應6個 http 服務實例和 6個 thrift 服務實例:
image
image

三臺 Consul Client 主機上的容器服務實例均正常啟動,服務注冊和發現運行正常!

4. 結果驗證

4.1. Nginx負載均衡

4.1.1. 訪問Nginx

Nginx 默認訪問端口號為80,任選一臺 Nginx 訪問,比如: http://192.168.1.181/swagger-ui.html

image

請求轉發至 Test ClientSwagger頁面,表明 nginx配置文件 nginx.confConsul-template 成功修改。

4.1.2. 進入Nginx容器

運行 docker ps 查看 nginx-consul-template 的容器 ID,比如這里是:4f2731a7e0cb。進入 nginx-consul-template 容器。

docker-enter 4f2731a7e0cb

查看容器內部的進程列表:

image

特別留意以下一行進程命令,這里完成了三步重要的操作:

consul-template -consul-addr=consul:8500 -template /etc/consul-templates/nginx.conf.ctmpl:/etc/nginx/conf.d/app.conf:nginx -s reload
  1. Consul-template 利用 Consul 上的服務信息Nginx配置文件模板 /etc/consul-templates/nginx.conf.ctmpl 進行重新解析渲染
  2. 渲染生成的 nginx 配置文件為 /etc/nginx/conf.d/app.conf
  3. 進一步運行 nginx -s reload 重新加載 app.conf,更新路由轉發列表

查看 app.conf 的配置項,發現三個 test-client 節點的 IP:port 都加入了路由轉發列表中。

image

退出并關閉主機 192.168.1.182 上的 test-client 容器。

image

再次查看 app.conf,可以發現路由節點 192.168.1.182:80 已經從 Nginx路由轉發列表剔除掉了。

image

同樣的,重新啟動 test-client 恢復容器,又可以發現 Nginx路由轉發列表 再次自動將其添加!

4.2. 服務負載均衡

4.2.1. 接口測試

test-client 通過 http 通信方式請求任意一臺 test-server,返回響應結果 (請求處理時間 ms )。

image

test-client 通過 thrift 通信方式請求任意一臺 test-server,返回響應結果 (請求處理時間 ms )。

image

4.2.3. 日志分析

服務的負載均衡并不是很好觀察,這里直接截取了一段 test-client服務緩存列表動態定時刷新時打印的日志:

2018-02-09 13:15:55.157  INFO 1 --- [erListUpdater-1] t.c.l.ThriftConsulServerListLoadBalancer : Refreshed thrift serverList: [
test-server-thrift-service: [
    ThriftServerNode{node='consul_client_01', serviceId='test-server-thrift-service', tags=[test-server-thrift-service-01], host='192.168.1.182', port=30000, address='192.168.1.182', isHealth=true},
    ThriftServerNode{node='consul_client_01', serviceId='test-server-thrift-service', tags=[test-server-thrift-service-02], host='192.168.1.182', port=32000, address='192.168.1.182', isHealth=true},
    ThriftServerNode{node='consul_client_02', serviceId='test-server-thrift-service', tags=[test-server-thrift-service-03], host='192.168.1.183', port=30000, address='192.168.1.183', isHealth=true},
    ThriftServerNode{node='consul_client_02', serviceId='test-server-thrift-service', tags=[test-server-thrift-service-04], host='192.168.1.183', port=32000, address='192.168.1.183', isHealth=true},
    ThriftServerNode{node='consul_client_03', serviceId='test-server-thrift-service', tags=[test-server-thrift-service-05], host='192.168.1.185', port=30000, address='192.168.1.185', isHealth=true},
    ThriftServerNode{node='consul_client_03', serviceId='test-server-thrift-service', tags=[test-server-thrift-service-06], host='192.168.1.185', port=32000, address='192.168.1.185', isHealth=true}
],
test-server-http-service: [
    ThriftServerNode{node='consul_client_01', serviceId='test-server-http-service', tags=[test-server-http-service-01], host='192.168.1.182', port=16000, address='192.168.1.182', isHealth=true},
    ThriftServerNode{node='consul_client_01', serviceId='test-server-http-service', tags=[test-server-http-service-02], host='192.168.1.182', port=18000, address='192.168.1.182', isHealth=true},
    ThriftServerNode{node='consul_client_02', serviceId='test-server-http-service', tags=[test-server-http-service-03], host='192.168.1.183', port=16000, address='192.168.1.183', isHealth=true},
    ThriftServerNode{node='consul_client_02', serviceId='test-server-http-service', tags=[test-server-http-service-04], host='192.168.1.183', port=18000, address='192.168.1.183', isHealth=true},
    ThriftServerNode{node='consul_client_03', serviceId='test-server-http-service', tags=[test-server-http-service-05], host='192.168.1.185', port=16000, address='192.168.1.185', isHealth=true},
    ThriftServerNode{node='consul_client_03', serviceId='test-server-http-service', tags=[test-server-http-service-06], host='192.168.1.185', port=18000, address='192.168.1.185', isHealth=true}
],
my-web-server: [
    ThriftServerNode{node='consul_client_01', serviceId='my-web-server', tags=[test-client-http-service-01], host='192.168.1.182', port=80, address='192.168.1.182', isHealth=true},
    ThriftServerNode{node='consul_client_02', serviceId='my-web-server', tags=[test-client-http-service-02], host='192.168.1.183', port=80, address='192.168.1.183', isHealth=true},
    ThriftServerNode{node='consul_client_03', serviceId='my-web-server', tags=[test-client-http-service-03], host='192.168.1.185', port=80, address='192.168.1.185', isHealth=true}
]]

服務實例

  • test-server-http-service 所有健康的服務實例:
服務IP地址 服務端口 服務標簽
192.168.1.182 16000 test-server-http-service-01
192.168.1.182 18000 test-server-http-service-02
192.168.1.183 16000 test-server-http-service-03
192.168.1.183 18000 test-server-http-service-04
192.168.1.185 16000 test-server-http-service-05
192.168.1.185 18000 test-server-http-service-06
  • test-server-thrift-service 所有健康的服務實例:
服務IP地址 服務端口 服務標簽
192.168.1.182 30000 test-server-thrift-service-01
192.168.1.182 32000 test-server-thrift-service-02
192.168.1.183 30000 test-server-thrift-service-03
192.168.1.183 32000 test-server-thrift-service-04
192.168.1.185 30000 test-server-thrift-service-05
192.168.1.185 32000 test-server-thrift-service-06
  • my-web-server 所有健康的服務實例:
服務IP地址 服務端口 服務標簽
192.168.1.182 80 test-client-http-service-01
192.168.1.183 80 test-client-http-service-02
192.168.1.185 80 test-client-http-service-03

spring-cloud-starter-thrift 采用的輪詢的轉發策略,也就是說 my-web-server 會按次序循環往來地將 http 或者 rpc 請求分發到各自的 6服務實例完成處理。


總結

本文提供了一套基于微服務服務注冊與發現體系容器高可用 (HA) 解決方案,引入了接入層服務層自動負載均衡的實現,詳細給出了實踐方案技術手段


歡迎關注技術公眾號: 零壹技術棧

零壹技術棧

本帳號將持續分享后端技術干貨,包括虛擬機基礎,多線程編程,高性能框架,異步、緩存和消息中間件,分布式和微服務,架構學習和進階等學習資料和文章。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。