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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Consul + fabio 实现自动服务发现、负载均衡

發布時間:2025/3/21 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Consul + fabio 实现自动服务发现、负载均衡 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

Consul

Fabio

服務發現的特點

工作原理

Demo

結合kubernetes擴容

?

Consul


hashicorp團隊開發 就是大名鼎鼎開發 vagrant 的團隊。
Consul?是一個提供服務發現、健康檢測、K/V存儲支持分布式高可用多數據中心的服務軟件。
比較類似ZooKeeper但又比它多了一些功能。 具體可以參考?Consul和ZooKeeper的區別。

?

Fabio


fabio 是 ebay 團隊用 golang 開發的一個快速、簡單零配置,能夠讓 consul 部署的應用快速支持 http(s) 的負載均衡路由器。
因為 consul 支持服務注冊與健康檢查,所以 fabio 能夠零配置提供負載,升級部署從未如此簡單。
根據項目的介紹,fabio 能提供每秒15000次請求。
有了這兩個組件非常容易做服務發現與自動負載均衡, "神器在手、天下我有!" ^ _ ^

?

服務發現的特點


服務與服務之間的調用通常需要在配置文件中填寫好主機和端口,但是這樣不易于維護,且分布式環境中不易于部署與擴容。
那么此時就需要考慮服務啟動的時候自己把主機和端口以及一些其他信息注冊到注冊中心,這樣其他服務可以從中找到它。
甚至更為簡單的,注冊完畢后通過 DNS 的方式來『尋址』。比如 Zookeepr 可以很好的完成這個工作,但是其中還有一個弊端就是服務的健康檢查,服務注冊到注冊中心之后如何保證這個服務一定可用?此時就需要自己來寫邏輯,當服務不可用的時候自動從注冊中心下線。 Consul 可以很輕易的解決這個問題。

?

工作原理


Consul 提供了一套健康檢測機制,簡單的說針對 http 類型的服務(consul 也支持其他類型例如tcp)在注冊的時候可以順便注冊下健康檢測的信息,提供一個健康檢測的地址(url)以及一個頻率超時時間,這樣的話 consul 會定期的發送這個url請求,當狀態碼是200的時候設置此服務是健康的狀態,否則是故障狀態。
既然注冊到consul的服務能夠自己維護健康狀態,此時 fabio 的工作就很簡單了! 就是直接從consul 注冊表里面取出健康的服務,根據服務注冊時候的 tags 配置自動創建自己的路由表,然后當一個 http 請求過來的時候自動去做負載均衡

簡單的流程圖如下:

======????服務注冊?????=========? ? ? ? ?=========
? A服務? ? ? <------>? ? ? ?consul集群??---->??健康的?A/不健康的?A?集群
======????健康檢查?????=========? ? ? ? ?=========
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ^
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |?加入/移出路由表
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?========
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fabio?集群
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?========
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?|?A服務???如果找到則成功路由,否則返回錯誤
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? V
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?http?請求
?

?

Demo


這里我們開始寫一個 demo 服務來體驗一波 consul+ fabio, 順便用 docker + k8s 來編排擴容。
因為 consul + fabio 都支持 docker 的方式運行,這里均以 docker 方式為例子。

docker pull magiconair/fabio?docker pull consul

consul 可以用集群的方式開發環境中也可以用 dev 模式 可以參考這里。
這里可以參考我整理的單機部署 consul 集群的 docker compose 配置:

version:?'2'services: consul_server_1: image:?"consul:latest" container_name:?"consul_server_1" environment:CONSUL_LOCAL_CONFIG:?'{"leave_on_terminate":?true}' networks:app_net:ipv4_address:?172.17.0.3 command:?"agent?-server?-bind=172.17.0.3?-client=172.17.0.3?-retry-join=172.17.0.2"consul_server_2: image:?"consul:latest" container_name:?"consul_server_2" ports:-?"8600:8600"-?"8500:8500" networks:app_net:ipv4_address:?172.17.0.4 command:?"agent?-server?-bind=172.17.0.4?-client=172.17.0.4?-retry-join=172.17.0.3?-ui"consul_server_3: image:?"consul:latest" container_name:?"consul_server_3" environment:CONSUL_LOCAL_CONFIG:?'{"leave_on_terminate":?true}' networks:app_net:ipv4_address:?172.17.0.5 command:?"agent?-server?-bind=172.17.0.5?-client=172.17.0.5?-retry-join=172.17.0.4?-bootstrap-expect=3"networks: app_net: driver:?bridge ipam:config:-?subnet:?172.17.0.0/24


