在 Squid 5.8 和 6.6 中,我们注意到意外的行为:有时调用外部 acl 帮助程序时不带参数(或空参数)。在繁忙的时候,这种情况每秒发生一到两次,在安静的时候,可能每 15 分钟发生一次,或者根本不发生。
ACL的配置如下:
external_acl_type DynProxy ttl=60 negative_ttl=60 ipv4 %DST %SRC /path/proxy_acl.php
这按预期工作。但是,偶尔会出现空请求(从 STDIN 读取的是空字符串)。根据文档,帮助程序回复“BH 消息=缺少参数”。 Squid 将此响应记录为
ERROR: helperHandleRead: unexpected read from external_acl_type #Hlpr8, 29 bytes 'BH message=missing arguments
在源代码中,这条语句有注释“有人在没有被说话的情况下说话”,这里似乎并不完全是这样,因为辅助程序的结构是:
function run() {
while (!feof(STDIN)) {
$input = trim(fgets(STDIN));
$args = explode(' ', $input);
if (count($args) < 2) {
$output = "BH message=missing arguments\n";
} else {
// ... do something
}
fwrite(STDOUT, $output);
}
}
我们搜索了日志文件,并在调用的同一秒内看到以下几行,但不确定这是否相关:
2024/01/02 12:37:31.306 kid1| 5,3| Read.cc(148) HandleRead: FD 72, size 32767, retval 29, errno 0
2024/01/02 12:37:31.306 kid1| 5,3| IoCallback.cc(112) finish: called for conn171338 local=[::] remote=[::] FD 72 flags=1 (0, 0)
造成此类空请求的原因是什么?默默地忽略这些请求而不是回复它们是否安全? 在 Squid 运行多年没有出现任何问题后,我们开始遇到可靠性问题。日志文件没有表明任何问题,但运行几天或几周后,连接突然无法建立,直到重新启动。所以我们在这里,调查我们能想到的所有可能的原因。
交叉发布到 https://bugs.squid-cache.org/show_bug.cgi?id=5340 找到了这个问题的答案。显然 PHP 在从 stdin 读取时超时(默认情况下为 60 秒)。
fgets(STDIN)
的结果将是 false
,有关错误的更多详细信息可通过调用 stream_get_meta_data
获得。
Squid 的最新版本处理意外响应的方式与以前不同,会终止辅助进程。因此,超时很可能一直存在,但可能在最近的更新后开始导致性能问题(如果这是根本原因)。