--- ctx 中保存有匹配的请求特征值 match_route = function(route_t, ctx) -- run cached matcher iftype(matchers[route_t.match_rules]) == "function"then clear_tab(ctx.matches) return matchers[route_t.match_rules](route_t, ctx) end
-- build and cache matcher
local matchers_set = {}
for _, bit_match_rule inpairs(MATCH_RULES) do --- 遍历特征 匹配 if band(route_t.match_rules, bit_match_rule) ~= 0then matchers_set[#matchers_set + 1] = matchers[bit_match_rule] end end
matchers[route_t.match_rules] = function(route_t, ctx) -- clear matches context for this try on this route clear_tab(ctx.matches)
-- 路由 route_t 必须满足匹配的所有特征 for i = 1, #matchers_set do ifnot matchers_set[i](route_t, ctx) then return end end
returntrue end
return matchers[route_t.match_rules](route_t, ctx) end
路由构建, 路由分类函数 ‘categorize_route_t’ 代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
... -- init, omit insert(category.all, route_t)
for _, host_t inipairs(route_t.hosts) do ifnot category.routes_by_hosts[host_t.value] then category.routes_by_hosts[host_t.value] = {} end
insert(category.routes_by_hosts[host_t.value], route_t) end
-- header match for _, header_name inipairs(plain_indexes.headers) do if req_headers[header_name] then req_category = bor(req_category, MATCH_RULES.HEADER) hits.header_name = header_name break // 匹配后结束 header 类别匹配 end end
-- host match
if plain_indexes.hosts[host_with_port] or plain_indexes.hosts[host_no_port] then req_category = bor(req_category, MATCH_RULES.HOST) elseif ctx.req_host then for i = 1, #wildcard_hosts do local from, _, err = re_find(host_with_port, wildcard_hosts[i].regex, "ajo") ... -- omit if from then hits.host = wildcard_hosts[i].value req_category = bor(req_category, MATCH_RULES.HOST) break end end end
-- uri match
for i = 1, #regex_uris do local from, _, err = re_find(req_uri, regex_uris[i].regex, "ajo")
... -- omit
if from then hits.uri = regex_uris[i].value req_category = bor(req_category, MATCH_RULES.URI) break end end
ifnot hits.uri then if plain_indexes.uris[req_uri] then hits.uri = req_uri req_category = bor(req_category, MATCH_RULES.URI) else for i = 1, #prefix_uris do iffind(req_uri, prefix_uris[i].value, nil, true) == 1then hits.uri = prefix_uris[i].value req_category = bor(req_category, MATCH_RULES.URI) break end end end end
-- method match
if plain_indexes.methods[req_method] then req_category = bor(req_category, MATCH_RULES.METHOD) end
-- src match
if plain_indexes.sources[ctx.src_ip] then req_category = bor(req_category, MATCH_RULES.SRC) elseif plain_indexes.sources[ctx.src_port] then req_category = bor(req_category, MATCH_RULES.SRC) else for i = 1, #src_trust_funcs do if src_trust_funcs[i](ctx.src_ip) then req_category = bor(req_category, MATCH_RULES.SRC) break end end end
-- dst match
if plain_indexes.destinations[ctx.dst_ip] then req_category = bor(req_category, MATCH_RULES.DST) elseif plain_indexes.destinations[ctx.dst_port] then req_category = bor(req_category, MATCH_RULES.DST) else for i = 1, #dst_trust_funcs do if dst_trust_funcs[i](ctx.dst_ip) then req_category = bor(req_category, MATCH_RULES.DST) break end end end
-- sni match
if plain_indexes.snis[ctx.sni] then req_category = bor(req_category, MATCH_RULES.SNI) end
-- 生成通用 API 函数 localfunctiongenerate_collection_endpoints(endpoints, schema, foreign_schema, foreign_field_name) local collection_path if foreign_schema then collection_path = fmt("/%s/:%s/%s", foreign_schema.admin_api_name or foreign_schema.name, foreign_schema.name, schema.admin_api_nested_name or schema.admin_api_name or schema.name)
else collection_path = fmt("/%s", schema.admin_api_name or schema.name) end
-- Create a list of entries, and randomize them. local unassignedWheelIndices = self.unassignedWheelIndices local duplicateCheck = new_tab(self.wheelSize, 0) -- 使用 randomlist 创建一个 1-wheelSize 范围的随机数数组, 数值不会重复. 用于将负载地址随机分布在 wheel 数组中 local orderlist = opts.order or randomlist(self.wheelSize)
for i = 1, self.wheelSize do local order = orderlist[i] unassignedWheelIndices[i] = order end
-- Sort the hosts, to make order deterministic -- ... table_sort(hosts, function(a,b)return (a.name..":"..(a.port or"") < b.name..":"..(b.port or"")) end) -- Insert the hosts -- 添加地址, 并在 wheel 中添加索引 for _, host inipairs(hosts) do local ok, err = self:addHost(host.name, host.port, host.weight) end
functionring_balancer:redistributeIndices() local totalWeight = self.weight -- Host 变更时会在 base 中会修改 weight local movingIndexList = self.unassignedWheelIndices
-- NOTE: calculations are based on the "remaining" indices and weights, to -- prevent issues due to rounding: eg. 10 equal systems with 19 indices. -- Calculated to get each 1.9 indices => 9 systems would get 1, last system would get 10 -- by using "remaining" indices, the first would get 1 index, the other 9 would get 2.
-- first; reclaim extraneous indices local weightLeft = totalWeight local indicesLeft = self.wheelSize local addList = {} -- addresses that need additional indices local addListCount = {} -- how many extra indices the address needs local addCount = 0 local dropped, added = 0, 0 -- 便利所有负载 for weight, address, _ inself:addressIter() do
-- 根据权重, 计算负载索引个数 local count if weightLeft == 0then count = 0 else count = math_floor(indicesLeft * (weight / weightLeft) + 0.0001) -- 0.0001 to bypass float arithmetic issues end local drop = #address.indices - count if drop > 0then -- we need to reclaim some indices address:dropIndices(movingIndexList, drop) dropped = dropped + drop elseif drop < 0then -- this one needs extra indices, so record the changes needed -- 记录需要添加索引的地址, 稍后为地址分配索引 addCount = addCount + 1 addList[addCount] = address addListCount[addCount] = -drop -- negate because we need to add them end indicesLeft = indicesLeft - count weightLeft = weightLeft - weight end
-- 为地址分配索引 -- second: add freed indices to the recorded addresses that were short of them for i, address inipairs(addList) do address:addIndices(movingIndexList, addListCount[i]) added = added + addListCount[i] end
returnself end
functionring_address:addIndices(availableIndicesList, count) count = count or #availableIndicesList if count > 0then local myWheelIndices = self.indices local size = #myWheelIndices -- ... local wheel = self.host.balancer.wheel local lsize = #availableIndicesList + 1 for i = 1, count do -- 获取一个未分配索引 local availableIdx = lsize - i local wheelIdx = availableIndicesList[availableIdx] availableIndicesList[availableIdx] = nil -- 当前地址增加一个索引,(地址删除索引时使用) myWheelIndices[size + i] = wheelIdx wheel[wheelIdx] = self end
# 数据库初始化 su - postgres psql # 创建用户 CREATE USER konga WITH PASSWORD 'konga'; # 创建数据库 CREATE DATABASE konga OWNER konga; # 授权 GRANT ALL PRIVILEGES ON DATABASE konga TO konga;