API最长前缀匹配策略
全称,api最长前缀匹配负载策略,通过请求的URI的最长前缀子串,再拿到所有API负载规则进行匹配,得到命中的API匹配规则,进而得到具体匹配的节点。
# 代码位置 : balance/tl_ops_balance_core_api.lua
-- 处理匹配逻辑
local tl_ops_balance_api_matcher_mode = function (matcher, request_uri, obj)
local match_mode = obj.match_mode
if not match_mode then
match_mode = tl_ops_match_mode.reg
end
-- 正则匹配模式
if match_mode == tl_ops_match_mode.reg or match_mode == tl_ops_match_mode.regi or match_mode == tl_ops_match_mode.regid then
local from, to , _ = find(request_uri , (obj.fake_prefix .. obj.url) , match_mode);
if from and to then
local sub = string.sub(request_uri, from, to)
if sub then
if not matcher or not matcher.url then
matcher = obj
end
-- 规则最长匹配优先
if matcher.url and #sub > #matcher.url then
matcher = obj
end
end
end
end
-- 全文匹配
if match_mode == tl_ops_match_mode.all then
if request_uri == (obj.fake_prefix .. obj.url) then
matcher = obj;
end
end
return matcher
end
-- 获取命中的api路由项
local tl_ops_balance_api_get_matcher_rule = function(api_list_table, rule, rule_match_mode, request_uri)
local matcher = nil;
local matcher_list = api_list_table[rule]
if not matcher_list then
return nil
end
-- 获取当前host
local cur_host = ngx.var.host;
for i, obj in pairs(matcher_list) do
repeat
if rule_match_mode == tl_ops_constant_balance_api.mode.host then
-- 如果是优先host规则匹配,先剔除不属于当前host的规则
if obj.host == nil or obj.host == '' then
break
end
if obj.host ~= "*" and obj.host ~= cur_host then
break
end
end
matcher = tl_ops_balance_api_matcher_mode(matcher, request_uri, obj)
break
until true
end
return matcher
end
local tl_ops_balance_api_service_matcher = function(service_list_table)
local matcher = nil
local node = nil
-- 规则匹配模式
local rule_match_mode, _ = cache_api:get(tl_ops_constant_balance_api.cache_key.rule_match_mode);
if not rule_match_mode then
-- 默认以host优先匹配
rule_match_mode = tl_ops_constant_balance_api.mode.host;
end
-- api路由策略
local api_rule, _ = cache_api:get(tl_ops_constant_balance_api.cache_key.rule);
if not api_rule then
return nil, nil, nil, nil, rule_match_mode
end
-- api配置列表
local api_list, _ = cache_api:get(tl_ops_constant_balance_api.cache_key.list);
if not api_list then
return nil, nil, nil, nil, rule_match_mode
end
local api_list_table = cjson.decode(api_list);
if not api_list_table then
return nil, nil, nil, nil, rule_match_mode
end
-- 获取当前url
local request_uri = tl_ops_utils_func:get_req_uri();
-- 根据路由当前策略进行路由, 返回正则命中的api
if api_rule == tl_ops_constant_balance_api.rule.point then
matcher = tl_ops_balance_api_get_matcher_rule(
api_list_table, tl_ops_constant_balance_api.rule.point, rule_match_mode, request_uri
);
elseif api_rule == tl_ops_constant_balance_api.rule.random then
matcher = tl_ops_balance_api_get_matcher_rule(
api_list_table, tl_ops_constant_balance_api.rule.random, rule_match_mode, request_uri
);
end
if not matcher or type(matcher) ~= 'table' then
return nil, nil, nil, nil, rule_match_mode
end
local service_list = service_list_table[matcher.service]
local node_id = matcher.node -- lua index start 1
local host = matcher.host
if not host or host == nil then
host = ""
end
-- 指定节点
if api_rule == tl_ops_constant_balance_api.rule.point then
if node_id ~= nil then
node = service_list[tonumber(node_id) + 1]
else
return nil, nil, nil, host, rule_match_mode
end
-- 服务内随机
elseif api_rule == tl_ops_constant_balance_api.rule.random then
math.randomseed(#request_uri)
node_id = tonumber(math.random(0,1) % #service_list_table[matcher.service]) + 1
node = service_list[node_id]
end
-- 获取当前节点健康状态
local key = tl_ops_utils_func:gen_node_key(tl_ops_constant_health.cache_key.state, matcher.service, node_id)
local node_state , _ = shared:get(key)
-- 命中统计
balance_count_api.tl_ops_balance_count_incr_api_succ(matcher.service, node_id, matcher.id);
-- 静态页面代理路径
local api_type = matcher.api_type
if api_type and api_type == tl_ops_api_type.page then
ngx.req.set_uri_args({
url = request_uri
})
ngx.req.set_uri("/pageproxy", true)
return
end
-- 需要重写url
local rewrite_url = matcher.rewrite_url
if rewrite_url and rewrite_url ~= '' then
ngx.req.set_uri(rewrite_url, false)
return
end
-- 需要转发到服务下的具体路径
local fake_prefix = matcher.fake_prefix
if fake_prefix and fake_prefix ~= '' then
-- 通过虚拟前缀截取后缀
local fake_sub = string.sub(request_uri, #fake_prefix + 1, #request_uri)
if fake_sub then
ngx.var.tlops_ups_api_prefix = fake_sub
end
end
return node, node_state, node_id, host, rule_match_mode
end
COOKIE精准匹配策略
这种策略是精准匹配,获取请求内所有cookie后,再拿到所有cookie负载规则进行匹配,得到命中的cookie匹配规则,进而得到具体匹配的节点。
具体实现代码类似 URI 匹配。
请求参数精准匹配策略
这种策略是精准匹配,获取请求内所有请求参数后,再拿到所有请求参数负载规则进行匹配,得到命中的请求参数匹配规则,进而得到具体匹配的节点。
具体实现代码类似 URI 匹配。
请求头部精准匹配策略
这种策略是精准匹配,获取请求内所有请求头后,再拿到所有请求头负载规则进行匹配,得到命中的请求头匹配规则,进而得到具体匹配的节点。
具体实现代码类似 URI 匹配。
请求body子串匹配策略
这种策略是子串匹配,获取请求内请求body后,再拿到所有请求body负载规则子串进行匹配,得到命中的请求头匹配规则,进而得到具体匹配的节点。
具体实现代码类似 URI 匹配。