日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于consul实现微服务的服务发现和负载均衡

發(fā)布時間:2025/3/21 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于consul实现微服务的服务发现和负载均衡 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一. 背景


隨著2018年年初國務院辦公廳聯(lián)合多個部委共同發(fā)布了《國務院辦公廳關于促進“互聯(lián)網(wǎng)+醫(yī)療健康”發(fā)展的意見(國辦發(fā)〔2018〕26號)》,國內(nèi)醫(yī)療IT領域又迎來了一波互聯(lián)網(wǎng)醫(yī)院建設的高潮。不過互聯(lián)網(wǎng)醫(yī)院多基于實體醫(yī)院建設,雖說掛了一個“互聯(lián)網(wǎng)”的名號,但互聯(lián)網(wǎng)醫(yī)院系統(tǒng)也多與傳統(tǒng)的院內(nèi)系統(tǒng),比如:HIS、LIS、PACS、EMR等共享院內(nèi)的IT基礎設施。

如果你略微了解過國內(nèi)醫(yī)院院內(nèi)IT系統(tǒng)的現(xiàn)狀,你就知道目前的多數(shù)醫(yī)院的IT系統(tǒng)相比于互聯(lián)網(wǎng)行業(yè)、電信等行業(yè)來說是相對“落伍”的,這種落伍不僅體現(xiàn)在IT基礎設施的專業(yè)性和數(shù)量上,更體現(xiàn)在對新概念、新技術、新設計理念等應用上。雖然國內(nèi)醫(yī)院IT系統(tǒng)在技術層面呈現(xiàn)出“多樣性”的特征,但整體上偏陳舊和保守 – - 你可以在全國范圍內(nèi)找到10-15年前的各種主流語言(VB、delphi、c#等實現(xiàn)的IT系統(tǒng),并且系統(tǒng)架構多為兩層C/S結構的。

近幾年“互聯(lián)網(wǎng)+醫(yī)療”的興起的確在一些方面提升了醫(yī)院的服務效率和水平,但這些互聯(lián)網(wǎng)醫(yī)療系統(tǒng)多部署于院外,并主要集中在“做入口”。它們并不算是醫(yī)院的核心系統(tǒng):即沒有這些互聯(lián)網(wǎng)系統(tǒng),醫(yī)院的業(yè)務也是照常進行的(患者可以在傳統(tǒng)的窗口辦理所有院內(nèi)業(yè)務,就是效率低罷了)。因此,雖然這些互聯(lián)網(wǎng)醫(yī)療系統(tǒng)采用了先進的互聯(lián)網(wǎng)系統(tǒng)設計理念和技術,但并沒有真正提升院內(nèi)系統(tǒng)的技術水平,它們也只能與院內(nèi)那些“陳舊”的、難于擴展的系統(tǒng)做對接。

不過互聯(lián)網(wǎng)醫(yī)院與這些系統(tǒng)有所不同,雖然它依然“可有可無”,但它卻是部署在院內(nèi)IT基礎設施上的系統(tǒng),同時也受到了院內(nèi)IT基礎設施條件的限制。在我們即將上線的一個針對醫(yī)院集團的互聯(lián)網(wǎng)醫(yī)院版本中,我們就遇到了“被限制”的問題。我們本想上線的Kubernetes集群因為院方提供的硬件“不足”而無法實施,只能“降級”為手工打造的基于consul的微服務服務發(fā)現(xiàn)和負載均衡平臺,初步滿足我們的系統(tǒng)需要。而從k8s到consul的實踐過程,總是讓我有一種從工業(yè)時代回到的農(nóng)業(yè)時代或是“消費降級”的趕腳^_^。

本文就來說說基于當前較新版本的consul實現(xiàn)微服務的服務發(fā)現(xiàn)和負載均衡的過程。

?

二. 實驗環(huán)境


這里有三臺阿里云的ECS,即用作部署consul集群,也用來承載工作負載的節(jié)點(這點與真實生產(chǎn)環(huán)境還是蠻像的,醫(yī)院也僅能提供類似的這點兒可憐的設備):

  • consul-1: 192.168.0.129
  • consul-2: 192.168.0.130
  • consul-3: 192.168.0.131

操作系統(tǒng):Ubuntu?server 16.04.4 LTS
內(nèi)核版本:4.4.0-117-generic

實驗環(huán)境安裝有:

  • Docker 17.03.3-ce
  • consul v1.1.0
  • consul-template 0.19.5
  • nginx 1.10.3
  • registrator master版本
  • Go 1.11版本

實驗所用的樣例程序鏡像:

  • httpfrontservice
  • httpbackendservice
  • tcpfrontservice

?

三. 目標及方案原理


本次實驗的最基礎、最樸素的兩個目標:

  • 所有業(yè)務應用均基于容器運行
  • 某業(yè)務服務容器啟動后,會被自動注冊服務,同時其他服務可以自動發(fā)現(xiàn)該服務并調用,并且到達這個服務的請求會負載均衡到服務的多個實例。

這里選擇了與編程語言技術棧無關的、可搭建微服務的服務發(fā)現(xiàn)和負載均衡的Hashicorp的consul。關于consul是什么以及其基本原理和應用,可以參見我多年前寫的這篇有關consul的文章。

但是光有consul還不夠,我們還需要結合consul-template、gliderlab的registrator以及nginx共同來實現(xiàn)上述目標,原理示意圖如下:

原理說明:

  • 對于每個biz node上啟動的容器,位于每個node上的Registrator實例會監(jiān)聽到該節(jié)點上容器的創(chuàng)建和停止的event,并將容器的信息以consul service的形式寫入consul或從consul刪除。
  • 位于每個nginx node上的consul-template實例會watch consul集群,監(jiān)聽到consul service的相關event,并將需要expose到external的service信息獲取,按照事先定義好的nginx conf template重新生成nginx.conf并reload本節(jié)點的nginx,使得nginx的新配置生效。
  • 對于內(nèi)部服務來說(不通過nginx暴露到外部),在被registrator寫入consul的同時,也完成了在consul DNS的注冊,其他服務可以通過特定域名的方式獲取該內(nèi)部服務的IP列表(A地址)和其他信息,比如端口(SRV),并進而實現(xiàn)與這些內(nèi)部服務的通信。

參考該原理,落地到我們實驗環(huán)境的部署示意圖如下:

四. 步驟


下面說說詳細的實驗步驟。

1. 安裝consul集群

首先我們先來安裝consul集群。consul既支持二進制程序直接部署,也支持Docker容器化部署。如果consul集群單獨部署在幾個專用節(jié)點上,那么consul可以使用二種方式的任何一種。但是如果consul所在節(jié)點還承載工作負載,考慮consul作為整個分布式平臺的核心,降低它與docker engine引擎的耦合(docker engine可能會因各種情況經(jīng)常restart),還是建議以二進制程序形式直接部署在物理機或vm上。這里的實驗環(huán)境資源有限,我們采用的是以二進制程序形式直接部署的方式。

consul最新版本是1.2.2(截至發(fā)稿時),consul 1.2.x版本與consul 1.1.x版本最大的不同在于consul 1.2.x支持service mesh了,這對于consul來說可是革新性的變化,因此這里擔心其初期的穩(wěn)定性,因此我們選擇consul 1.1.0版本。

我們下載consul 1.1.0安裝包后,將其解壓到/usr/local/bin下。

在$HOME下建立consul-install目錄,并在其下面存放consul集群的運行目錄consul-data。在consul-install目錄下,執(zhí)行命令啟動節(jié)點consul-1上的consul:

consul-1 node:# nohup consul agent -server -ui -dns-port=53 -bootstrap-expect=3 -data-dir=/root/consul-install/consul-data -node=consul-1 -client=0.0.0.0 -bind=192.168.0.129 -datacenter=dc1 > consul-1.log & 2>&1# tail -100f consul-1.log bootstrap_expect > 0: expecting 3 servers ==> Starting Consul agent... ==> Consul agent running!Version: 'v1.1.0'Node ID: 'd23b9495-4caa-9ef2-a1d5-7f20aa39fd15'Node name: 'consul-1'Datacenter: 'dc1' (Segment: '<all>')Server: true (Bootstrap: false)Client Addr: [0.0.0.0] (HTTP: 8500, HTTPS: -1, DNS: 53)Cluster Addr: 192.168.0.129 (LAN: 8301, WAN: 8302)Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false==> Log data will now stream in as it occurs:2018/09/10 10:21:09 [INFO] raft: Initial configuration (index=0): []2018/09/10 10:21:09 [INFO] raft: Node at 192.168.0.129:8300 [Follower] entering Follower state (Leader: "")2018/09/10 10:21:09 [INFO] serf: EventMemberJoin: consul-1.dc1 192.168.0.1292018/09/10 10:21:09 [INFO] serf: EventMemberJoin: consul-1 192.168.0.1292018/09/10 10:21:09 [INFO] consul: Adding LAN server consul-1 (Addr: tcp/192.168.0.129:8300) (DC: dc1)2018/09/10 10:21:09 [INFO] consul: Handled member-join event for server "consul-1.dc1" in area "wan"2018/09/10 10:21:09 [INFO] agent: Started DNS server 0.0.0.0:53 (tcp)2018/09/10 10:21:09 [INFO] agent: Started DNS server 0.0.0.0:53 (udp)2018/09/10 10:21:09 [INFO] agent: Started HTTP server on [::]:8500 (tcp)2018/09/10 10:21:09 [INFO] agent: started state syncer ==> Newer Consul version available: 1.2.2 (currently running: 1.1.0)2018/09/10 10:21:15 [WARN] raft: no known peers, aborting election2018/09/10 10:21:17 [ERR] agent: failed to sync remote state: No cluster leader

我們的三個節(jié)點的consul都以server角色啟動(consul agent -server),consul集群初始有三個node( -bootstrap-expect=3),均位于dc1 datacenter(-datacenter=dc1),服務bind地址為192.168.0.129(-bind=192.168.0.129 ),允許任意client連接( -client=0.0.0.0)。我們啟動了consul ui(-ui),便于以圖形化的方式查看consul集群的狀態(tài)。我們設置了consul DNS服務的端口號為53(-dns-port=53),這個后續(xù)會起到重要作用,這里先埋下小伏筆。

這里我們使用nohup+&符號的方式將consul運行于后臺。生產(chǎn)環(huán)境建議使用systemd這樣的init系統(tǒng)對consul的啟停和配置更新進行管理。

從consul-1的輸出日志來看,單節(jié)點并沒有選出leader。我們需要繼續(xù)在consul-2和consul-3兩個節(jié)點上也重復consul-1上的操作,啟動consul:

consul-2 node:#nohup consul agent -server -ui -dns-port=53 -bootstrap-expect=3 -data-dir=/root/consul-install/consul-data -node=consul-2 -client=0.0.0.0 -bind=192.168.0.130 -datacenter=dc1 -join 192.168.0.129 > consul-2.log & 2>&1consul-3 node:# nohup consul agent -server -ui -dns-port=53 -bootstrap-expect=3 -data-dir=/root/consul-install/consul-data -node=consul-3 -client=0.0.0.0 -bind=192.168.0.131 -datacenter=dc1 -join 192.168.0.129 > consul-3.log & 2>&1

啟動后,我們查看到consul-3.log中的日志:

2018/09/10 10:24:01 [INFO] consul: New leader elected: consul-32018/09/10 10:24:01 [WARN] raft: AppendEntries to {Voter a215865f-dba7-5caa-cfb3-6850316199a3 192.168.0.130:8300} rejected, sending older logs (next: 1)2018/09/10 10:24:01 [INFO] raft: pipelining replication to peer {Voter a215865f-dba7-5caa-cfb3-6850316199a3 192.168.0.130:8300}2018/09/10 10:24:01 [WARN] raft: AppendEntries to {Voter d23b9495-4caa-9ef2-a1d5-7f20aa39fd15 192.168.0.129:8300} rejected, sending older logs (next: 1)2018/09/10 10:24:01 [INFO] raft: pipelining replication to peer {Voter d23b9495-4caa-9ef2-a1d5-7f20aa39fd15 192.168.0.129:8300}2018/09/10 10:24:01 [INFO] consul: member 'consul-1' joined, marking health alive2018/09/10 10:24:01 [INFO] consul: member 'consul-2' joined, marking health alive2018/09/10 10:24:01 [INFO] consul: member 'consul-3' joined, marking health alive2018/09/10 10:24:01 [INFO] agent: Synced node info ==> Newer Consul version available: 1.2.2 (currently running: 1.1.0)

consul-3 node上的consul被選為初始leader了。我們可以通過consul提供的子命令查看集群狀態(tài):

# consul operator raft list-peers Node ID Address State Voter RaftProtocol consul-3 0020b7aa-486a-5b44-b5fd-be000a380a89 192.168.0.131:8300 leader true 3 consul-1 d23b9495-4caa-9ef2-a1d5-7f20aa39fd15 192.168.0.129:8300 follower true 3 consul-2 a215865f-dba7-5caa-cfb3-6850316199a3 192.168.0.130:8300 follower true 3

我們還可以通過consul ui以圖形化方式查看集群狀態(tài)和集群內(nèi)存儲的各種配置信息:

至此,consul集群就搭建ok了。

2. 安裝Nginx、consul-template和Registrator

根據(jù)前面的“部署示意圖”,我們在consul-1和consul-2上安裝nginx、consul-template和Registrator,在consul-3上安裝Registrator。

a) Nginx的安裝

