Squid Web Cache Wiki

Squid Web Cache 文档

🔗 Squid 的内部工作原理

🔗 哪些对象可以缓存?

互联网对象是文件、文档或对 FTP、HTTP 或 gopher 等互联网服务的查询的响应。客户端向缓存代理请求一个互联网对象;如果该对象尚未缓存,代理服务器将获取该对象(从 URL 中指定的服务器或从父级或同级缓存)并将其交付给客户端。

🔗 ICP 协议是什么?

ICP 是一种用于 Squid 缓存之间通信的协议。ICP 协议定义在两个互联网 RFC 中。RFC 2186 描述了协议本身,而 RFC 2187 描述了 ICP 在分层 Web 缓存中的应用。

ICP 主要用于缓存层级结构中,用于定位同级缓存中的特定对象。如果一个 Squid 缓存没有请求的文档,它会向其同级发送 ICP 查询,同级会以“命中”(HIT)或“未命中”(MISS)的 ICP 回复进行响应。然后,缓存会根据这些回复选择从哪个缓存来解析自己的 MISS。

ICP 还支持通过单个 TCP 连接多路复用传输多个对象流。ICP 目前基于 UDP 实现。当前版本的 Squid 也支持通过组播进行 ICP。

🔗 什么是缓存层级结构?什么是父级和同级?

缓存层级结构是一组缓存代理服务器,它们被组织成逻辑上的父/子和同级关系,以便最接近互联网网关(最接近骨干网接入点)的缓存充当远离骨干网的缓存的父级。父级缓存会解决其子级的“未命中”。换句话说,当一个缓存从其父级请求一个对象,而父级缓存中没有该对象时,父级会获取该对象,将其缓存,然后交付给子级。这确保了层级结构在骨干网传输链路上实现了最大的带宽利用率降低,有助于减轻缓存层级结构服务的网络外部的互联网信息服务器的负载,并在父级建立丰富的缓存,以便层级结构中的其他子级缓存能够获得更好的“命中”率。

除了父子关系之外,Squid 还支持同级的概念:位于同一层级结构中的缓存,用于分发缓存服务器的负载。层级结构中的每个缓存独立决定是直接从对象的源站点、父级缓存还是同级缓存获取引用,使用一个简单的解析协议。同级缓存不会为另一个同级缓存获取对象来解析缓存“未命中”。

🔗 Squid 的缓存解析算法是什么?

  1. 向所有合适的同级发送 ICP 查询
  2. 等待所有回复到达,并设置可配置的超时时间(默认为两秒)。
    • 收到第一个“命中”回复后开始获取对象,或者
    • 从第一个回复“未命中”(MISS)的父级缓存获取对象(受权重值影响),或者
    • 从源获取对象

当涉及防火墙时,该算法会更复杂一些。

可以通过 cache_peerno-query 选项来跳过 ICP 查询,如果唯一的合适来源是父级缓存(即,如果只有一个地方可以获取对象,何必费心查询?)。

🔗 Squid 的开发人员目前正在开发哪些功能?

我们正在开发的功能和领域一直在变化。请参阅 Squid Roadmap 以获取有关当前活动的更多详细信息。

🔗 详细告诉我关于互联网流量负载的信息

负载可以被描述为客户端或客户端组施加在系统上的负担。理解负载的性质对于管理系统容量很重要。

如果您对互联网流量负载感兴趣,那么 NLANR 的 网络分析活动 是一个很好的起点。

🔗 使用 NLANR 缓存系统的缓存的权衡是什么?

NLANR 的根缓存位于 NSF 超级计算机中心 (SCCs),这些中心通过 NSF 的高速骨干网服务 (vBNS) 互连。因此,NLANR 根缓存之间的缓存通信不会跨越互联网。

分层缓存的好处(即,减少网络带宽消耗、减少访问延迟和提高弹性)是有代价的。层级结构中较高的缓存必须处理其下属的未命中。如果叶子缓存的平衡命中率为 50%,则所有叶子引用的半数必须通过二级缓存进行解析,而不是直接从对象的源站点进行解析。如果这个二级缓存拥有大部分文档,这通常仍然是划算的,但如果更高层的缓存经常没有该文档,或者变得过载,那么它们实际上可能会增加访问延迟,而不是减少它。

