- 后端
- 网络/通信
- 云原生
【免费下载链接】bfe
A modern layer 7 load balancer from baidu
导读
mod_redirect是百度开源七层负载均衡器 BFE 中的核心模块之一,负责根据预定义规则对 HTTP 请求执行重定向。本文以官方文档 mod_redirect 模块说明 为主体,结合 模块基本配置、规则配置 及仓库源码,完整讲解该模块的启用方式、两种配置文件的写法、四种重定向动作的语义与底层实现、请求处理调用链与热加载机制。读完本文,你将能够独立编写可运行的mod_redirect.conf与redirect.data,并理解重定向结果如何生成、如何被 BFE 处理框架消费。
一、模块概览:它做什么,在哪里生效
mod_redirect的核心能力一句话概括:在请求被路由到后端集群之前,若命中规则条件,则直接改写请求的重定向目标并中止后续处理。其适用场景包括:
- 域名变更后的旧地址跳转(如将
http://old.example.com301 到https://new.example.com); - 协议升级(HTTP → HTTPS);
- 按路径、查询参数、Header 等条件进行的精细化分流跳转;
- 基于请求中携带的目标 URL 参数实现"中转跳转"。
1.1 在 BFE 模块链中的位置
从模块注册表 bfe_modules/bfe_modules.go 可以看到,mod_redirect的注册位置带有明确约束注释:
// mod_redirect // Requirement: After mod_logid mod_redirect.NewModuleRedirect(),即要求mod_redirect 必须排在 mod_logid 之后注册。同时在主配置 conf/bfe.conf 中,它默认通过Modules = mod_redirect启用,位于mod_rewrite之后、mod_logid之后,与源码注册顺序一致。
1.2 挂在哪个处理阶段
在 mod_redirect.go 的init()中,模块将自己注册为HandleFoundProduct阶段的过滤器:
err := cbs.AddFilter(bfe_module.HandleFoundProduct, m.redirectHandler)HandleFoundProduct对应 bfe_module/bfe_callback.go 中定义的回调阶段,即产品(Product)路由已确定之后、进入后端转发之前。这正是重定向的最佳介入点:此时已能按产品名(product)精确匹配规则,且重定向结果可以立即取代后端转发。若规则命中,处理器返回 bfe_module/bfe_handler_list.go 中定义的BfeHandlerRedirect标志,后续处理链将据此直接产出Location响应头,不再访问后端集群。
二、模块基本配置:mod_redirect.conf
mod_redirect.conf是模块的基本配置文件,采用 INI 格式,由 conf_mod_redirect.go 中的ConfLoad()通过gcfg.ReadFileInto解析。官方文档给出的完整配置项如下:
| 配置项 | 类型 | 含义 | 是否必填 | 补充说明 | 生效条件 |
|---|---|---|---|---|---|
| Basic.DataPath | String | 规则配置文件路径 | 是 | 默认mod_redirect/redirect.data | 类型为 FilePath,文件必须存在且可读 |
| Log.OpenDebug | Boolean | 是否开启调试日志 | 否 | 默认False | - |
官方示例(INI):
[Basic] DataPath = mod_redirect/redirect.data [Log] OpenDebug = false2.1 源码层面的默认值与路径处理
需要特别注意的是,文档标注为"必填"的Basic.DataPath在源码中实际有默认值兜底。见 conf_mod_redirect.go:
func ConfModRedirectCheck(cfg *ConfModRedirect, confRoot string) error { if cfg.Basic.DataPath == "" { log.Logger.Warn("ModRedirect.DataPath not set, use default value") cfg.Basic.DataPath = "mod_redirect/redirect.data" } cfg.Basic.DataPath = bfe_util.ConfPathProc(cfg.Basic.DataPath, confRoot) return nil }未配置DataPath时会告警并回落至默认相对路径mod_redirect/redirect.data,随后通过bfe_util.ConfPathProc将相对路径与配置根目录(confRoot)拼接为完整路径。
仓库自带的真实配置文件 conf/mod_redirect/mod_redirect.conf 如下(注意小节名[basic]大小写不敏感):
[basic] DataPath = mod_redirect/redirect.data2.2 调试开关
Log.OpenDebug控制 mod_redirect.go 中的包级变量openDebug。开启后,redirectHandler会打印规则匹配前后状态:匹配前输出host/path/query与规则列表,命中后输出redirectUrl与redirectCode,未命中则输出not need redirect。生产环境建议保持关闭(默认False),排查重定向不生效问题时再临时开启。
三、规则配置:redirect.data
redirect.data是mod_redirect的规则配置文件,JSON 格式。其完整字段说明如下:
| 配置项 | 类型 | 含义 | 是否必填 | 补充说明 |
|---|---|---|---|---|
| Version | String | 配置文件版本 | 是 | 通常为时间戳字符串,如20190101000000,类型为 Version |
| Config | Object | 各产品的重定向规则集合 | 是 | Key 为产品名 |
| Config{k} | String | 产品名 | 是 | - |
| Config{v} | Array | 有序的重定向规则列表 | 是 | - |
| Config{v}[] | Object | 一条重定向规则 | 是 | - |
| Config{v}[].Cond | String | 条件表达式 | 是 | 语法见 Condition 条件语法 |
| Config{v}[].Actions | Array | 有序的重定向动作列表 | 是 | - |
| Config{v}[].Actions[] | Object | 一个重定向动作 | 是 | - |
| Config{v}[].Actions[].Cmd | String | 动作名称 | 是 | 合法取值见下文"动作"小节 |
| Config{v}[].Actions[].Params | Object | 动作参数 | 否 | 依具体动作而定 |
| Config{v}[].Status | Integer | HTTP 状态码 | 否 | 须为合法的 HTTP 重定向状态码 |
官方完整示例:
{ "Version": "20190101000000", "Config": { "example_product": [ { "Cond": "req_path_prefix_in(\"/redirect\", false)", "Actions": [ { "Cmd": "URL_SET", "Params": ["https://example.org"] } ], "Status": 301 } ] } }仓库自带的真实规则文件 conf/mod_redirect/redirect.data 与之同构,仅在Version上使用了"init version"占位。
3.1 加载与校验流程
规则文件由 redirect_conf_load.go 中的redirectConfLoad()加载,流程为:打开文件 → JSON 解码 → 逐级校验 → 转换为内部结构。校验规则(RedirectConfCheck/ProductRulesCheck/RuleListCheck/redirectRuleCheck)强制要求:
Version与Config必须存在(否则报no Version/no Config);- 每个产品必须有规则列表(
no RuleList for product:xxx); - 每条规则必须同时具备
Cond、Actions、Status:缺Cond报no Cond,缺Actions报no Actions,缺Status或Status为 0 报redirect code not provided; Cond字符串通过condition.Build()编译为可执行的条件对象,语法错误将直接导致加载失败。
仓库测试 redirect_conf_load_test.go 恰好覆盖了这两个方向:redirect_1.conf(testdata/redirect_1.conf)是合法文件(产品pn含 1 条规则,pt为空列表),加载成功;redirect_2.conf(testdata/redirect_2.conf)故意缺少cond字段,加载必然报错——这是你排查"规则加载失败"时最常遇到的原因之一。
3.2 条件表达式 Cond
Cond是 BFE 统一的条件表达式,支持多个条件原语(primitive)通过&&、||、!、括号组合,完整语法见 Condition 概念与语法。常用原语包括:
req_host_in("a.com|b.com"):请求 Host 是否命中集合;req_path_prefix_in("/redirect", false):请求路径是否以指定前缀开头(第二个参数为大小写敏感标志);req_query_key_in("space"):请求查询参数中是否存在指定 key;req_method_in("GET"):请求方法匹配。
组合示例(来自 testdata/mod_redirect/redirect.json):
"cond": "req_host_in(\"www.example.org\") && req_path_prefix_in(\"/index/\", false) && req_query_key_in(\"space\")"该条件要求同时满足:Host 为www.example.org、路径以/index/开头、查询串含space参数,才会触发重定向。
四、四种重定向动作详解
redirect.data中Actions[].Cmd的合法取值共四种(官方文档 Actions 表):
| 动作 | 说明 |
|---|---|
| URL_SET | 重定向到指定的 URL |
| URL_FROM_QUERY | 重定向到从请求指定查询参数中解析出的 URL |
| URL_PREFIX_ADD | 重定向到"指定前缀 + 原始 URL"拼接结果 |
| SCHEME_SET | 重定向到原 URL 但替换协议,仅支持 http|https |
4.1 动作校验规则
动作校验在 action.go 的ActionFileCheck()中完成,有两条硬性约束:
- 每条规则只允许一个动作:
ActionFileListCheck明确len(*conf) > 1时报currently only support exclusive action!,四种动作在EXCLUSIVE_ACTIONS映射中互斥,动作必须"独占"; - 每个动作恰好需要 1 个参数:
URL_SET、URL_FROM_QUERY、URL_PREFIX_ADD、SCHEME_SET的paramsLenCheck = 1,参数个数不符会报num of params:[ok:1, now:N]; SCHEME_SET参数仅限http/https(大小写不敏感,会自动转小写),其他协议报scheme %s invalid, only http|https supported now。
4.2 各动作的底层实现
四种动作的最终执行逻辑集中在 action_url.go:
- URL_SET(
ReqUrlSet):直接把Redirect.Url赋值为参数指定的完整 URL,最简单直接; - URL_FROM_QUERY(
ReqUrlFromQuery):从请求查询串中取出参数指定 key 的值作为跳转目标。源码注释给出典型用法:请求http://service?url=(.*),参数传url即可跳转到$1的值。实现上若req.Query为空会先调用req.HttpRequest.URL.Query()惰性解析; - URL_PREFIX_ADD(
ReqUrlPrefixAdd):取原始 URI(path + query,通过RequestURI()得到),在其前面拼接参数指定的前缀。注释示例:原 URI/(.*)加前缀后变为link$1,适合"在旧路径前统一加域名/前缀"的场景; - SCHEME_SET(
ReqSchemeSet):保留原 host(优先取 URL 中的 Host,为空则取请求头 Host)与 URI,仅替换协议,生成scheme://host/uri形式。这是HTTP → HTTPS 强制跳转的标准实现。
动作执行入口是 action.go 的redirectActionsDo():先经checkExclusiveAction确认是唯一动作,再按Cmd分发到对应实现。
4.3 动作的单元测试佐证
action_url_test.go 对四种动作逐一验证了生成的重定向 URL:
TestReqUrlSet:原 URLhttp://www.example.org/unknown+ 参数http://www.example.org/more→ 直接跳转到http://www.example.org/more;TestReqUrlFromQuery:请求http://www.example.org/redirect?url=http://n.example.org+ keyurl→ 跳转到http://n.example.org;TestReqUrlPrefixAdd:原 URLhttp://n.example.org/yule/test.html+ 前缀http://n1.example.com/redirect→ 跳转到http://n1.example.com/redirect/yule/test.html(注意:前缀拼接的是 path+query,不保留原 host);TestReqSchemeSet:原 URLhttp://n.example.org/test.html+ schemehttps→ 跳转到https://n.example.org/test.html。
这四个测试是理解各动作"参数到底怎么拼、结果长什么样"的最直观教材。
五、请求处理调用链:从规则命中到重定向响应
当请求进入 BFE 并完成产品路由后,mod_redirect的处理逻辑在 mod_redirect.go 的redirectHandler中展开,完整调用链如下:
- 查表:
m.ruleTable.Search(request.Route.Product)按产品名获取规则列表; - 逐条匹配:
PrepareReqRedirect()(mod_redirect.go)按文件中的书写顺序遍历规则,对每条规则执行rule.Cond.Match(req); - 执行动作:首条命中规则的
Cond成立后,立即执行该规则的Actions(即上文四种动作之一),并调用redirectCodeSet(req, rule.Status)将状态码写入req.Redirect.Code,然后短路返回true,不再继续匹配后续规则——规则的先后顺序直接影响结果,应将更具体/优先级更高的规则排在前面; - 返回处理标志:命中则返回
bfe_module.BfeHandlerRedirect,未命中(或无该产品规则)返回bfe_module.BfeHandlerGoOn,请求继续走后续模块与后端转发。
规则表 redirect_table.go 使用sync.RWMutex保护productRules,Update()整体替换规则集、Search()读锁查询,保证热加载时读请求不受阻塞。
模块级测试 mod_redirect_test.go 验证了完整行为:产品pn且请求满足www.example.org+/index/前缀 +space查询参数时返回BfeHandlerRedirect;而产品pb(无规则)时返回BfeHandlerGoOn。
六、热加载:不改进程、在线更新规则
mod_redirect支持通过 BFE 的 web 监控接口在线重载规则,无需重启进程。注册逻辑见 mod_redirect.go:
err = whs.RegisterHandler(web_monitor.WebHandleReload, m.name, m.loadConfData)loadConfData()(mod_redirect.go)的行为值得注意:
- 可通过查询参数
?path=xxx指定临时配置文件路径(用于灰度验证新规则); - 未指定时使用
m.configPath(即mod_redirect.conf中的DataPath); - 加载成功后调用
m.ruleTable.Update(conf)原子替换规则表; - 返回
文件名=版本号(如redirect.data=20190101000000)作为重载成功的确认信息,便于核对当前生效的规则版本。
由于Version字段的存在,你可以在redirect.data中写入时间戳,重载后通过返回值确认版本已切换,实现"配置即代码"式的可追溯管理。
七、端到端完整示例:从零配置一个重定向场景
综合上述全部要素,下面给出一个可复制到仓库conf/目录运行的完整示例(路径均以 BFE 配置根目录为基准)。
步骤 1:启用模块。确认 conf/bfe.conf 中存在Modules = mod_redirect。
步骤 2:编写模块配置 conf/mod_redirect/mod_redirect.conf:
[Basic] DataPath = mod_redirect/redirect.data [Log] OpenDebug = false步骤 3:编写规则配置 conf/mod_redirect/redirect.data,实现两类需求:
{ "Version": "20261009000000", "Config": { "example_product": [ { "Cond": "req_host_in(\"old.example.com\")", "Actions": [ { "Cmd": "URL_SET", "Params": ["https://new.example.com"] } ], "Status": 301 }, { "Cond": "req_path_prefix_in(\"/index/\", false) && !req_query_key_in(\"space\")", "Actions": [ { "Cmd": "SCHEME_SET", "Params": ["https"] } ], "Status": 302 } ] } }- 第一条:访问
old.example.com的任何请求,301 永久跳转到https://new.example.com(域名迁移场景); - 第二条:路径以
/index/开头且查询串中不含space参数时,302 临时升级为 HTTPS(强制跳转且保留原 host 与 path)。
步骤 4:加载与验证。启动 BFE 后,通过 web 监控接口触发重载,确认返回redirect.data=20261009000000;随后发起满足/不满足条件的请求,观察响应Location头与状态码。若结果不符,开启OpenDebug = true后查看调试日志中before:/after:两行输出,定位是条件未命中还是动作生成错误。
八、总结与常见问题速查
mod_redirect以"产品(product)→ 规则列表 → 条件 + 独占动作 + 状态码"三层结构,提供了简洁而完备的请求重定向能力。核心要点回顾:
- 两条配置文件:INI 格式的
mod_redirect.conf(指定规则路径)与 JSON 格式的redirect.data(定义规则本体); - 四种动作
URL_SET/URL_FROM_QUERY/URL_PREFIX_ADD/SCHEME_SET均为互斥独占、各需 1 个参数,SCHEME_SET仅支持 http/https; - 规则按书写顺序匹配,首个命中即生效(短路);
Cond、Actions、Status三者缺一不可; - 处理阶段为
HandleFoundProduct,命中后返回BfeHandlerRedirect终止后端转发;热加载通过 web reload 接口实现,返回文件名=版本号确认。
排查问题的常见切入点:规则未生效先查产品名是否与request.Route.Product一致;加载失败优先检查redirect.data的 JSON 合法性与必填字段是否齐全(可对照 testdata/redirect_2.conf 这类"故意缺字段"的反例);跳转 URL 与预期不符时,对照 action_url_test.go 理解各动作的参数拼接规则。深入源码可继续阅读 mod_redirect.go、redirect_conf_load.go 与 redirect_table.go。
- 后端
- 网络/通信
- 云原生
【免费下载链接】bfe
A modern layer 7 load balancer from baidu
相关推荐
Multipass Windows 10/11 构建实战:从环境搭建到 WiX 安装程序打包
Multipass Windows 10/11 构建实战:从环境搭建到 WiX 安装程序打包 本文基于仓库根目录的 BUILD.windows.md https
后端网络/通信云原生FAST Element 非浏览器 HTML 渲染与水合标记机制完全指南
FAST Element 非浏览器 HTML 渲染与水合标记机制完全指南 导读 @microsoft/fast element 的声明式(Declarative
后端网络/通信云原生BFE mod_block 模块深度解析:基于规则的连接与请求拦截指南
BFE mod_block 模块深度解析:基于规则的连接与请求拦截指南 导读 mod_block 是 BFE(Baidu Front End,百度开源的七层负载
后端网络/通信云原生
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考