ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Apache APISIX brotli 插件:动态 Brotli 响应压缩的配置实战与源码解析

Apache APISIX brotli 插件:动态 Brotli 响应压缩的配置实战与源码解析 Apache APISIX brotli 插件动态 Brotli 响应压缩的配置实战与源码解析【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisixbrotli 插件用于在 Apache APISIX 网关层动态控制 Nginx 的 Brotli 压缩行为让网关根据每个路由/全局规则按需对响应体进行 Brotli 压缩而无需修改 Nginx 配置文件或重启服务。读完本文你将掌握 brotli 共享库的构建安装、插件属性含义与取值、通过 Admin API 启用与删除插件的完整流程以及该插件在header_filter/body_filter阶段压缩响应的底层原理与测试验证方法。描述brotli插件可以在 Apache APISIX 中动态地设置 Nginx 中 ngx_brotli 的行为。与原生ngx_brotli模块通过 Nginx 指令如brotli、brotli_types、brotli_comp_level静态配置不同APISIX 的 brotli 插件把这些能力抽象为路由/全局规则上的 JSON 属性随配置热更新即时生效实现了压缩策略的按路由差异化与动态调整。在插件优先级体系中brotli 的priority为996紧邻 gzip 插件995之前二者构成 APISIX 内置的响应压缩组合。默认情况下该插件在 config.yaml.example 中处于注释状态需要在plugins列表中显式启用后才能使用。前提条件构建并安装 brotli 共享库该插件依赖 brotli 共享库在编译 OpenResty/APISIX 环境时需要确保系统能够加载到libbrotli动态库。官方文档给出了基于源码构建的示例脚本wget https://github.com/google/brotli/archive/refs/tags/v1.1.0.zip unzip v1.1.0.zip cd brotli-1.1.0 mkdir build cd build cmake -DCMAKE_BUILD_TYPERelease -DCMAKE_INSTALL_PREFIX/usr/local/brotli .. sudo cmake --build . --config Release --target install sudo sh -c echo /usr/local/brotli/lib /etc/ld.so.conf.d/brotli.conf sudo ldconfig上述命令依次完成下载 brotli v1.1.0 源码、解压、以 Release 模式配置 CMake 构建安装前缀为/usr/local/brotli、编译安装、将动态库路径写入/etc/ld.so.conf.d/brotli.conf并刷新动态链接器缓存。值得注意的是APISIX 的 brotli 插件在运行时通过 Lua 侧加载共享库。在 apisix/plugins/brotli.lua 中插件使用pcall(require, brotli)的方式安全地尝试加载 brotli 的 Lua 绑定加载失败时is_loaded为false插件会在header_filter阶段记录错误日志 please check the brotli library 并跳过压缩而不会导致请求失败。这意味着即使未正确安装共享库路由上的插件配置依然可以正常下发只是压缩功能不生效。属性说明插件的完整属性定义见 apisix/plugins/brotli.lua 中的schema其含义与 ngx_brotli 的对应指令一一对应名称类型必选项默认值有效值描述typesarray[string] 或 *False[text/html]动态设置brotli_types指令指定需要压缩的响应 MIME 类型。特殊值*匹配任意 MIME 类型min_lengthintegerFalse20 1动态设置brotli_min_length指令响应体长度小于该值的响应不压缩comp_levelintegerFalse6[0, 11]动态设置brotli_comp_level指令压缩级别0 为不压缩数值越大压缩率越高modeintegerFalse0[0, 2]动态设置 brotli 压缩模式对应brotli decompress mode更多信息参考 RFC 7932lgwinintegerFalse19[0, 10-24]动态设置 brotli 滑动窗口大小lgwin是滑动窗口大小的以 2 为底的对数设置为 0 时由压缩器自行决定最佳值更多信息参考 RFC 7932lgblockintegerFalse0[0, 16-24]动态设置 brotli 输入块大小lgblock是最大输入块大小的以 2 为底的对数设置为 0 时由压缩器自行决定最佳值更多信息参考 RFC 7932http_versionnumberFalse1.11.1, 1.0与gzip_http_version指令类似用于识别 http 协议版本低于该版本的请求不压缩varybooleanFalsefalse与gzip_vary指令类似用于启用或禁用插入Vary: Accept-Encoding响应头结合源码可以进一步理解各属性的取值约束与设计意图typesschema中通过anyOf限定为「元素为字符串、至少一项的数组」或枚举*之一且默认{text/html}。在header_filter中apisix/plugins/brotli.lua如果配置为数组会先剥离Content-Type中分号后的字符如text/plain; charsetUTF-8会被截取为text/plain再与列表逐项精确匹配配置为*时则不做类型过滤。min_lengthminimum 1默认 20。源码中只有当响应携带Content-Length头时才参与判断apisix/plugins/brotli.lua与 Nginx 行为一致缺失Content-Length时不做最小长度检查。comp_levelminimum 0、maximum 11默认 6注释说明跟随 ngx_brotlibrotli_comp_level的默认值。brotli 的 011 压缩级别区间比 gzip 的 19 更宽11 级可获得最佳压缩率但 CPU 开销更高。modeminimum 0、maximum 2默认 0。源码注释给出了三种模式的含义0为MODE_GENERIC通用默认、1为MODE_TEXT面向 UTF-8 文本、2为MODE_FONT面向 WOFF 2.0 字体。针对文本或字体数据选择对应模式可提升压缩率。lgwin / lgblock分别通过enum限定为{0,10..24}与{0,16..24}默认值 19 与 0 均跟随 ngx_brotli 的brotli_window/ 默认行为。lgwin0或lgblock0表示由压缩器自行决定最优值。http_version枚举{1.1, 1.0}默认 1.1。源码通过ngx.req.http_version()获取当前请求的 HTTP 版本若小于配置值则跳过压缩apisix/plugins/brotli.lua。vary布尔类型默认未启用。启用后调用core.response.add_header(Vary, Accept-Encoding)apisix/plugins/brotli.lua追加响应头避免中间缓存对「未声明 Accept-Encoding」的客户端错误复用压缩响应。从源码结构可以推断这些属性最终会被组装为 brotli 压缩器的 options 传入brotli.compressor:new(options)apisix/plugins/brotli.lua其中comp_level映射为压缩器的quality参数mode、lgwin、lgblock原样透传。启用插件启用 brotli 插件需要两步先在conf/config.yaml的plugins列表中加入brotli参考 config.yaml.example 中#- brotli # priority: 996的注释位置去掉行首注释并重启或 reload APISIX然后通过 Admin API 在路由或全局规则上配置插件参数。首先从config.yaml中获取admin_key并存入环境变量admin_key$(yq .deployment.admin.admin_key[0].key conf/config.yaml | sed s///g)然后在指定的路由上启用brotli插件curl -i http://127.0.0.1:9180/apisix/admin/routes/1 -H X-API-KEY: $admin_key -X PUT -d { uri: /, plugins: { brotli: { } }, upstream: { type: roundrobin, nodes: { httpbin.org: 1 } } }示例中brotli: {}表示使用全部默认属性仅压缩text/html、最小长度 20 字节、压缩级别 6 等即可开启对/路径响应体的 Brotli 压缩。若需要自定义参数只需在插件对象中补充对应字段例如brotli: { types: [text/html, text/plain, application/json], min_length: 100, comp_level: 9, mode: 1, lgwin: 22, vary: true }Admin API 在写入配置前会调用插件的check_schemaapisix/plugins/brotli.lua非法参数会被直接拒绝。测试文件 t/plugin/brotli.t 中的 schema 校验用例展示了典型失败场景types: []空数组、min_length: 0低于下限 1、mode: 4超出上限 2、comp_level: 12超出上限 11、http_version: 2不在枚举内、lgwin: 100与lgblock: 8不在枚举内、vary: 0非布尔类型都会被返回 failed to check the configuration of plugin brotli 错误。使用示例通过上述命令启用插件后发起带Accept-Encoding: br头的请求即可测试压缩是否生效curl http://127.0.0.1:9080/ -i -H Accept-Encoding: br预期响应如下响应头中出现Content-Encoding: br表示压缩生效HTTP/1.1 200 OK Content-Type: text/html; charsetutf-8 Transfer-Encoding: chunked Connection: keep-alive Date: Tue, 05 Dec 2023 03:06:49 GMT Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Server: APISIX/3.6.0 Content-Encoding: br Warning: Binary output can mess up your terminal. Use --output - to tell Warning: curl to output it to your terminal anyway, or consider --output Warning: FILE to save to a file.由于 Brotli 输出为二进制内容直接输出到终端会收到 curl 的警告提示建议使用curl ... --output response.br将压缩结果保存到文件后再用brotli -d解压验证内容完整性。触发压缩的判定逻辑从源码apisix/plugins/brotli.lua可以看到check_accept_encoding函数对Accept-Encoding头的完整判定逻辑请求头缺失时直接不压缩单个编码值为*或br时命中多个编码值时用正则([a-z\*])(;q)?([0-9.]*)?逐项解析只要存在br或*且其q权重不为0即q0表示客户端明确拒绝即命中。测试文件 t/plugin/brotli.t 对这部分逻辑做了全面覆盖Accept-Encoding: br、*、gzip, br、gzip, *均命中gzip、gzip, deflate不命中gzip;q0.5, br;q0.6命中而gzip;q0.5, br;q0显式禁用 br不命中gzip;q0.8, deflate, sdch;q0.6, *;q0.1中通配符权重非 0 同样命中。压缩的执行流程压缩在响应阶段分两步完成apisix/plugins/brotli.luaheader_filter 阶段依次检查 brotli 库是否加载、Accept-Encoding是否命中、上游响应是否已带Content-Encoding若上游已压缩则跳过避免双重压缩见英文文档中的 caution 提示、Content-Type是否匹配types、Content-Length是否达到min_length、HTTP 版本是否达标全部通过后创建压缩器实例清除 body-modified 标记并写入Content-Encoding: br响应头。body_filter 阶段对每个响应分块调用ctx.compressor:compress(chunk)压缩并拼接flush()结果到达流末尾eof时追加finish()输出完成整个流的收尾。测试用例 t/plugin/brotli.t 中测试用 brotli 解压器对压缩后的响应体做解压并断言解压结果长度与原始请求体一致验证了「压缩→解压」闭环的正确性TEST 30/31 则验证了上游已返回Content-Encoding: gzip的响应不会被 brotli 二次压缩符合跳过已压缩上游响应的设计。删除插件当需要禁用 brotli 插件时通过 Admin API 删除路由配置中对应的 JSON 配置即可APISIX 会自动重新加载相关配置无需重启服务curl http://127.0.0.1:9180/apisix/admin/routes/1 -H X-API-KEY: $admin_key -X PUT -d { uri: /, upstream: { type: roundrobin, nodes: { httpbin.org: 1 } } }注意上述命令用「不带plugins字段的完整路由配置」覆盖了原路由从而移除 brotli 插件。也可以将plugins置为空对象{}达到同样效果。删除后路由恢复原始透传行为响应不再携带Content-Encoding: br。补充与 gzip 插件的协同brotlipriority 996与 gzippriority 995在 config.yaml.example 中相邻配置。由于两者的压缩判定均发生在header_filter/body_filter阶段且都依赖Accept-Encoding头协商生产实践中通常二选一启用优先启用 brotli 以获取更高的压缩率尤其适合文本类响应若客户端生态不支持 brotli 再回退到 gzip。二者共用类似的types、min_length、http_version、vary属性模型学习成本可以复用。总结brotli 插件将 Nginx 静态的 brotli 压缩指令转化为 APISIX 动态可调的 JSON 属性配合 Admin API 实现按路由/全局的差异化压缩策略与秒级热更新。使用时注意三个关键点确保 brotli 共享库正确安装并能被 Lua 加载理解types、min_length、comp_level、mode、lgwin、lgblock、http_version、vary各属性与 ngx_brotli 指令的对应关系及 schema 校验约束知晓上游已压缩响应会被跳过、Content-Length缺失时不检查最小长度等边界行为。相关实现与测试可分别查阅 apisix/plugins/brotli.lua、t/plugin/brotli.t 及 conf/config.yaml.example 以深入理解。【免费下载链接】apisixThe Cloud-Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/ap/apisix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表