我們使用ubuntu 16.04.4默認源中的nginx版本:1.10.3,通過apt-get install nginx安裝nginx,這個無須贅述了。

b) consul-template的安裝

consul-template是一個將consul集群中存儲的信息轉換為文件形式的工具。常用的場景是監(jiān)聽consul集群中數(shù)據(jù)的變化,并結合模板將數(shù)據(jù)持久化到某個文件中,再執(zhí)行某一關聯(lián)的action。比如我們這里通過consul-template監(jiān)聽consul集群中service信息的變化,并將service信息數(shù)據(jù)與nginx的配置模板結合,生成nginx可用的nginx.conf配置文件,并驅動nginx重新reload配置文件,使得nginx的配置更新生效。因此一般來說,哪里部署有nginx,我們就應該有一個配對的consul-template部署。

在我們的實驗環(huán)境中consul-1和consul-2兩個節(jié)點部署了nginx,因此我們需要在consul-1和consul-2兩個節(jié)點上部署consul-template。我們直接安裝comsul-template的二進制程序(我們使用0.19.5版本),下載安裝包并解壓后,將consul-template放入/usr/local/bin目錄下:

# wget -c https://releases.hashicorp.com/consul-template/0.19.5/consul-template_0.19.5_linux_amd64.zip# unzip consul-template_0.19.5_linux_amd64.zip # mv consul-tempate /usr/local/bin # consul-template -v consul-template v0.19.5 (57b6c71)