也可以按照 docker hub 上的文檔自己部署, 啟動成功之后訪問下 consul ui。


然后部署 faibo
docker-compose.yml

fabio: image:?"magiconair/fabio" ports: -?"9998:9998" -?"9999:9999" volumes: -?./fabio.properties:/etc/fabio/fabio.properties

fabio 雖然說是零配置但是某些情況下還是需要個性化配置一些東西,此時可以去寫一個簡單的配置fabio.properties
指定了 consul 的地址端口以及自身的一些統計信息等等

registry.consul.register.addr?=?172.16.0.21:9998 registry.consul.addr?=?172.16.0.21:8500 metrics.target?=?stdout

?


fabio 不僅僅可以與 consul 結合,也可以手動寫一些路由規則
語法如下:

route?add?<svc>?<src>?<dst>?weight?<w>?tags?"<t1>,<t2>,..." -?Add?route?for?service?svc?from?src?to?dst?and?assign?weight?and?tagsroute?add?<svc>?<src>?<dst>?weight?<w> -?Add?route?for?service?svc?from?src?to?dst?and?assign?weight


詳情請移步。

此時安裝部署完畢之后跑一個 demo 試試。
官方提供了一個簡單的實現:

package?mainimport?( "flag" "fmt" "log" "net" "net/http" "os" "os/signal" "path/filepath" "strconv" "strings""github.com/magiconair/fabio-example/_third_party/github.com/hashicorp/consul/api" )func?main()?{ var?addr,?name,?prefix?string flag.StringVar(&addr,?"addr",?"127.0.0.1:5000",?"host:port?of?the?service") flag.StringVar(&name,?"name",?filepath.Base(os.Args[0]),?"name?of?the?service") flag.StringVar(&prefix,?"prefix",?"",?"comma-sep?list?of?host/path?prefixes?to?register") flag.Parse()if?prefix?==?""?{flag.Usage()os.Exit(1) }//?register?prefixes prefixes?:=?strings.Split(prefix,?",") for?_,?p?:=?range?prefixes?{http.HandleFunc(p,?func(w?http.ResponseWriter,?r?*http.Request)?{fmt.Fprintf(w,?"Serving?%s?from?%s?on?%s\n",?r.RequestURI,?name,?addr)}) }//?start?http?server go?func()?{log.Printf("Listening?on?%s?serving?%s",?addr,?prefix)if?err?:=?http.ListenAndServe(addr,?nil);?err?!=?nil?{log.Fatal(err)} }()//?register?consul?health?check?endpoint http.HandleFunc("/health",?func(w?http.ResponseWriter,?r?*http.Request)?{fmt.Fprintln(w,?"OK") })//?build?urlprefix-host/path?tag?list //?e.g.?urlprefix-/foo,?urlprefix-/bar,?... var?tags?[]string for?_,?p?:=?range?prefixes?{tags?=?append(tags,?"urlprefix-"+p) }//?get?host?and?port?as?string/int host,?portstr,?err?:=?net.SplitHostPort(addr) if?err?!=?nil?{log.Fatal(err) } port,?err?:=?strconv.Atoi(portstr) if?err?!=?nil?{log.Fatal(err) }//?register?service?with?health?check serviceID?:=?name?+?"-"?+?addr service?:=?&api.AgentServiceRegistration{ID:??????serviceID,Name:????name,Port:????port,Address:?host,Tags:????tags,Check:?&api.AgentServiceCheck{HTTP:?????"http://"?+?addr?+?"/health",Interval:?"1s",Timeout:??"1s",}, }client,?err?:=?api.NewClient(api.DefaultConfig()) if?err?!=?nil?{log.Fatal(err) }if?err?:=?client.Agent().ServiceRegister(service);?err?!=?nil?{log.Fatal(err) } log.Printf("Registered?service?%q?in?consul?with?tags?%q",?name,?strings.Join(tags,?","))//?run?until?we?get?a?signal quit?:=?make(chan?os.Signal,?1) signal.Notify(quit,?os.Interrupt,?os.Kill) <-quit//?deregister?service if?err?:=?client.Agent().ServiceDeregister(serviceID);?err?!=?nil?{log.Fatal(err) } log.Printf("Deregistered?service?%q?in?consul",?name) }??


程序在啟動的時候去注冊,并且注冊了健康檢測的地址/health,在退出的時候取消注冊,往 consul注冊服務的時候有個 tags ,可以允許給這個服務傳一個標簽 ,fabio 根據這個參數來自動關聯路由映射。

先跑下試試

CONSUL_HTTP_ADDR=172.16.0.21:8500?./fabio-example?-addr=172.16.0.17:9876?-prefix=a.com/


此時 consul 已經收到注冊 ,fabio 路由已經添加。

#????Service?Host????Path????Dest????Weight 1???fabio-example???a.com???/???http://172.16.0.17:9876/????100%

?

???~?curl?-iv?-H?'Host:?a.com'?172.16.0.21:9999/ *???Trying?172.16.0.21... *?Connected?to?172.16.0.21?(172.16.0.21)?port?9999?(#0) >?GET?/?HTTP/1.1 >?Host:?a.com >?User-Agent:?curl/7.43.0 >?Accept:?*/* > <?HTTP/1.1?200?OK HTTP/1.1?200?OK <?Content-Length:?49 Content-Length:?49 <?Content-Type:?text/plain;?charset=utf-8 Content-Type:?text/plain;?charset=utf-8 <?Date:?Fri,?22?Jul?2016?01:01:28?GMT Date:?Fri,?22?Jul?2016?01:01:28?GMT< Serving?/?from?fabio-example?on?172.16.0.17:9876 *?Connection?#0?to?host?172.16.0.21?left?intact

?

結合kubernetes擴容


如果基于 k8s 做編排的話需要做一些修改,例如: ip端口 要動態的從容器里面獲取,服務啟動的時候那個 tags prefix 需要配置,可以參考fabio的文檔
這里我就用 java 快速搭建了一個, Spring cloud框架提供了服務發現一條龍服務,針對 consul 的就是?spring-cloud-consul?,只要一行代碼 幾行配置就能快速使用 :)
Application類上添加@EnableDiscoveryClient注解。

application.yml

spring: cloud: consul:discovery:healthCheckPath:?${management.contextPath}/health??#健康檢測的路徑?healthCheckInterval:?15s?#健康檢測的頻率tags:?urlprefix-api.xxxx.com/??#fabio?的路由規則


ps: spring 健康檢測可以用 spring-boot-starter-actuator快速實現。

然后 k8s 里面需要擴容就可以任性擴容了,因為如果不采用服務發現的方式, k8s 擴容時候可能 http 請求會轉發到啟動完畢的容器,但是服務并不可用(例如 java 進程雖然啟動了,但是初始化可能需要幾分鐘...)。

感受一下 擴容10個

$?kubectl?scale?--replicas=10?rc?api$?kubectl?get?pods[root@172-16-0-17?fabio-example]#?kubectl?get?pods NAME?????????????????????????????????????????????READY?????STATUS????RESTARTS???AGE api-6xytx?????????????????????????????????????????1/1???????Running???0??????????11s api-9e5838075aae036e2dc971984855e379-ac30s????????1/1???????Running???0??????????14h api-dfmtv?????????????????????????????????????????1/1???????Running???0??????????11s api-eo01h?????????????????????????????????????????1/1???????Running???0??????????11s api-hn1kv?????????????????????????????????????????1/1???????Running???0??????????11s api-iyqmg?????????????????????????????????????????1/1???????Running???0??????????11s api-k32ud?????????????????????????????????????????1/1???????Running???0??????????11s api-q10a7?????????????????????????????????????????1/1???????Running???0??????????11s api-re7e1?????????????????????????????????????????1/1???????Running???0??????????11s api-tm2pk?????????????????????????????????????????1/1???????Running???0??????????11s


10秒鐘瞬間擴容至10個, 然后看下 consul 與 fabio


fabio

#????Service?Host????Path????Dest????????????????Weight 1???api?api.com?????/???http://172.31.9.3:8080/?????10% 2???api?api.com?????/???http://172.31.9.2:8080/?????10% 3???api?api.com?????/???http://172.31.82.6:8080/????10% 4???api?api.com?????/???http://172.31.82.4:8080/????10% 5???api?api.com?????/???http://172.31.28.3:8080/????10% 6???api?api.com?????/???http://172.31.28.2:8080/????10% 7???api?api.com?????/???http://172.31.23.7:8080/????10% 8???api?api.com?????/???http://172.31.23.2:8080/????10% 9???api?api.com?????/???http://172.31.12.6:8080/????10% 10??api?api.com?????/???http://172.31.12.4:8080/????10%

總結

以上是生活随笔為你收集整理的Consul + fabio 实现自动服务发现、负载均衡的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。