升级到Varnish 7.0

PCRE2

从PCRE到PCRE2的迁移导致了许多变化,首先是构建依赖关系的变化。有关各种平台上的包依赖关系,请参阅当前的安装说明。

以前,如果正则表达式的实时(JIT)编译在构建期间存在,则始终在运行时启用它。从现在开始,默认情况下启用jit编译,但可以使用 --disable-pcre2-jit 配置选项。一旦启用,只会尝试JIT编译,并且会忽略失败,因为它们不是必需的。

新的 varnishd 参数 pcre2_jit_compilation 控制如果在配置时禁用了JIT支持,是否应尝试JIT编译并且不起作用。

看见 pcre2_jit_compilation

以前的参数 pcre_match_limitpcre_match_limit_recursion 已重命名为 pcre2_match_limitpcre2_depth_limit 。对于较旧的PCRE2库,可能会看到深度限制在错误消息中被称为递归限制。

看见 pcre2_depth_limitpcre2_depth_limit 以获取更多信息。

正则表达式的语法应该是相同的,但可能会遇到细微的差异。我们知道一个这样的区别,PCRE2无法编译未知的转义序列。例如,PCRE解释 "\T" AS "T" 并忽略转义字符,但PCRE2将其视为语法错误。解决方案是简单地使用 "T" 一般情况下,删除所有虚假转义字符。

而PCRE2可以捕获命名组并具有自己的替换语法,其中捕获的组可以通过位置引用 $<n> 甚至连名字都没有。VCL的替换语法 regsub() 保持不变,且捕获的组仍需要 \<n> 语法WHERE \1 指的是第一组。

出于这个原因,不应该要求对现有的VCL、BAN表达式、VSL查询或使用Varnish中的正则表达式的任何东西进行更改,除非PCRE2似乎更严格,并且拒绝无效的转义序列。

VMOD作者操纵 VCL_REGEX 如果参数仅使用VRT API,则它们不应受此迁移的影响。然而,底层的VRE API发生了很大的变化,允许VRE的新版本涵盖所有Varnish用例,从而 libvarnish 是现在唯一的二进制链接 directlylibpcre2-8

迁移意味着保留在过时的永久存储中的禁令不再兼容,应该从头重新构建新的过时的永久存储。

结构化字段号

VCL类型INTEGER和REAL现在分别映射到结构化字段整数和十进制数。VCL编译器不再接受结构化字段边界之外的数字,并且vmod_std的各种转换函数将无法处理超出边界的数字。

例如,不再支持科学记数法 12.34e+3 必须拼写为 12340 取而代之的是。

内存占用

为了降低多次刷新单个任务的日志的可能性, vsl_buffer 增加到16kb。这通常会带来更好的性能,比如 varnishlogvarnishncsa 除.外 raw 分组。

为了适应额外的工作空间消耗,并在其上增加更多净空空间, workspace_clientworkspace_backend 默认情况下,两者都增加到96kB。

PCRE2 jit编译器生成的代码消耗更多堆栈,因此 thread_pool_stack 增加到80kB,在32位系统上增加到64kB。

如果您依赖缺省值,这将导致虚拟内存消耗增加,与正在处理的并发客户端请求和后端获取的数量成比例。此内存不在可以应用的存储限制中。

为了解决使用HTTP/2可能出现的行首阻塞情况,请求正文现在在HTTP/2会话(流0)和客户端请求之间进行缓冲。它在存储上分配,由 h2_rxbuf_storage 参数,并且是对客户端请求和也在存储上分配的后端获取之间的现有缓冲的补充。新的缓冲区大小取决于 h2_initial_window_size 其具有新的缺省值65535B,以避免具有负窗口的流。

范围请求

对于范围请求,Varnish仅支持字节单位,并且始终被剥离 Accept-Range 来自后端的标头。对于PASS交易来说,情况不再是这样。