這里先不啟動consul-template,后續(xù)在注冊不同服務的場景中,我們再啟動consul-template。

c) Registrator的安裝

Registrator是另外一種工具,它監(jiān)聽Docker引擎上發(fā)生的容器創(chuàng)建和停止事件,并將啟動的容器信息以consul service的形式存儲在consul集群中。因此,Registrator和node上的docker engine對應,有docker engine部署的節(jié)點上都應該安裝有對應的Registator。因此我們要在實驗環(huán)境的三個節(jié)點上都部署Registrator。

Registrator官方推薦的就是以Docker容器方式運行,但這里我并不使用lastest版本,而是用master版本,因為只有最新的master版本才支持service meta數(shù)據(jù)的寫入,而當前的latest版本是v7版本,年頭較長,并不支持service meta數(shù)據(jù)寫入。

在所有實驗環(huán)境節(jié)點上執(zhí)行:

# docker run --restart=always -d \--name=registrator \--net=host \--volume=/var/run/docker.sock:/tmp/docker.sock \gliderlabs/registrator:master\consul://localhost:8500

我們看到registrator將node節(jié)點上的/var/run/docker.sock映射到容器內(nèi)部的/tmp/docker.sock上,通過這種方式registrator可以監(jiān)聽到node上docker引擎上的事件變化。registrator的另外一個參數(shù):consul://localhost:8500則是Registrator要寫入信息的consul地址(當然Registrator不僅僅支持consul,還支持etcd、zookeeper等),這里傳入的是本node上consul server的地址和服務端口。