🔗 在哪里可以找到更多关于防火墙的信息?

请参阅 防火墙 FAQ 信息站点。

🔗 “存储 LRU 过期时间”是什么意思?

例如

Storage LRU Expiration Age:      4.31 days

LRU 过期时间是一个动态计算的值。任何在指定时间内未被访问过的对象将被从缓存中移除,以便为新的、进入的对象腾出空间。换句话说,以您目前的流量水平,您的缓存将从空到满大约需要这么多天。

随着您的缓存变得越来越繁忙,LRU 过期时间会降低,以便移除更多的对象来为新对象腾出空间。理想情况下,您的缓存的 LRU 过期时间应至少为 3 天。如果 LRU 过期时间低于 3 天,那么您的缓存可能不足以处理它接收到的请求量。通过增加更多磁盘空间,您可以提高缓存命中率。

🔗 “失败率在 1.01;进入仅命中模式 5 分钟”是什么意思?

考虑一对名为 A 和 B 的缓存。可能 A 可以连接到 B,反之亦然,但 B 对互联网其余部分的连接性很差。在这种情况下,我们希望 B 能够识别它连接性差并以某种方式将这一事实传达给其邻居缓存。

Squid 将在短时间内跟踪失败到成功的请求的比例。失败的请求是指被记录为 ERR_DNS_FAIL、ERR_CONNECT_FAIL 或 ERR_READ_ERROR 的请求。当失败到成功的比例超过 1.0 时,Squid 将返回 ICP_MISS_NOFETCH 而不是 ICP_MISS 给邻居。请注意,Squid 仍会为缓存命中返回 ICP_HIT。

🔗 Squid 是否会定期重新读取其配置文件?

否,您必须向 Squid 发送 HUP 信号才能使其重新读取其配置文件,包括访问控制列表。一个简单的方法是使用 -k 命令行选项。

squid -k reconfigure

🔗 “unlinkd”是如何工作的?

unlinkd 是一个外部进程,用于解除链接未使用的缓存文件。在外部进程中执行解除链接操作会给 Squid 带来一些竞争条件问题。如果我们不小心,可能会发生以下一系列事件:

那么,问题是,我们如何保证 unlinkd 不会删除 Squid 最近分配给新对象的缓存文件?我们采取的方法是让 Squid 维护一个未使用的(但未删除!)交换文件编号堆栈。堆栈大小硬编码为 128 个条目。我们只在未使用的文件编号堆栈已满时才将解除链接请求发送给 unlinkd。因此,如果我们不得不开始解除链接文件,我们将拥有一个 128 个文件编号的池,从中选择,我们知道这些文件不会被 unlinkd 移除。

在实现方面,将解除链接请求发送到 unlinkd 进程的唯一方法是通过 storePutUnusedFileno 函数。

不幸的是,有时 Squid 无法使用 unlinkd 进程,而必须直接调用 unlink(2)。其中一种情况是当缓存交换大小超过高水位标记时。如果我们把释放的文件编号推入未使用的文件编号堆栈,而堆栈未满,那么将不会删除任何文件,实际的磁盘使用量将保持不变。因此,当我们超过高水位标记时,我们必须直接调用 unlink(2)

🔗 图标 URL 是什么?

Squid 必须做的最令人不快的事情之一是生成 Gopher 和 FTP 目录列表的 HTML 页面。出于某种奇怪的原因,人们喜欢在每个列表条目旁边放置小小的图标,以表示链接指向的对象的类型(图像、文本文件等)。

我们在源代码分发版中包含了用于此目的的一组图标。这些图标文件在运行时被 Squid 加载为缓存对象。因此,每个 Squid 缓存现在都有自己的图标用于 Gopher 和 FTP 列表。就像 Web 上可用的其他对象一样,我们使用 统一资源定位符,或URL来引用图标。

🔗 我可以让我的常规 FTP 客户端使用 Squid 缓存吗?

不行,这是不可能的。Squid 只接受 HTTP 请求。它在服务器端支持 FTP,但在客户端不支持。

非常强大的 wget 可以通过 Squid(以及可能任何其他代理缓存)下载 FTP URL。

🔗 为什么 select 循环平均时间如此之高?