要找出是否有 Accept-Range 标头来自后端, obj.uncacheable 在……里面 vcl_deliver 指示这是否为PASS事务。

什么时候 http_range_support 打开时,会添加一致性检查,以确保后端不会充当坏网关。如果一个意外的 Content-Range 收到标头,或者如果它与客户端的不匹配 Range 标头,则会被视为错误,并生成503响应。

如果您的后端添加了虚假内容 Content-Range 您可以评估的标头可以安全地忽略,您可以修改VCL中的响应::

sub vcl_backend_response {
    if (!bereq.http.range) {
        unset beresp.http.content-range;
    }
}

一致性检查失败时,会记录一个错误以及遇到的特定范围问题。

ACL

这个 acl VCL中的关键字现在支持位标志:

  • log

  • pedantic (默认情况下启用)

  • table

全局参数 vcc_acl_pedantic (默认情况下关闭)已删除,因此现在默认情况下,ACL是迂回的。待办事项:参考手册。

默认情况下,它们也是静默的,以下ACL声明是等效的:

acl <name> { ... }
acl <name> -log +pedantic -table { ... }

这意味着与ACL匹配的条目不再记录为 VCL_acl 默认情况下。

要恢复以前的默认行为,请按如下方式声明您的ACL::

acl <name> +log -pedantic { ... }

默认情况下,ACL针对运行时性能进行了优化,这可能会显著增加非常大的ACL的VCL编译时间。这个 table 标志以牺牲运行时性能为代价来改进编译时间。

看见 访问控制列表(ACL)

对开发人员的更改

建房

从源代码构建需要Autoconf 2.69或更高版本,Automake 1.13或更高版本。在从发布存档构建时,这两者都不需要,因为它们已经是自举的。

有一种新的 --enable-workspace-emulator 配置标志以将常规的“压缩分配”工作区替换为“稀疏分配”替代方案。与地址消毒器相结合,它可以帮助VMOD作者发现内存处理问题,如缓冲区溢出,否则常规工作区可能会忽略这些问题。

vdef.h

这个 vdef.h 标头不再是自包含的,它包括 stddef.h

由于它是使用Varnish绑定时应包括的第一个标头,因此将一些定义提升为 vdef.h

  • 美国政府的后备力量 __has_feature() 缺少宏的情况下

  • 用于结构化字段数量限制的VRT宏

  • struct txt 及其配套的宏(这些宏需要 vas.h 也是如此)

此标头隐式包含在 vrt.hcache.h 并且不应该关注VMOD作者。

工作区API

不推荐使用的函数 WS_Front()WS_Inside() 都消失了,取而代之的是 WS_Reservation()WS_Allocated() 。出于这个原因, WS_Assert_Allocated() 尽管没有被弃用,但还是被删除了,因为它在 assert(WS_Allocated(...)) 。访问工作区前端指针只有在预订期间才有意义,这就是为什么 WS_Front() 在以前的版本中已弃用。

应该不再需要它才能访问 struct ws 字段,所有事情都应该通过 WS_*() 功能。当工作空间模拟器被启用时,它甚至成为强制性的, struct ws 字段具有不同的语义。

STRING_LIST

VMOD作者不能再 STRING_LIST 函数或对象方法中的参数。要处理字符串片段,请使用 VCL_STRANDS 取而代之的是。

结果,以下符号消失了:

  • VRT_String()

  • VRT_StringList()

  • VRT_CollectString()

  • vrt_magic_string_end

过去需要使用 STRING_LIST in the form of a prototype ending with const char *, ... 现在拿着 const char *, VCL_STRANDS

  • VRT_l_client_identity()

  • VRT_l_req_method()

  • VRT_l_req_url()

  • VRT_l_req_proto()

  • VRT_l_bereq_method()

  • VRT_l_bereq_url()

  • VRT_l_bereq_proto()

  • VRT_l_beresp_body()

  • VRT_l_beresp_proto()

  • VRT_l_beresp_reason()

  • VRT_l_beresp_storage_hint()

  • VRT_l_beresp_filters()

  • VRT_l_resp_body()

  • VRT_l_resp_proto()

  • VRT_l_resp_reason()

  • VRT_l_resp_filters()

