1. 程式人生 > >aserver配置解析之單元化規則

aserver配置解析之單元化規則

最近有空把aserver的線上配置看了一遍,大體上了解了接入層對整個請求的流轉和控制。
aserver是tengine的一個分支,其中包含了很多的私有指令,不過大部分根據指令名稱也能猜出個大概。
本篇主要是講解一下單元化規則的相關內容。
我理解的單元化規則問題,就是當用戶請求過來的時候,aserver如何能轉發到對應單元的後端upstream機器。那麼就來看一下如何根據使用者區分單元。
在cell_location_mtop.conf裡,

set $cell_random 1;
set_by_lua_file $armory_self_cell /home/admin/cai/conf/nginx_lua_armory_cell.lua;
set_by_lua_file $cell /home/admin/cai/conf/set_user_unit.lua $cookie_unb $router_rule;
這裡設定cell_random為1,是表示當用戶未登入或者為訪客時,將進行隨機的單元化分配,而預設情況下,客戶端連線的是最後一次分配到的單元aserver。

再來看nginx_lua_armory_cell.lua,
首先判斷armory_cell這個變數是否存在,這個變數是從armory上取下來的,指令是在nginx_aserver.conf的這裡:

armory_role $armory_cell CENTER_UNIT.center;
這條指令的含義是:從armory上取本機所屬的單元,若取不到則置為中心。
接著進行判斷,

若不存在,則直接取center
若存在,則取CENTER_UNIT.之後的單元字串 這樣,便取到了armory_self_cell的值,理論上應該為center,unit,unsz,unyun這幾個值
接下來看set_user_unit.lua
先取一個預設的單元,

local default_unit
if ngx.var.cell_random then
default_unit = ngx.var.armory_self_cell
else
default_unit = “center”
end
接下來獲取使用者的userid,一共有3個來源

cookie裡的unb
cookie裡的munb
http請求頭裡的x-uid
local userid = ngx.var.cookie_unb
if userid == nil or userid == “” then
userid = ngx.var.cookie_munb
if userid == nil or userid == “” then
userid = ngx.req.get_headers()[“x-uid”]
if userid == nil or userid == “” then
return default_unit
end
end
end
下面是解析使用者尾號的分佈了,我們從diamond的dataid為com.ali.unit.routerule,groupid為DEFAULT_GROUP拉取單元化規則,這個指令是在nginx_aserver.conf裡。

diamond_app DEFAULT_GROUP com.ali.unit.routerule $router_rule $router_ver;
這個配置是下面這種格式:

unit:{(userId % 10000) % 10000 in (6700…6799)}
{10.177.32.0/24,10.177.33.0/24,10.177.34.0/24,10.17
第一行用來判斷使用者尾號是否在對應的區間內。其中有兩種規則:
精確規則: 形式是unit:{1 3 5 7 9},此種模式可以將指定的多個獨立尾號使用者引流至同一單元,且此種模式優先順序要高於普通規則。
普通規則: 形式是unit:{(userId % 10000) % 10000 in (6700…6799)},這個就不說了,要注意的是這種規則下只能指定一個區間。
第二行用來指示該單元對應的機器網路分佈。這樣後面從vipserver拉取upstream的機器列表的時候,就能夠判斷區分到底取哪些單元的機器了。
那麼問題來了,假如多個單元的分佈規則區間合併完並不能包含所有尾號,那麼怎麼分配呢?比如像下面這樣:

unit:{(userId % 10000) % 10000 in (6700…6799)}
{10.177.32.0/24,10.177.33.0/24,10.177.34.0/24,10.17

unsz:{(userId % 10000) % 10000 in (7000…9999)}
{10.185.36.0/24,10.185.37.0/24,10.185.38.0/24,10.18

unyun:{(userId % 10000) % 10000 in (10000…10000)}
{10.185.248.0/24,10.185.249.0/24,10.185.250.0/24,10

CENTER:{(userId % 10000) % 10000 in (0…6699)}
{10.0.0.0/8,172.0.0.0/8,192.168.0.0/16}

那麼尾號6900的使用者如何分配呢?
以前的邏輯是返回default_unit,如上面程式碼的分析,這個值取的是機器所在的單元。
那麼當某個單元流量已經切走,而客戶端的單元規則還沒有更新的時候,客戶端就仍然請求到了這個沒有流量的單元,這樣,跨單元的問題最終只能在hsf被糾正。這也是一個"詭異"的跨單元問題排查產生的原因。不過現在已經修改過了,找不到匹配的區間,直接返回’center’。

整體的判斷邏輯如下:
在這裡插入圖片描述
這個只是aserver上的規則判斷,其實有很多細節問題還沒有搞清楚,尤其是和客戶端的策略配合,是比較複雜的,後面得慢慢了解。下篇會再講一下詳情的配置。