Registrator的啟動日志如下:

# docker logs -f registrator 2018/09/10 05:56:39 Starting registrator v7 ... 2018/09/10 05:56:39 Using consul adapter: consul://localhost:8500 2018/09/10 05:56:39 Connecting to backend (0/0) 2018/09/10 05:56:39 consul: current leader 192.168.0.130:8300 2018/09/10 05:56:39 Listening for Docker events ... 2018/09/10 05:56:39 Syncing services on 1 containers 2018/09/10 05:56:39 ignored: 6ef6ae966ee5 no published ports

在所有節(jié)點都啟動完Registrator后,我們來先查看一下當前consul集群中service的catelog以及每個catelog下的service的詳細信息:

// consul-1:# curl http://localhost:8500/v1/catalog/services {"consul":[]}

目前只有consul自己內(nèi)置的consul service catelog,我們查看一下consul這個catelog service的詳細信息:

// consul-1:# curl localhost:8500/v1/catalog/service/consul|jq% Total % Received % Xferd Average Speed Time Time Time CurrentDload Upload Total Spent Left Speed 100 1189 100 1189 0 0 180k 0 --:--:-- --:--:-- --:--:-- 193k [{"ID": "d23b9495-4caa-9ef2-a1d5-7f20aa39fd15","Node": "consul-1","Address": "192.168.0.129","Datacenter": "dc1","TaggedAddresses": {"lan": "192.168.0.129","wan": "192.168.0.129"},"NodeMeta": {"consul-network-segment": ""},"ServiceID": "consul","ServiceName": "consul","ServiceTags": [],"ServiceAddress": "","ServiceMeta": {},"ServicePort": 8300,"ServiceEnableTagOverride": false,"CreateIndex": 5,"ModifyIndex": 5},{"ID": "a215865f-dba7-5caa-cfb3-6850316199a3","Node": "consul-2","Address": "192.168.0.130","Datacenter": "dc1","TaggedAddresses": {"lan": "192.168.0.130","wan": "192.168.0.130"},"NodeMeta": {"consul-network-segment": ""},"ServiceID": "consul","ServiceName": "consul","ServiceTags": [],"ServiceAddress": "","ServiceMeta": {},"ServicePort": 8300,"ServiceEnableTagOverride": false,"CreateIndex": 6,"ModifyIndex": 6},{"ID": "0020b7aa-486a-5b44-b5fd-be000a380a89","Node": "consul-3","Address": "192.168.0.131","Datacenter": "dc1","TaggedAddresses": {"lan": "192.168.0.131","wan": "192.168.0.131"},"NodeMeta": {"consul-network-segment": ""},"ServiceID": "consul","ServiceName": "consul","ServiceTags": [],"ServiceAddress": "","ServiceMeta": {},"ServicePort": 8300,"ServiceEnableTagOverride": false,"CreateIndex": 7,"ModifyIndex": 7} ]