有没有办法加快处理 select 的时间?Cachemgr 显示

Select loop called: 885025 times, 714.176 ms avg

这个数字不是处理文件描述符 I/O 所需的时间。我们只计算 select 被调用的次数,并将进程总运行时间除以 select 调用次数。

这意味着,平均而言,您的缓存需要 0.714 秒来检查一次所有打开的文件描述符。但这还包括 select() 在没有文件描述符 I/O 时处于等待状态的时间。我相对空闲的工作站缓存有类似的数字。

Select loop called: 336782 times, 715.938 ms avg

但我繁忙的缓存的耗时要少得多。

Select loop called: 16940436 times, 10.427 ms avg
Select loop called: 80524058 times, 10.030 ms avg
Select loop called: 10590369 times, 8.675 ms avg
Select loop called: 84319441 times, 9.578 ms avg

🔗 Squid 如何处理 Cookie?

请求中的 Cookie 标头不影响 HTTP 回复是否可以缓存。同样,回复中的 Set-Cookie 标头也不影响回复是否可以缓存。

根据 RFC 2109,正确处理 Set-Cookie 回复标头的方法是缓存整个对象,除了 Set-Cookie 标头行。

但是,我们可以过滤掉特定的 HTTP 标头。但我们是在发送端而不是接收端进行过滤。因此,Squid 确实缓存带有 Set-Cookie 标头的回复,但它会过滤掉缓存命中时的 Set-Cookie 标头本身。

🔗 Squid 如何决定何时刷新缓存的对象?

在检查对象新鲜度时,我们计算以下值:

将这些值与 refresh_pattern 规则的参数进行比较。刷新参数是:

URL 正则表达式按列出的顺序进行检查,直到找到匹配项。然后,下面描述的算法将用于确定对象是新鲜的还是过期的。

Squid-2 中使用的刷新算法如下:

  if (EXPIRES) {
      if (EXPIRES <= NOW)
          return STALE
      else
          return FRESH
  }
  if (CLIENT_MAX_AGE)
      if (OBJ_AGE > CLIENT_MAX_AGE)
          return STALE
  if (OBJ_AGE > CONF_MAX)
      return STALE
  if (OBJ_DATE > OBJ_LASTMOD) {
      if (LM_FACTOR < CONF_PERCENT)
          return FRESH
      else
          return STALE
  }
  if (OBJ_AGE <= CONF_MIN)
      return FRESH
  return STALE

🔗 “延迟读取”到底是什么意思?

cachemanager 的 I/O 页面列出了各种服务器端协议的延迟读取

有时服务器端的读取会超前于客户端的写入。特别是如果您的缓存位于高速网络上,而您的客户端以调制解调器的速度连接。Squid 会读取 read_ahead_gap 字节(默认为 16 KB) ahead of the client,然后才会开始延迟服务器端的读取。

🔗 为什么我的缓存的入站流量等于出站流量?

我一直在监测我的缓存的以太网适配器上的流量,发现了一个我无法解释的行为:入站流量等于出站流量。差异微乎其微。命中率报告为 40%。出站流量不应该至少比入站流量大 40% 吗?

作者:David J N Begley

我无法解释您所看到的精确行为,但我可以提供以下建议;每当您开始测量原始以太网或接口上的 IP 流量时,您都可以忘记让所有数字与 Squid 报告的发送/接收流量完全匹配。

为什么?

Squid 是一个应用程序——它计算发送到或从网络功能接收到的任何数据;在每一层更低的层级,都有额外的流量涉及(例如,头开销、重传和分片、不相关的广播/流量等)。Squid 永远看不到这些额外的流量,因此不计入——但如果您运行 MRTG(或任何 SNMP/RMON 测量工具)针对特定接口,所有这些额外的流量都会“神奇地出现”。

此外,请记住,一个接口对上层网络没有任何概念(因此以太网接口不会区分完全是组织内部的 IP 流量,以及与 Internet 的往返流量);这意味着,当您开始测量一个接口时,您必须先了解*您正在测量什么*,然后才能将数字与其他地方进行比较。

这是可能的(尽管绝非保证),您之所以看到大致相等的输入/输出,是因为您测量了一个既从外部世界(互联网)检索数据,*又*将其提供给最终用户(内部客户端)的接口。但这并不能完全解释,但希望它能为您提供一些可以开始应用于您自身情况的想法。

