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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

OpenResty中的upstream healthcheck功能沉思录

發布時間:2023/11/27 生活经验 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenResty中的upstream healthcheck功能沉思录 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
綜述

healthcheck功能本質上還是個定時器,去定期檢查指定upstream組的狀態,它發送指定的http請求并解析響應碼,去探測upstream中每個peer的存活狀態,再結合歷史請求記錄來判斷并標記其狀態,如果有狀態改變,就在共享內存中更新版本記錄,下次執行時,所有的worker進程都要更新到最新的peer狀態。

下面的表述都假定我們要監控的upstream組名是ats_node_backend, 也就是對應nginx.conf中的這個代碼塊

upstream ats_node_backend {
? ? server 127.0.0.2;
? ? server 127.0.0.3 backup;
? ? server 127.0.0.4 fail_timeout=23 weight=7 max_fails=200 backup;

}

配置參數解釋
hc.spawn_checker(options)
options中包含如下選項,在調用該接口時作為參數傳遞進來
type? ? ? ? 必須存在并且是http,目前只支持http
http_req? 必須存在,健康探測的http請求raw字符串
timeout? ? 默認1000,單位ms
interval? ? 健康探測的時間間隔,單位ms, 默認1000,推薦2000
valid_status? ?合法響應碼的表,比如{200, 302}
concurrency? ?并發數,默認1
fall? ? ? ? ? ? 默認5,對UP的設備,連續fall次失敗,認定為DOWN
rise? ? ? ? ? ?默認2,對DOWN的設備,連續rise次成功,認定為UP
shm? ? ? ?必須配置,用于健康檢查的共享內存名稱,通過ngx.shared[shm]得到共享內存
upstream? ?指定要做健康檢查的upstream組名,必須存在
version? 默認0
primary_peers? 主組
backup_peers? 備組
statuses? 存放合法響應碼的數組,來自ipairs()得到的valid_status配置項
根據options會構造一個ctx表來存放所有的配置數據,并會作為定時器ngx.timer.at()中的第三個參數
ctx的內容如下
upstream? ?指定的upstream組名
primary_peers 主組
backup_peers? 備組
http_req? 健康檢查的raw http請求
timeout? 超時時間,單位s,注意不是ms
interval? 健康檢查的間隔,單位s,注意不是ms
dict? 存放統計數據的共享內存
fall? ?認為DOWN之前的連續失敗次數,默認5
rise? 認為UP之前的連續成功次數,默認2
statuses? 認為正常的http狀態碼的表{200,302}
version? ? 0 每次執行定時任務時的版本號,有peer狀態改變,版本號加1
concurrency? ? 創建該數目的輕量線程來并發發送健康檢測請求的個數

上面的這些配置項,將作為一個上下文保存下來,在不同的階段被反復調用

使用方法

在init_worker_by_lua_block階段,在nginx.conf中放入下面的代碼

