1. 程式人生 > >.Net Core微服務系列--服務發現

.Net Core微服務系列--服務發現

負載 amd uno 概念 啟動 cat currently csp 集群

什麽是服務發現

首先我們先思考一個問題,當我們在瀏覽器中輸入一個域名比如baidu.com,然後發生了什麽才能讓我們訪問到百度的網頁?簡單來說,瀏覽器會首先從主機的hosts文件中查看是否有baidu.com對應ip的映射,如果有就直接用hosts文件得到的ip來請求數據,如果沒有那麽就需要去DNS服務器來請求ip地址,Dns服務器在自己數據庫中查找域名對應的ip,如果有多個ip那麽需要用DNS負載均衡器根據策略返回一個ip。DNS服務器簡單來看就是提供了一個域名和服務器映射關系的註冊和查詢的東西,這個其實就是服務發現。所以我們可以說DNS就是實現了服務發現,當然DNS有兩點局限性使得我們無法直接應用到微服務中。


  • DNS服務器不支持動態變更。我在前面的文章中有提到過微服務有按需虛擬化的概念,我們的節點可能會根據需要在虛擬化平臺中動態的增加,減少,丟棄,DNS服務器就不能支撐我們微服務的動態變化
  • DNS服務器也沒辦法了解到每個實例的情況,因此無法實現真正的負載均衡

為什麽有服務發現

以前我們服務一般運行在物理機器上,服務實例的地址相對於固定,我們只需要在調用方用配置的方式獲取服務實例的網絡地址就行,但是對於現在基於雲端,容器化的微服務來說服務實例的網絡地址一般都是動態變化的,在實例升級,擴展,離線的時候都會經常改變,所以才有了服務發現。服務發現提供了服務註冊,服務目錄,服務查詢等功能,並且會動態的更新服務目錄來保證調用方獲取的服務列表是最新可用的。

常用服務發現工具

這個就直接貼網上的圖片了

技術分享圖片

本篇文章就選用Consul來進行Demo的測試了。

服務發現均衡器

當我們從服務發現工具中獲取一個實例集群的地址,應該會是多個(當然這個集群也可以直接暴露的是一個負債均衡的地址),客戶端可以自己根據策略來進行負載均衡處理,但是這樣額外增加了每個客戶端工作,所以我們可以結合現在的HA均衡器和服務發現工具來實現這個這個功能,比如 Nginx + Consul Template。大概流程如圖

技術分享圖片

搭建Consul測試環境

Consul的介紹網上一大堆,我就直接貼以下他的特性然後直接進入到測試階段。

  • 服務發現(Service Discovery):客戶端通過 Consul 提供服務,其他客戶端可以通過 Consul 利用 dns 或者 http 發現依賴服務
  • 健康檢查(Health Checking): Consul 提供任務的健康檢查,可以用來操作或者監控集群的健康,也可以在服務發現時去除失效的服務
  • 鍵值對存儲(Key/Value Store): 存儲層級鍵值對
  • 多數據中心(Multi Datacenter): Consul 支持開箱即用的多數據中心

因為我只有一臺ubuntu和一臺windows,準備再ubuntu.docker,windows 分別運行一個Node,docker上的node就只是用來滿足三個服務節點,本次測試不會在這個節點上配置服務。

安裝

Linux(Ubuntu 18.04)上安裝Consul並檢查安裝結果
到官網根據系統版本下載壓縮包https://www.consul.io/downloads.html
解壓之後就是一個consul的可執行文件,將其添加到系統的環境變量中,並檢查是否可運行

unzip consul_1.4.4_linux_amd64.zip
sudo cp -a consul  /usr/bin
consul -v

Ubutu啟動Agent

consul必須啟動agent才能使用,有兩種啟動模式server和client,還有一個官方自帶的ui。server用與持久化服務信息,集群官方建議3或5個節點。client只用與於server交互。ui可以查看集群情況的。

先啟動一個Server

consul agent  -bootstrap-expect 3  -server   -data-dir /path/to/data-dir -node=linuxnode1 -bind=YourIP -config-dir /path/to/config-dir -enable-script-checks=true  -datacenter=dc1 -ui

參數解釋:

-bootstrap-expect:集群期望的節點數,只有節點數量達到這個值才會選舉leader。

-server: 運行在server模式

-data-dir:指定數據目錄,其他的節點對於這個目錄必須有讀的權限

-node:指定節點的名稱

-bind:為該節點綁定一個地址

-config-dir:指定配置文件,定義服務的,默認所有一.json結尾的文件都會讀

-enable-script-checks=true:設置檢查服務為可用

-datacenter: 數據中心沒名稱,

-ui: 使用自帶的UI

這些命令行參數 也可以直接在配置文件中進行設置,如下所示

{
  "datacenter": "dc1,
  "data_dir": "/your/data/path,
  "log_level": "INFO",
  "node_name": "foobar",
  "server": true,
  "watches": [
    {
        "type": "checks",
        "handler": "/usr/bin/health-check-handler.sh"
    }
  ]
}

*其中Watch節點是用於服務告警

因為我們集群期望節點數是3 所以現在的consul agent 是報錯狀態

技術分享圖片

docker啟動Agent

  docker run -d -p 18500:8500 -p 18300:8300 -p 18301:8301 --name consulserver consul agent -server -node=dockernode1 -client 0.0.0.0 -datacenter=dc1 -retry-join={KnowCluserIP}

windows啟動Agent