要解释任何统计数据,您必须首先了解您正在测量什么;例如,一个接口计算入站和出站字节——仅此而已。该接口不区分来自外部互联网站点或来自内部(组织内)客户端(发出请求)的入站字节。如果您想要这个,可以尝试查看 RMON2。

此外,如果您讨论的是对象请求/计数方面的 40% 命中率,那么您绝对没有理由期望流量减少 40%;毕竟,并非所有请求/对象的大小都相同,因此您可能在请求方面节省了很多,但在实际流量方面却节省很少。

🔗 为什么有些对象不被缓存?

为了确定给定的对象是否可以缓存,Squid 会考虑许多因素。当前的算法(针对 Squid-2)大致如下:

但是,如果 Squid 从同级缓存收到这些响应之一,并且所有 DateLast-ModifiedExpires 回复标头都缺失,则不会缓存它。这可以防止此类对象在同级之间永远来回传递。

302 Moved Temporarily 的回复仅当回复还包含 Expires 标头时才可缓存。

以下 HTTP 状态码会被“负面缓存”一段时间(可配置):

所有其他 HTTP 状态码均不可缓存,包括:

🔗 “保持连接比率”是什么意思?

保持连接比率显示在 server_list 缓存管理器页面上。

这是一种尝试检测可能无法处理持久连接的邻居缓存的机制。每次我们向邻居发送一个 Connection: keep-alive 请求标头时,我们都会计算邻居向我们发送 Connection: keep-alive 回复标头的次数。因此,保持连接比率是这两个计数器的比率。

如果比率保持在 0.5 以上,我们将继续假设邻居正确实现了持久连接。否则,我们将停止向该邻居发送保持连接请求标头。

🔗 Squid 的缓存替换算法是如何工作的?

Squid 使用 LRU(最少最近使用)算法来替换旧的缓存对象。这意味着最长时间未被访问的对象将首先被移除。在源代码中,每当访问对象时,StoreEntry->lastref 值都会更新。

对象不一定“按需”移除。相反,一个定期安排的事件会定期移除对象。通常,该事件每秒运行一次。

Squid 将缓存磁盘使用量保持在低水位标记和高水位标记之间。默认情况下,低标记为 90%,高标记为总配置缓存大小的 95%。当磁盘使用量接近低水位标记时,替换不那么激进(移除的对象较少)。当使用量接近高水位标记时,替换更激进(移除的对象更多)。

在选择要移除的对象时,Squid 会检查一定数量的对象,并确定哪些可以移除,哪些不能。许多因素决定了任何给定对象是否可以被移除。如果对象当前正在被请求,或正在从上游站点检索,它将不会被移除。如果对象被“负面缓存”,它将被移除。如果对象具有私有缓存密钥,它将被移除(没有理由保留它——因为密钥是私有的,后续请求永远找不到它)。最后,如果自上次访问以来经过的时间大于 LRU 阈值,则对象将被移除。

LRU 阈值是根据当前的缓存大小以及低水位和高水位标记动态计算的。LRU 阈值在高水位和低水位标记之间呈指数级缩放。当存储交换大小接近低水位标记时,LRU 阈值很大。当存储交换大小接近高水位标记时,LRU 阈值很小。阈值会自动调整以适应传入请求的速率。事实上,当您的缓存大小稳定下来时,LRU 阈值表示在当前的请求速率下,填满(或完全替换)您的缓存所需的时间。LRU 阈值的典型值是 1 到 10 天。

回到选择要移除的对象。显然,每次我们需要移除一些对象时,不可能检查缓存中的每个对象。我们每次只能检查一小部分。

每次访问对象时,它都会被移到列表的顶部。随着时间的推移,使用最少 Object 会迁移到列表的底部。在查找要移除的对象时,我们只需要检查列表中最后大约 100 个对象。不幸的是,这种方法增加了我们的内存使用量,因为它需要为每个缓存对象存储三个额外的指针。我们还使用带有 MD5 校验和的缓存密钥。

🔗 私钥和公钥是什么?

密钥指的是 Squid 用于索引缓存对象的数据库密钥。缓存中的每个对象——无论是保存在磁盘上还是正在下载——都有一个缓存密钥。我们使用 MD5 校验和作为缓存密钥。