这个 VRT_SetHdr() 函数还用于获取 STRING_LIST 现在需要一名 const char *, VCL_STRANDS 也是。但是,除了这一变化之外,它也不再接受特殊的 vrt_magic_string_unset 争论。

取而代之的是一个新的 VRT_UnsetHdr() 添加了功能。

这个 VRT_CollectStrands() 函数已重命名为 VRT_STRANDS_string() ,这是它最初的原意名称。

空哨兵

两个便民哨兵 vrt_null_strandsvrt_null_blob 都是为了避免 NULL 用法。 VRT_blob() 退货 vrt_null_blob 当源为空或长度为零时。空Blob的类型为 VRT_NULL_BLOB_TYPE

利布瓦尼沙皮

不推荐使用的函数 VSB_new()VSB_delete() 都被移除了。使用 VSB_init()VSB_fini() 对于静态缓冲区和 VSB_new_auto()VSB_destroy() 用于动态缓冲区。

它们的删除导致libvarnishapi的soname增加到3.0.0。

唇彩Varnish

对libVarnish进行了其他更改,这些更改仅对VMOD作者可用,因为它们不会被libvarnishapi公开。

VNUM

这个 VNUMpfx() 函数被替换为 SF_Parse_Number() 它同时解析RFC8941中的小数和整数。此外,还有新的 SF_Parse_Decimal()SF_Parse_Integer() 功能更加专业化。

VNUM_bytes_unit() 返回一个整数,不再分析派系字节。

新的令牌解析器 VNUM_uint()VNUM_hex() 都被添加了。

其他VNUM函数依赖于新的SF函数进行解析,具有相同的限制。

以下宏定义了结构化字段的编号界限:

  • VRT_INTEGER_MIN

  • VRT_INTEGER_MAX

  • VRT_DECIMAL_MIN

  • VRT_DECIMAL_MAX

VRE

在为PCRE2迁移做准备的过程中,VRE API发生了彻底的变化,以便通过VRE将Varnish源代码中的所有PCRE使用情况整合在一起。

与重命名参数的方式类似, match_recursion 字段自 struct vre_limits 已重命名为 depth 。在其他方面,它具有相同的意义和目的。

值得注意的突破性变化:

  • VRE_compile() 签名已更改

  • VRE_exec() 已被取代:- VRE_match() 做简单的匹配- VRE_capture() 捕获 txt 阵列- VRE_sub() 用VSB中的替换项替换匹配项

  • VRE_error() 打印VSB中上述所有函数的错误消息

  • VRE_export() 包装一个可用的 vre_t 可以作为字节流持久化的

导出的正则表达式采用给定大小的字节流的形式,各种匹配函数可以按原样使用该字节流。应注意始终保持导出的 vre_t

这个 VRE_ERROR_NOMATCH 符号现在被硬链接,就像 VRE_CASELESS ,以及 VRE_NOTEMPTY 不再受支持。在VRE外观中没有留下匹配选项,但 VRE_match()VRE_capture()VRE_sub() 函数仍然需要一个 options 参数以保持将来允许匹配选项的能力。

这个 VRE_ERROR_LEN 给出一个应该是安全的大小,以避免在静态缓冲区中出现截断的错误消息。

从通过提供的正则表达式获得对PCRE2功能的完全访问权限 vre_t 特定于后端的 vre_pcre2.h 包含一个 VRE_unpack() 功能。例如,这会打开通往 pcre2_substitute() 使用PCRE2替换语法和命名捕获组作为VCL的替代 regsub() 支持的语法 VRE_sub()

理想情况下, vre_pcre2.h 将是下一次我们转向不同的正则表达式引擎时唯一的突破性更改。希望不会太快。

eof