3. 內(nèi)部http服務的注冊和發(fā)現(xiàn)

對于微服務而言,有暴露到外面的,也有僅運行在內(nèi)部,被內(nèi)部服務調用的。我們先來看看內(nèi)部服務,這里以一個http服務為例。

對于暴露到外部的微服務而言,可以通過域名、路徑、端口等來發(fā)現(xiàn)。但是對于內(nèi)部服務,我們怎么發(fā)現(xiàn)呢?k8s中我們可以通過k8s集群的DNS插件進行自動域名解析實現(xiàn),每個pod中container的DNS server指向的就是k8s dns server。這樣service之間可以通過使用固定規(guī)則的域名(比如:your_svc.default.svc.cluster.local)來訪問到另外一個service(僅需配置一個service name),再通過service實現(xiàn)該服務請求負載均衡到service關聯(lián)的后端endpoint(pod container)上。consul集群也可以做到這點,并使用consul提供的DNS服務來實現(xiàn)內(nèi)部服務的發(fā)現(xiàn)。

我們需要對三個節(jié)點的DNS配置進行update,將consul DNS server加入到主機DNS resolver(這也是之前在啟動consul時將consul DNS的默認監(jiān)聽端口從8600改為53的原因),步驟如下:

  • 編輯/etc/resolvconf/resolv.conf.d/base,加入一行:
nameserver 127.0.0.1
  • 重啟resolveconf服務
/etc/init.d/resolvconf restart

再查看/etc/resolve.conf文件:

# cat /etc/resolv.conf # Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8) # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN nameserver 100.100.2.136 nameserver 100.100.2.138 nameserver 127.0.0.1 options timeout:2 attempts:3 rotate single-request-reopen

我們發(fā)現(xiàn)127.0.0.1這個DNS server地址已經(jīng)被加入到/etc/resolv.conf中了(切記:不要直接手工修改/etc/resolve.conf)。

好了!有了consul DNS,我們就可以發(fā)現(xiàn)consul中的服務了。consul給其集群內(nèi)部的service一個默認的域名:your_svc.service.{data-center}.consul. 之前我們查看了cluster中只有一個consul catelog service,我們就來訪問一下該consul service:

# ping -c 3 consul.service.dc1.consul PING consul.service.dc1.consul (192.168.0.129) 56(84) bytes of data. 64 bytes from iZbp15tvx7it019hvy750tZ (192.168.0.129): icmp_seq=1 ttl=64 time=0.029 ms 64 bytes from iZbp15tvx7it019hvy750tZ (192.168.0.129): icmp_seq=2 ttl=64 time=0.025 ms 64 bytes from iZbp15tvx7it019hvy750tZ (192.168.0.129): icmp_seq=3 ttl=64 time=0.031 ms# ping -c 3 consul.service.dc1.consul PING consul.service.dc1.consul (192.168.0.130) 56(84) bytes of data. 64 bytes from 192.168.0.130: icmp_seq=1 ttl=64 time=0.186 ms 64 bytes from 192.168.0.130: icmp_seq=2 ttl=64 time=0.136 ms 64 bytes from 192.168.0.130: icmp_seq=3 ttl=64 time=0.195 ms# ping -c 3 consul.service.dc1.consul PING consul.service.dc1.consul (192.168.0.131) 56(84) bytes of data. 64 bytes from 192.168.0.131: icmp_seq=1 ttl=64 time=0.149 ms 64 bytes from 192.168.0.131: icmp_seq=2 ttl=64 time=0.184 ms 64 bytes from 192.168.0.131: icmp_seq=3 ttl=64 time=0.179 ms