Squid 缓存使用私有公有缓存密钥的概念。一个对象可以开始时是私有的,但后来可以更改为公有状态。私有对象只与单个客户端相关联,而公有对象可以同时发送给多个客户端。换句话说,公有对象可以被任何缓存客户端定位。私有密钥只能由一个客户端定位——请求它的那个客户端。

在接收并解析完所有 HTTP 回复标头后,对象将从私有更改为公有。在某些情况下,回复标头会指示对象不应设为公有。例如,如果使用了 private Cache-Control 指令。

🔗 Squid 是否会将数据包发送到端口 7(echo)?如果是,为什么?

可能会。这是 Harvest 缓存软件的一项旧功能。该缓存会向源服务器的 echo 端口发送 ICP “SECHO”消息。如果 SECHO 消息在任何其他 ICP 回复到达之前到达,则表示源服务器可能比任何邻居缓存都更近。在这种情况下,Harvest/Squid 会直接将请求发送到源服务器。

随着对安全性的关注日益增加,许多管理员会过滤到端口 7 的 UDP 数据包。计算机应急响应小组 (CERT) 曾发布过一份咨询意见( CA-96.01: UDP Port Denial-of-Service Attack),指出 UDP echo 和 chargen 服务可用于拒绝服务攻击。这使得管理员对任何发送到其系统端口 7 的数据包都非常紧张,并引起了他们的抱怨。

source_ping 功能已在 Squid-2 中禁用。如果您看到从 Squid 缓存(远程端口 3130)发出的到端口 7 的数据包,那么它可能是一个非常旧版本的 Squid。

🔗 “警告:来自未知名称服务器 [a.b.c.d] 的回复”是什么意思?

这意味着 Squid 向一个 IP 地址发送了 DNS 查询,但响应来自另一个 IP 地址。默认情况下,Squid 会检查地址是否匹配。如果不匹配,Squid 将忽略响应。

发生这种情况有多种原因:

如果您在警告中识别出 IP 地址是您的名称服务器主机之一,那么可能是原因(1)或(2)。

您可以通过设置以下配置选项来停止这些警告,并允许来自“未知”名称服务器的响应:

ignore_unknown_nameservers off

:warning: 警告:这会使您的 Squid 面临许多潜在的安全漏洞。您应该优先配置好您的可能名称服务器 IP 集。

🔗 Squid 如何将缓存文件分发到可用目录中?

:information_source: 此信息对于版本 2.2 是最新的。

请参阅源代码中的storeDirMapAllocate()

当 Squid 想要创建一个新的磁盘文件来存储对象时,它首先选择对象将进入哪个 cache_dir。这是通过 storeDirSelectSwapDir() 函数完成的。如果您有 N 个缓存目录,该函数会识别出其中 3N/4(75%)具有可用空间最多的目录。然后,将这些目录按可用空间最多进行排序使用。当 Squid 将一个 URL 存储到每一个 3N/4 cache_dir 后,该过程会重复,storeDirSelectSwapDir() 会找到一组新的具有可用空间最多的 3N/4 缓存目录。

选择了 cache_dir 后,下一步是查找可用的 swap 文件编号。这是通过检查 文件映射 来实现的,使用 file_map_allocate() 函数。本质上,swap 文件编号是按顺序分配的。例如,如果最后分配的编号碰巧是 1000,那么下一个将是 1000 之后第一个未被使用的编号。

🔗 为什么我会看到负的字节命中率?

字节命中率的计算方式与请求命中率略有不同。Squid 计算从服务器端读取的字节数以及写入客户端的字节数。字节命中率计算如下:

  (client_bytes - server_bytes) / client_bytes

如果 server_bytes 大于 client_bytes,您将得到一个负值。

server_bytes 可能大于 client_bytes 的原因有很多,包括:

🔗 “禁用私钥使用”是什么意思?

首先,您需要了解公钥和私钥的区别。

当 Squid 发送 ICP 查询时,它使用 ICP 的 'reqnum' 字段来保存私钥数据。换句话说,当 Squid 收到 ICP 回复时,它使用 'reqnum' 值来构建待处理对象的私有缓存密钥。