local hc = require "resty.upstream.healthcheck"local ok, err = hc.spawn_checker{shm = "healthcheck",  -- defined by "lua_shared_dict"upstream = "foo.com", -- defined by "upstream"type = "http",http_req = "GET /status HTTP/1.0\r\nHost: foo.com\r\n\r\n",-- raw HTTP request for checkinginterval = 2000,  -- run the check cycle every 2 sectimeout = 1000,   -- 1 sec is the timeout for network operationsfall = 3,  -- # of successive failures before turning a peer downrise = 2,  -- # of successive successes before turning a peer upvalid_statuses = {200, 302},  -- a list valid HTTP status codeconcurrency = 10,  -- concurrency level for test requests}if not ok thenngx.log(ngx.ERR, "failed to spawn health checker: ", err)returnend

這里Host可以是127.0.0.1或是其它ip。如果你需要一個查看探測的upstream組的狀態,可以再在nginx.conf中配置

server {...# status page for all the peers:location = /status {access_log off;allow 127.0.0.1;deny all;default_type text/plain;content_by_lua_block {local hc = require "resty.upstream.healthcheck"ngx.say("Nginx Worker PID: ", ngx.worker.pid())ngx.print(hc.status_page())}}}

然后在外面直接訪問

wget 'http://127.0.0.1/status'

就可以看到所有upstream的peer狀態,特別是我們檢測的ats_node_backend這組,沒有配置檢測的upstream組前面會有"(NO checkers)"字樣。


代碼架構

本身是個定時器,該模塊對外提供了兩個接口


該定時器內干的活兒如下:



自問自答

1.如何對一個peer做健康探測?
通俗的健康探測可以是嘗試與peer連接,或者發送http請求。后者是一種比較精確地檢查服務是否正常的情況,因為只是做端口探測的話,如果服務僵死了,端口還是探測得通的。
healthcheck模塊這里采用lua輕量級線程去專門向要檢查的服務發送指定的http請求,并接收服務的響應狀態碼,根據狀態碼的情況來判斷服務是否是正常的,斷定UP或是DOWN


2.如何保存對peer健康探測的每次結果?
探測的結果無非兩種情況:ok或是fail。因此,分為兩種情況來對應存放,比如以key為ok:ats_node_backend:p9的記錄來primary peers中peer id為9的設備的累計成功次數,同理nok:ats_node_backend:b1表示backup peers中peer id為1的設備的累計失敗次數。
如果當前探測結果是成功,會首先去共享內存中查詢累計的成功次數,并在原來的次數基礎上增加1并更新到共享內存中。修改之后如果次數為0,就需要將對應的失敗記錄從共享內存中清除。


3.如何判斷是否要改變當前的peer狀態?
需要考慮3個因素,參見上面配置的標注(1)(2)(3):
(1)當前peer的狀態peer.down, 從upstream模塊的接口upstream.get_primary_servers()中獲取peer.down的值, 另外也要謹慎處理當前worker中的這個peer.down值
(2)目前成功或是失敗的次數
(3)healthcheck模塊配置中的判斷成功或失敗的閾值,從定時器的ctx參數中可以得到, ctx.ok或ctx.fail
下面以判斷下線狀態為例來說明:
該peer當前是上線狀態,也就是peer.down=nil或false,fails次數超過設定失敗閾值,認定為下線(DOWN)
進一步的操作為調用set_peer_down_globally()函數,同時更改peer.down=true


4.set_peer_down和peer.down有啥關系?

關系是一樣的


5.節點內多臺設備的健康探測是怎樣執行的?
采用nginx輕量級線程去并發執行多個檢查任務,異步執行完之后,回調處理函數,處理完后該線程死掉。


6.當一個worker在healthcheck過程中發現某個peer掉線了,它是如何處理的?它如何將該peer的狀態傳遞到所有其它worker知道?

在該腳本中是分為三步來完成的,參考上面的圖示:
(1)在set_peer_down_globally()函數中,對探測做出的結果,來設置一次set_peer_down,同時給出下面的兩步來誘發后面的處理
說明ctx.new_version=true;
同時在共享內存中存入對應的記錄,標記以d:ats_node_backend:p9為key的記錄來表明該peer是UP還是DOWN狀態
(2)在do_check()函數中,如果有新版本的話,先查詢共享內存中的v:ats_node_backend的記錄的值,加1,更新ctx.version,同時置空ctx.new_version。
這里的代碼處理非常巧妙:
dict:add(key, 0)
local new_ver, err = dict:incr(key, 1)
使用dict:add()是為了避免插入重復的鍵值,如果該鍵已經存在,直接返回nil和和err="exists",如果不存在,直接置0
下一步是在原來的基礎上加1,這一步妥妥能執行。
(3)在下一次定時任務執行時,所有worker進程首先去共享內存中查找key為v:ats_node_backend的記錄的值,也就是獲取ctx.version的精確值。比較當前值與ctx.version,如果ctx.version的值小于共享內存中的值,說明需要更新peer版本。



注意每條日志的worker進程號不一樣,說明它們都在更新peer版本號。


7.其它的worker如何更新peer版本呢?

就是去共享內存中檢查key為d:ats_node_backend:p9的記錄,如果存在該記錄,說明peer是DOWN,否則peer是UP。只有peer.down和查到的值不同,就需要set_peer_down,同時設置peer.down=down


8.為啥不使用ctx.version來傳遞版本號,而要專門在共享內存中記錄專門的記錄來傳遞呢?
這主要是涉及到nginx中worker進程的執行和配置同步問題。一般來說,通常每份代碼都會被所有的worker執行到,但是對peers的健康檢查,我們只需要一個worker去執行就夠了,一個worker執行完后,其它的worker來同步它的狀態就夠了。在do_check中我們看到除了下面的get_lock保護的代碼是某個worker執行的,其它的代碼,所有的worker都會去執行。定時任務采用進程搶占方式,每次執行的worker進程并不固定,這樣的話,ctx.version一般是不連續的,通過共享內存方式,可以保證每個worker進程每次都可以得到最新的peer信息,而且peer version是逐漸遞增的。
但是在一個worker執行過程中,ctx中的所有的字段都是可以在函數中傳遞的。


9.為啥要所有的worker進程都執行set_peer_down這個函數?
https://github.com/openresty/lua-upstream-nginx-module#set_peer_down

上面的官方文檔強調了,該函數的執行必須所有的worker都執行,才能在server級別上生效。只在一個worker中執行,只能在該worker內部生效。


10.在nginx.conf中調用時,能否采用單進程調用方式,比如使用ngx.worker.id()==0的if條件語句?
這也是我曾經犯過的錯誤,答案當然是否定的。原因有兩個:一個是為了讓upstream.set_peer_down接口在server級別生效,必須所有的worker進程都要調用該函數;另一個,就是healthcheck模塊內部已經實現了使用單個worker去進行實際的健康檢測功能。


11.外部如何獲取upstream中各peer之間的狀態?

該模塊對外提供了一個狀態查詢接口_M.status_page()
下面說下它的處理細節:
在status_page()中會創建一個局部數組類型的表,來獲取所有的統計信息,最后將這些數組中的元素拼接成字符串。
local bits = new_tab(n * 20, 0)
n = #us? ?us是upstream的縮寫,指upstream的組數,每組upstream會占用20個數組元素
table.concat? 將table中的元素按照指定分隔符連接起來
bits數組內容如下
bits[0]="Upstream "
bits[1]="ats_node_backend"
bits[2]="? ?(NO checkers)"
bits[3]="\n? ? Primary Peers\n"
bits[4]="? ? ? ? "
bits[5]="10.10.101.10:18980"
bits[6]=" DOWN\n"
……
bits[n]="? ?Backup Peers\n"
bits[n+1]="? ? ? ? "
bits[n+2]="10.10.101.12:18980"
bits[n+3]=" up\n"
……

bits[n+m]="\n"


參考文獻
[1].https://github.com/openresty/lua-resty-upstream-healthcheck
[2].https://github.com/openresty/lua-upstream-nginx-module#set_peer_down


總結

以上是生活随笔為你收集整理的OpenResty中的upstream healthcheck功能沉思录的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 五月婷婷丁香花 | 朝桐光一区二区 | 天天激情站 | av网址导航 | 国产一级二级三级 | 91av综合 | 亚洲少妇一区二区三区 | 在线观看视频一区二区三区 | 欧洲最强rapper网站直播 | 91在线观 | 黑人巨大精品欧美一区二区免费 | аⅴ资源新版在线天堂 | 日韩av线观看 | 国产原创一区 | jizzjizz日本人 | 97人人精品 | 欧美一级二级在线观看 | 日本不卡视频一区 | 轮番上阵免费观看在线电影 | 成人午夜网址 | 熟妇人妻中文字幕无码老熟妇 | 中国一级黄色 | 久久久精品人妻一区二区三区色秀 | 又嫩又硬又黄又爽的视频 | 久久色播 | 男男一级淫片免费播放 | 丰满少妇高潮一区二区 | 看av免费毛片手机播放 | 欧美69av | 国产真人无码作爱视频免费 | 国产伦精品一区二区三区四区免费 | 欧美性猛交 | 欧美精品一二区 | 日韩激情在线播放 | 肉丝超薄少妇一区二区三区 | 精品国产乱码久久久久久1区2区 | 亚洲性生活视频 | 亚洲大尺度在线观看 | 一区二区三区免费在线视频 | 日韩免费一级 | 樱花草涩涩www在线播放 | 亚洲影视网 | 在线欧美亚洲 | 日韩城人网站 | 中文字幕av无码一区二区三区 | 五月天六月婷婷 | 欧美天天| 日日噜| 亚洲成人偷拍 | 欧美一区国产一区 | 亚洲激情电影在线 | 日韩精品一区二区视频 | 男女激情网 | 99精品久久久久久久婷婷 | 国产在线拍 | 五月激情婷婷综合 | 蜜色视频 | 神马久久网站 | 亚洲91视频 | 希岛婚前侵犯中文字幕在线 | 亚洲黄色免费在线观看 | 午夜写真片福利电影网 | 97超碰导航 | 亚洲成人777 | 一级黄色片看看 | 极品videosvideo喷水 | 性生活视频软件 | 天天射美女 | 亚洲av成人无码久久精品 | 又爽又黄又无遮挡 | 成人黄网免费观看视频 | 精品无码久久久久久久 | 噜噜色综合 | 中日毛片| 久久久久亚洲日日精品 | 亚洲无限观看 | 日本深夜福利 | 牲欲强的熟妇农村老妇女视频 | 日本在线网址 | 男女插插视频 | 久久久久青草 | 亚洲福利在线播放 | 国产毛片欧美毛片久久久 | 国产视频一区在线观看 | 日本一区二区不卡视频 | 91一区在线 | 97caocao| 综合av第一页 | 激情综合小说 | 老熟妇午夜毛片一区二区三区 | 无遮挡在线 | 成人xxxxx| 97青草| 一本av在线 | 久久精品无码一区 | 亚洲精品h| 欧美精品日韩少妇 | 国产欧美日本 | 高清av网站 |