windows跟linux操作一樣下載壓縮包 解壓之後將consul 可執行文件加入系統的環境變量
打開cmd 執行命令

consul agent  -bootstrap-expect 2  -server   -data-dir /path/to/data-dir -node=cn1 -bind=YourIP -config-dir /path/to/config-dir -enable-script-checks=true  -datacenter=dc1 -retry-join=KnowClusterIp

參數解釋
-retry-join:加入到已有的集群中支持重試

再執行 docker members 可以看到我們三個Server已經啟動並加入了相同的集群中了

技術分享圖片

通過ip:8500 訪問自帶的Web管理器

技術分享圖片

也可以很直觀的看到我們的三個node,我現在停掉dockernode1的容器

技術分享圖片

可以看到dockernode1處於異常狀態了

OK,到現在為止我們consul的測試環境是搭建起來了,但是我們的三個節點中都沒有服務,接下來我們會向這幾個節點中都加入一些服務。

服務註冊

創建一個ASP.NET CORE WebApi程序

打開VS CODE 並運行

 dotnet new webapi

一個簡單的api程序就建立好了,我們添加一點簡單的代碼用於健康檢查

   [Route("api/Health")]
    public class HealthController : Controller
    {
        [HttpGet]
        public IActionResult Get() => Ok("ok");
    }

使用AntDepoly(https://github.com/yuzd/AntDeployAgent)發布到windows服務器上

編寫dockerfile

FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS build
WORKDIR /app

# copy csproj and restore as distinct layers
COPY *.csproj ./aspnetapi/
WORKDIR /app/aspnetapi
RUN dotnet restore

# copy everything else and build app
COPY . ./aspnetapi/
WORKDIR /app/aspnetapi
RUN dotnet publish -c Release -o out


FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime
WORKDIR /app
COPY --from=build /app/aspnetapi/out ./
ENTRYPOINT ["dotnet", "aspnet-healthcheck.dll"]

直接去構建鏡像 或者直接用我放到hub中的鏡像來運行兩個服務

docker run -it --rm -p 8001:80 -d --name ubuntunode1 yhx1990126/aspnetcore-healthcheck:1.0
docker run -it --rm -p 8002:80 -d --name ubuntunode2 yhx1990126/aspnetcore-healthcheck:1.0

OK,現在我們就已經IIS和docker中分別部署了兩套服務,接著把這四個服務註冊到Consul中

註冊服務

在前面運行Consul Agent配置的文件夾中建立一個service.json的配置文件(當指定了config-dir後,consul會到目錄中根據詞典順序加載配置文件),service.json的內容如下

{
    "services": [{
            "id": "ubuntuservice01",
            "name": "ubuntuservice",
            "tags": ["ubuntu"],
            "address": "192.168.0.149",
            "port": 8001,
            "checks": [{
                "http": "http://192.168.0.149:8001/api/Health",
                "interval": "10s"
            }]
        },
        {
            "id": "ubuntuservice02",
            "name": "ubuntuservice",
            "tags": ["ubuntu"],
            "address": "192.168.0.149",
            "port": 8002,
            "checks": [{
                "http": "http://192.168.0.149:8001/api/Health",
                "interval": "10s"
            }]
        }
    ]
}

兩個服務用的同一個name,當後面從Consul獲取IP的時候就會拿到這兩個服務的IP,Json文件中的Checks節點是用來進行健康檢查的,更多管service的配置可以參照官方文檔https://www.consul.io/docs/agent/services.html

在windows上同樣建立相同的Json文件,修改一下name和IP就行,最後運行命令

consul reload

這個命令是Consul用來重新加載配置的,支持重新加載的配置如下

  • Log level
  • Checks
  • Services
  • Watches
  • HTTP Client Address
  • TLS Configuration
    • Please be aware that this is currently limited to reload a configuration that is already TLS enabled. You cannot enable or disable TLS only with reloading.
  • Node Metadata
  • Metric Prefix Filter
  • Discard Check Output
  • RPC rate limiting

OK,騷等幾秒,直接去web界面看結果

技術分享圖片

技術分享圖片

可以看到我們的服務已經註冊成功了,調用接口來獲取服務地址試試

http://192.168.0.149:8500/v1/catalog/service/ubuntuservice

技術分享圖片

技術分享圖片

可以看到我們返回了我們註冊的兩個地址。

我們現在是用配置文件的方式註冊服務的,當然也可以在asp.net core 程序中進行註冊,但是這樣對代碼有入侵所以還是推薦配置文件的方式來註冊。有關其他的配置比如 watch,check可以參考官方,這裏就不進行實驗了。

服務消費

本來計劃接下來是講解在asp.net core 程序中怎麽消費服務的,但是想了下其實沒有什麽好說的,無外乎就是利用Consul提供的接口來進行服務的尋址,然後利用獲取到的接口進行調用,這一塊內容就打算放到後期與網關結合那一塊去實現。

小結

今天了解了服務發現在微服務中的作用,了解了Consul的基本使用,但是基本沒有跟.net core相關的東西,

我之所以還是把這篇文章放到微服務之路的系列文章裏是因為服務發現在微服務中地位太重要了,所以還是決定要單獨寫一篇來介紹服務發現。
最後應該會發現,在微服務的體系中,如果用Consul類似的工具來實現服務發現基礎設施,為了保證高可用性,無疑會增加系統的復雜性,所以我們也可以選擇一些部署環境內置了服務發現的工具 比如k8s來減少我們自己搭建環境的復雜性和成本。

.Net Core微服務系列--服務發現