某些 ICP 实现始终将 'reqnum' 字段设置为零,然后发送回复。Squid 无法与此类邻居缓存一起使用私有缓存密钥,因为 Squid 将无法找到这些 ICP 回复的缓存密钥。因此,如果 Squid 检测到发送零 reqnum 的邻居缓存,它将禁用私有缓存密钥的使用。

没有私有缓存密钥会产生一些重要的隐私影响。两个用户可能会收到一个本应只发送给其中一个用户的响应。此响应可能包含个人机密信息。如果您希望 Squid 使用私有缓存密钥,则需要禁用“零 reqnum”邻居。

🔗 什么是半关闭的文件描述符?

TCP 允许连接处于“半关闭”状态。这是通过 shutdown(2) 系统调用实现的。在 Squid 中,这意味着客户端已关闭其连接的写入端,但仍为其读取端保持打开状态。半关闭的连接很棘手,因为 Squid 无法区分半关闭的连接和完全关闭的连接。

如果 Squid 尝试读取连接,并且 read() 返回 0,而 Squid 知道客户端尚未获取完整响应,则 Squid 会将文件描述符标记为半关闭。最可能的情况是客户端已中止请求,连接实际上已关闭。然而,客户端有可能使用了 shutdown() 调用,并且仍然可以读取响应。

要禁用半关闭的连接,只需在 squid.conf 中添加以下内容:

half_closed_clients off

然后,Squid 将始终关闭其连接端,而不是将其标记为半关闭。

:information_sourcE: 来自 Squid-3.0,默认值现在是 OFF。

🔗 为什么实际使用的文件系统空间大于 Squid 认为的?

如果比较 df 输出和 cachemgr storedir 输出,您会注意到实际磁盘使用量大于 Squid 报告的数量。这可能由于多种原因:

🔗 ‘‘positive_dns_ttl’’ 和 ‘‘negative_dns_ttl’’ 如何工作?

positive_dns_ttl 是 Squid 缓存成功 DNS 查找的时间长度。类似地,negative_dns_ttl 是 Squid 缓存失败 DNS 查找的时间长度。

positive_dns_ttl 并非总是使用。在以下情况下不使用:

假设您有以下设置:

positive_dns_ttl 1 hours
negative_dns_ttl 1 minutes

当 Squid 查询 www.squid-cache.org 这样的名称时,它会得到一个像 204.144.128.89 这样的 IP 地址。该地址会缓存一个小时。这意味着,当 Squid 再次需要知道 www.squid-cache.org 的地址时,它会在接下来的一个小时内使用缓存的答案。一小时后,缓存的信息将过期,Squid 会为 www.squid-cache.org 的地址进行新的查询。

如果您安装了 DNS TTL 补丁,或者正在使用内部查找,那么每个主机名都有自己的 TTL 值,该值由域名管理员设置。您可以在“ipcache”缓存管理器页面中看到这些值。例如:

 Hostname                      Flags lstref    TTL N
 www.squid-cache.org               C   73043  12784  1( 0)  204.144.128.89-OK
 www.ircache.net                   C   73812  10891  1( 0)   192.52.106.12-OK
 polygraph.ircache.net             C  241768 -181261  1( 0)   192.52.106.12-OK

TTL 字段显示条目将在多少秒后过期。负值表示条目已过期,将在下次使用时刷新。

negative_dns_ttl 指令指定缓存失败 DNS 查找的时间长度。当 Squid 无法解析主机名时,您可以肯定这是一个真正的失败,并且您不太可能在短时间内获得成功的答案。Squid 会重试多次查找,然后才声明查找失败。如果您愿意,可以将 negative_dns_ttl 设置为零。

🔗 “swapin MD5 匹配错误”是什么意思?

这意味着 Squid 打开了一个磁盘文件来提供缓存命中,但发现存储的对象与用户的请求不匹配。Squid 在每个磁盘文件的开头存储 URL 的 MD5 摘要。当文件被打开时,Squid 检查磁盘文件的 MD5 是否与用户请求的 URL 的 MD5 匹配。如果不匹配,则会打印警告,并且 Squid 会将请求转发给源服务器。

您无需担心此警告。这意味着 Squid 正在自动从缓存目录损坏中恢复。