我們看到consul服務有三個實例,因此DNS輪詢在不同ping命令執(zhí)行時返回了不同的地址。

現(xiàn)在在主機層面上,我們可以發(fā)現(xiàn)consul中的service了。如果我們的服務調用者跑在docker container中,我們還能找到consul服務么?

# docker run busybox ping consul.service.dc1.consul ping: bad address 'consul.service.dc1.consul'

事實告訴我們:不行!

那么我們?nèi)绾巫屵\行于docker container中的服務調用者也能發(fā)現(xiàn)consul中的service呢?我們需要給docker引擎指定DNS:

在/etc/docker/daemon.json中添加下面配置:

{"dns": ["node_ip", "8.8.8.8"] //node_ip: consul_1為192.168.0.129、consul_2為192.168.0.130、consul_3為192.168.0.131 }

重啟docker引擎后,再嘗試在容器內(nèi)發(fā)現(xiàn)consul服務:

# docker run busybox ping consul.service.dc1.consul PING consul.service.dc1.consul (192.168.0.131): 56 data bytes 64 bytes from 192.168.0.131: seq=0 ttl=63 time=0.268 ms 64 bytes from 192.168.0.131: seq=1 ttl=63 time=0.245 ms 64 bytes from 192.168.0.131: seq=2 ttl=63 time=0.235 ms

這次就ok了!

接下來我們在三個節(jié)點上以容器方式啟動我們的一個內(nèi)部http服務demo httpbackend:

# docker run --restart=always -d -l "SERVICE_NAME=httpbackend" -p 8081:8081 bigwhite/httpbackendservice:v1.0.0

我們查看一下consul集群內(nèi)的httpbackend service信息:

# curl localhost:8500/v1/catalog/service/httpbackend|jq% Total % Received % Xferd Average Speed Time Time Time CurrentDload Upload Total Spent Left Speed 100 1374 100 1374 0 0 519k 0 --:--:-- --:--:-- --:--:-- 670k [{"ID": "d23b9495-4caa-9ef2-a1d5-7f20aa39fd15","Node": "consul-1","Address": "192.168.0.129",...},{"ID": "a215865f-dba7-5caa-cfb3-6850316199a3","Node": "consul-2","Address": "192.168.0.130",...},{"ID": "0020b7aa-486a-5b44-b5fd-be000a380a89","Node": "consul-3","Address": "192.168.0.131",...} ]

再訪問一下該服務:

# curl httpbackend.service.dc1.consul:8081 this is httpbackendservice, version: v1.0.0

內(nèi)部服務發(fā)現(xiàn)成功!

4. 暴露外部http服務

說完了內(nèi)部服務,我們再來說說那些要暴露到外部的服務,這個環(huán)節(jié)就輪到consul-template登場了!在我們的實驗中,consul-template讀取consul中service信息,并結合模板生成nginx配置文件。我們基于默認安裝的/etc/nginx/nginx.conf文件內(nèi)容來編寫我們的模板。我們先實驗暴露http服務到外面。下面是模板樣例:

//nginx.conf.template.... ...http {... ...### Virtual Host Configs##include /etc/nginx/conf.d/*.conf;include /etc/nginx/sites-enabled/*;## http server config#{{range services -}}{{$name := .Name}}{{$service := service .Name}}{{- if in .Tags "http" -}}upstream {{$name}} {zone upstream-{{$name}} 64k;{{range $service}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=60 weight=1;{{end}}}{{end}}{{end}}{{- range services -}} {{$name := .Name}}{{- if in .Tags "http" -}}server {listen 80;server_name {{$name}}.tonybai.com;location / {proxy_pass http://{{$name}};}}{{end}}{{end}}}

consul-template使用的模板采用的是go template的語法。我們看到在http block中,我們要為consul中的每個要expose到外部的catelog service定義一個server block(對應的域名為your_svc.tonybai.com)和一個upstream block。

對上面的模板做簡單的解析,弄明白三點,模板基本就全明白了:

  • {{- range services -}}: 標準的{{ range pipeline }}模板語法,services這個pipeline的調用相當于: curl localhost:8500/v1/catalog/services,即獲取catelog services列表。這個列表中的每項僅有Name和Tags兩個字段可用。
  • {{- if in .Tags “http” -}}:判斷語句,即如果Tags字段中有http這個tag,那么則暴露該catelog service。
  • {{range $service}}: 也是標準的{{ range pipeline }}模板語法,$service這個pipeline調用相當于curl localhost:8500/v1/catalog/service/xxxx,即獲取某個service xxx的詳細信息,包括Address、Port、Tag、Meta等。

接下來,我們在consul-1和consul-2上啟動consul-template:

consul-1: # nohup consul-template -template "/root/consul-install/templates/nginx.conf.template:/etc/nginx/nginx.conf:nginx -s reload" > consul-template.log & 2>&1consul-2: # nohup consul-template -template "/root/consul-install/templates/nginx.conf.template:/etc/nginx/nginx.conf:nginx -s reload" > consul-template.log & 2>&1

查看/etc/nginx/nginx.conf,你會發(fā)現(xiàn)http server config下面并沒有生成任何配置,因為consul集群中還沒有滿足Tag條件的service(包含tag “http”)。現(xiàn)在我們就來在三個node上創(chuàng)建httpfront services。

# docker run --restart=always -d -l "SERVICE_NAME=httpfront" -l "SERVICE_TAGS=http" -P bigwhite/httpfrontservice:v1.0.0

查看生成的nginx.conf:

upstream httpfront {zone upstream-httpfront 64k;server 192.168.0.129:32769 max_fails=3 fail_timeout=60 weight=1;server 192.168.0.130:32768 max_fails=3 fail_timeout=60 weight=1;server 192.168.0.131:32768 max_fails=3 fail_timeout=60 weight=1;}server {listen 80;server_name httpfront.tonybai.com;location / {proxy_pass http://httpfront;}}

測試一下httpfront.tonybai.com(可通過修改/etc/hosts),httpfront service會調用內(nèi)部服務httpbackend(通過httpbackend.service.dc1.consul:8081訪問):

# curl httpfront.tonybai.com this is httpfrontservice, version: v1.0.0, calling backendservice ok, its resp: [this is httpbackendservice, version: v1.0.0 ]

可以在各個節(jié)點上查看httpfront的日志:(通過docker logs),你會發(fā)現(xiàn)到httpfront.tonybai.com的請求被均衡到了各個節(jié)點上的httpfront service上了:

{GET / HTTP/1.0 1 0 map[Connection:[close] User-Agent:[curl/7.47.0] Accept:[*/*]] {} <nil> 0 [] true httpfront map[] map[] <nil> map[] 192.168.0.129:35184 / <nil> <nil> <nil> 0xc0000524c0} calling backendservice... {200 OK 200 HTTP/1.1 1 1 map[Date:[Mon, 10 Sep 2018 08:23:33 GMT] Content-Length:[44] Content-Type:[text/plain; charset=utf-8]] 0xc0000808c0 44 [] false false map[] 0xc000132600 <nil>} this is httpbackendservice, version: v1.0.0

5. 暴露外部tcp服務

我們的微服務可不僅僅有http服務的,還有直接暴露tcp socket服務的。nginx對tcp的支持是通過stream block支持的。在stream block中,我們來為每個要暴露在外面的tcp service生成server block和upstream block,這部分模板內(nèi)容如下:

stream {{{- range services -}}{{$name := .Name}}{{$service := service .Name}}{{- if in .Tags "tcp" -}}upstream {{$name}} {least_conn;{{- range $service}}server {{.Address}}:{{.Port}} max_fails=3 fail_timeout=30s weight=5;{{ end }}}{{end}}{{end}}{{- range services -}}{{$name := .Name}}{{$nameAndPort := $name | split "-"}}{{- if in .Tags "tcp" -}}server {listen {{ index $nameAndPort 1 }};proxy_pass {{$name}};}{{end}}{{end}} }

和之前的http服務模板相比,這里的Tag過濾詞換為了“tcp”,并且由于端口具有排他性,這里用”名字-端口”串來作為service的name以及upstream block的標識。用一個例子來演示會更加清晰。由于修改了nginx模板,在演示demo前,需要重啟一下各個consul-template。

然后我們在各個節(jié)點上啟動tcpfront service(注意服務名為tcpfront-9999,9999是tcpfrontservice expose到外部的端口):

# docker run -d --restart=always -l "SERVICE_TAGS=tcp" -l "SERVICE_NAME=tcpfront-9999" -P bigwhite/tcpfrontservice:v1.0.0

啟動后,我們查看一下生成的nginx.conf:

stream {upstream tcpfront-9999 {least_conn;server 192.168.0.129:32770 max_fails=3 fail_timeout=30s weight=5;server 192.168.0.130:32769 max_fails=3 fail_timeout=30s weight=5;server 192.168.0.131:32769 max_fails=3 fail_timeout=30s weight=5;}server {listen 9999;proxy_pass tcpfront-9999;}}

nginx對外的9999端口對應到集群內(nèi)的tcpfront服務!這個tcpfront是一個echo服務,我們來測試一下:

# telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. hello [v1.0.0]2018-09-10 08:56:15.791728641 +0000 UTC m=+531.620462772 [hello ] tonybai [v1.0.0]2018-09-10 08:56:17.658482957 +0000 UTC m=+533.487217127 [tonybai ]

基于暴露tcp服務,我們還可以實現(xiàn)將全透傳的https服務暴露到外部。所謂全透傳的https服務,即ssl證書配置在服務自身,而不是nginx上面。其實現(xiàn)方式與暴露tcp服務相似,這里就不舉例了。

?

五. 小結


以上基于consul+consul-template+registrator+nginx實現(xiàn)了一個基本的微服務服務發(fā)現(xiàn)和負載均衡框架,但要應用到生產(chǎn)環(huán)境還需一些進一步的考量。

關于服務治理的一些功能,consul 1.2.x版本已經(jīng)加入了service mesh的support,后續(xù)在成熟后可以考慮upgrade consul cluster。

consul-template在v0.19.5中還不支持servicemeta的,但在master版本中已經(jīng)支持,后續(xù)利用新版本的consul-template可以實現(xiàn)功能更為豐富的模板,比如實現(xiàn)灰度發(fā)布等。

總結

以上是生活随笔為你收集整理的基于consul实现微服务的服务发现和负载均衡的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 男女那个视频 | 欧美在线资源 | 国产精品色片 | 日本三级中国三级99人妇网站 | 右手影院亚洲欧美 | 老司机精品视频网站 | 久久久久黄色 | 国产伦精品一区二区三区高清 | 久久久久久福利 | 粉嫩久久99精品久久久久久夜 | 亚洲精品成人久久 | 美女又爽又黄免费视频 | 天堂视频在线 | 97香蕉视频| 欧美变态另类刺激 | 99插插| 中日韩av在线 | 日本三级片在线观看 | 91视频官网| 国产盗摄精品 | 看片日韩 | 精品人妻一区二区三区蜜桃 | 天堂视频网 | 一区二区三区精品视频在线观看 | 国产午夜无码精品免费看奶水 | 美女扒开内裤让男人捅 | 日韩高清在线播放 | 亚洲一区二区三区香蕉 | 国产91在线播放 | 黄色免费在线网址 | 国产视频1 | 欧美两根一起进3p做受视频 | 欧美极品视频在线观看 | 午夜色影院 | 亚洲成人三级 | 久久e热| 小明成人免费视频 | 欧美日韩三级 | 五月婷婷爱爱 | 男男肉耽高h彩漫 | 色综合影视 | 91嫩草影视 | www.99热| 欧美亚洲精品在线观看 | 国产一级在线免费观看 | 精品国产乱码久久久久久影片 | 精品久久五月天 | 欧美一区二区三区成人片在线 | 波多野结衣视频免费在线观看 | 蜜臀av88| 精品国模一区二区三区欧美 | 天海翼一区二区 | 国产黄色免费视频 | 韩国三级久久 | 免费一级suv好看的国产网站 | 日本欧美www | 探花视频在线免费观看 | 三级网站在线 | 日少妇的逼 | 欧美精品在线观看一区二区 | 日韩乱码人妻无码中文字幕 | 三年在线观看视频 | 最好看的2019年中文视频 | 天天操天天爽天天干 | 四虎精品永久在线 | 狠狠操一区二区 | 成人国产一区二区三区精品麻豆 | 久久综合精品国产二区无码不卡 | 香蕉网站在线观看 | 亚洲成av人片久久 | 欧美在线免费观看视频 | 欧美性受xxxx黑人猛交88 | www.四虎.| 国产精品人 | 国产精品91视频 | youjizz日韩| 50度灰在线 | 日本视频三区 | 中文字幕免费一区二区 | 日日夜夜婷婷 | 国产精品色婷婷 | 国产一二三视频 | 蜜桃视频一区 | 一级在线免费视频 | 狠狠爱网站 | 色老头影视 | 极度诱惑香港电影完整 | 自宅警备员在线观看 | 久久伊人免费视频 | 亚洲成人一区二区在线观看 | 日本中文字幕在线看 | 日韩av线上 | 激情五月激情 | 一本到久久 | 一级全黄裸体免费观看视频 | 国产污视频网站 | 黄瓜污视频 | 一级黄色片在线观看 | 顶级毛片 |