🔗 “无法解压 swapfile 元数据”是什么意思?

Squid 的每个磁盘缓存文件开头都有一个元数据部分。此标题用于存储 URL MD5、一些 StoreEntry 数据等。当 Squid 打开磁盘文件进行读取时,它会查找元数据标题并解压它。

此警告意味着 Squid 无法解压元数据。这是一个非致命的 bug,Squid 可以从中恢复。元数据可能只是丢失了,或者文件可能已损坏。

您无需担心此警告。这意味着 Squid 正在二次检查磁盘文件是否与 Squid 认为应该存在的内容匹配,但检查失败了。Squid 会在这种情况下恢复并生成缓存未命中。

🔗 为什么 Squid 在拦截模式下不进行“ident”查找?

这是拦截代理工作方式的一个副作用。

当 Squid 配置为拦截代理时,操作系统会假装它是源服务器。这意味着被拦截的 TCP 连接的“本地”套接字地址实际上是源服务器的 IP 地址。如果您在拦截代理上运行 netstat -n,您将在 Local Address 列中看到许多外部 IP 地址。

当 Squid 需要进行 ident 查询时,它会创建一个新的 TCP 套接字,并将本地端点 绑定 到与客户端 TCP 连接的本地端点相同的 IP 地址。由于本地地址实际上不是本地的(它是某个遥远的源服务器的 IP 地址),因此 bind() 系统调用会失败。Squid 将此视为 ident 查找失败。

那么,为什么要在这种情况下进行绑定呢?如果您知道您正在进行拦截代理,那么为什么不将本地端点绑定到主机(内网)的 IP 地址呢?为什么要让这么多人无谓地受苦?

因为 ident 的工作方式就是如此。请阅读 RFC 931,特别是“限制”部分。

🔗 什么是 FTP 被动连接?

作者:Colin Campbell

FTP 使用两个数据流,一个用于传递命令,另一个用于传输数据。命令通道由监听端口 21 的 ftpd 处理。

数据通道取决于您是否请求被动 FTP。当您在非被动环境中请求数据时,您的客户端会告诉服务器:“我正在监听 <IP 地址> <端口>。”然后服务器从端口 20 连接到客户端指定的 IP 地址和端口。这要求您的“安全设备”允许任何来自端口 20 的外部主机连接到内部任何大于 1023 的端口。这有点像一个漏洞。

在被动模式下,当您请求数据传输时,服务器会告诉客户端:“我正在监听 <IP 地址> <端口>。”然后您的客户端连接到服务器上的该 IP 和端口,数据即可流动。

🔗 Squid 何时会重新转发客户端请求?

当 Squid 将 HTTP 请求转发到下一跳(可能是 cache_peer 或源服务器)时,可能会出现问题。在某些情况下,Squid 会决定重新转发请求。本节记录了相关的 Squid 决策逻辑。{花括号} 中的注释旨在帮助开发人员将这些注释与 Squid 源代码相关联。非开发人员应忽略这些注释。

:warning: Squid 使用两种略有不同的方法来做出重新转发决策:{FwdState::checkRetry}{FwdState::reforward}。不幸的是,在许多不同的情况下,至少有一种方法可能会被调用,并且方法决策可能受调用顺序(即事务状态)的影响。下面记录的逻辑在某些极端情况下与实际情况不符。如果您发现与您关心的实际用例存在严重差异,请提交文档错误报告。

如果至少满足以下任一条件,Squid 不会尝试重新转发请求:

在其他情况下,Squid 会尝试重新转发请求。如果失败是由持久连接竞争引起的,Squid 将使用相同的目标地址重试。否则,Squid 将转到备选目的地列表中的下一个源服务器或对等地址。

请注意,本节仅涵盖 *转发* 重试。事务可能在 Squid 尝试转发请求之前(例如,HTTP 请求本身可能格式错误或被 Squid 拒绝)或在 Squid 完成接收响应之后(例如,响应可能被 Squid 拒绝)失败。

此分析主要基于 {FwdState::checkRetry}{FwdState::reforward} 以及相关的转发源代码。本文档基于截至 2013-08-29 的 Squid 版本。此后逻辑可能已发生变化。

回到 FAQ 索引

导航: 网站搜索网站页面分类🔼 向上