🔗 特性:负载均衡
- 目标:负载均衡源服务器或对等节点。
- 版本: 2.6
🔗 愿望清单
Squid 作为负载均衡器的支持已基本实现,但一些功能集成不佳或缺失。
- 现在可以使用 ACL 进行父节点选择。
- 目前可以使用客户端 IP 地址进行会话亲和性设置。要通过 cookie 实现此功能,现在由后端应用程序负责设置该 cookie。如果能有一个外部认证器负责此功能就好了。
- Squid 会对所有发送到对等节点的流量进行统计。如果能有一种或两种基于字节的均衡算法就更好了。
🔗 整体对等节点选择逻辑
要转发请求,Squid 会构建一个要尝试的唯一目标列表。这些目标可能包括对等节点(cache_peer)和源服务器。目标按添加到列表的顺序使用。通常,列表中的第一个目标会处理请求,但各种失败可能会导致需要联系其他目标。本节将描述目标列表是如何构建的。
本节目前假设**没有**固定的连接、ICP/HTCP 查询、netdb 数据库和 Cache Digests 需要处理。如果您的 Squid 使用了这些功能,目标列表可能**开始**时是由本节未列出的算法选择的对等节点!欢迎提供涵盖这些重要用例的附加文档。
首先,Squid 决定是直接连接,还是从以下四种可能的答案中选择:
- 直接连接。
- 通过对等节点连接。
- 优先直接连接(但需要时通过对等节点连接)。
- 优先通过对等节点连接(但需要时直接连接)。
这个直接连接或使用对等节点连接的决定是基于 always_direct、never_direct 以及各种事务属性/限制的组合。如果这些初步检查没有定论,Squid 会使用 prefer_direct 来从最后两种可能选项(优先直接连接或优先对等节点连接)中进行选择。这个决定会影响到哪些对等节点选择算法被用来将目标添加到列表中,详情如下。
🔗 直接连接
如果 Squid 决定直接连接,它会将源服务器添加到目标列表。
🔗 通过对等节点连接
如果 Squid 决定与其他代理进行对等连接,它会通过以下三个步骤构建目标列表:
- 添加要使用的“最佳”对等节点(如果有)。
- 添加所有活动的父节点(如果有)。
- 添加默认父节点(如果有)。
第 1 步中的“最佳”对等节点是通过以下有序的对等节点选择算法序列找到的第一个对等节点:
- 源 IP 哈希
- 用户名哈希
- CARP
- 轮询
- 加权轮询
- 首次上线父节点
- 默认父节点
第 1 步序列末尾的默认父节点算法与第 3 步执行的算法相同,但第 1 步的默认父节点可能永远没有机会运行,如果另一个第 1 步算法找到了“最佳”对等节点……
上述每种对等节点选择算法(包括第 2 步中的所有活动的父节点)在添加到目标列表之前,都会将每个候选对等节点与以下**排除**条件进行检查:
- 对等节点为 originserver 类型,且请求是针对非对等节点端口的 CONNECT 请求。
- cache_peer_access 拒绝访问该对等节点。
满足上述任一排除条件的对等节点将不会被添加到目标列表中。
🔗 优先直接连接
Squid 通过以下两个步骤构建目标列表:
- 将源服务器添加到目标列表。
- 如果请求是“分层”的,或者 nonhierarchical_direct 为关闭状态,则 Squid 会遵循“通过对等节点连接”子节中描述的三个步骤。否则,此步骤不执行任何操作。
🔗 优先对等节点连接
Squid 通过以下两个步骤构建目标列表:
- 如果请求是“分层”的,或者 nonhierarchical_direct 为关闭状态,则 Squid 会遵循“通过对等节点连接”子节中描述的三个步骤。否则,此步骤不执行任何操作。
- 将源服务器添加到目标列表。
🔗 对等节点选择算法
在构建对等节点层级结构以实现负载均衡、高性能或高可用性/容错分层时,Squid 提供了多种算法。
以下算法按优先级顺序列出。Squid 将依次尝试使用每种算法查找可用对等节点。如果某种算法没有配置任何可用对等节点,它将跳到下一个。
在未配置任何内容的情况下,选择的对等节点将是:
- 首先是响应的 ICP 兄弟节点,然后是**默认**的**首次上线**父节点,最后是**默认**的 cache_peer。
🔗 HTCP:超文本缓存协议
| 日志代码 | UDP_*, SIBLING_HIT, PARENT_HIT | |
| 选项 | no-query | 禁用与此对等节点的 HTCP 查询。 |
| htcp | 启用与此对等节点的 HTCP 查询(而不是 ICP)。 | |
| htcp= | 启用与此对等节点的 HTCP 查询(而不是 ICP)。 |
这是一种基于 UDP 的获取-响应协议,用于发现**兄弟**节点是否已存储相同 URL 的对象。有关此协议的详细信息,请参阅 RFC 2756。
此协议会发送完整的 HTTP 标头到对等节点以进行响应决策。应尽可能优先于 ICP 选择,但可能会产生较大的后台流量开销。
🔗 ICP:Internet 缓存协议
| 日志代码 | UDP_*, SIBLING_HIT, PARENT_HIT | |
| 选项 | no-query | 禁用与此对等节点的 ICP 查询。 |
这是一种基于 UDP 的获取-响应协议,用于发现**兄弟**节点是否已存储相同 URL 的对象。有关此协议的详细信息,请参阅 RFC 2186。
由于仅请求 URL,它存在一些限制。现代 HTTP 的“变体”概念未被包含(一个 URL 具有压缩变体、deflate 变体、sdch 变体、纯文本变体等)。许多网站还根据访问者详细信息提供许多变体。因此,在现代万维网中存在误报和次优路由选择的风险。请参阅下面的 HTCP 以获得解决方案。
🔗 默认父节点
| 日志条目 | DEFAULT_PARENT |
| 选项 | default |
如果一个对等节点被标记为*默认*,它将始终被考虑作为备用源。但是,如果它处于 DEAD 状态或被 ACL 要求阻止,它可能会被跳过。只能有一个对等节点被标记为默认。
尽管自 squid-2.6 以来文档一直如此说明;但在 3.1.15 之前的 squid 版本中,默认父节点实际上将优先于所有其他选择算法。这在 3.1.15 中已得到纠正,使默认成为最后手段选择,符合文档说明。
🔗 源 IP 哈希
| 日志条目 | SOURCEHASH_PARENT | |
| 选项 | sourcehash | 对该对等节点使用基于 IP 的哈希算法。 |
标记为*sourcehash*的对等节点被分组,并使用哈希值基于 IP 地址进行负载均衡,从而确保每个用户始终通过同一对等节点连接。
这与*userhash*几乎相同,当无法登录时可以使用此版本。
🔗 用户名哈希
| 日志条目 | USERHASH_PARENT | |
| 选项 | userhash | 对该对等节点使用基于登录的哈希算法。 |
标记为*userhash*的对等节点被分组,并使用哈希值基于登录用户名进行负载均衡,从而确保每个用户始终通过同一对等节点连接。当对等节点变得不可用或恢复可用时,存在一定的灵活性,哈希值会进行调整以应对变化。
此算法主要用于在集群或层级结构中创建可预测的路径。对于 ISP 集群来说尤其有用,这些集群必须处理像Hotmail这样将 IP 和用户登录与会话绑定的网站。这些会话在通过常规的 HTTP 无状态集群(它们为了负载均衡而分割事务流)时会中断。
在 3.1.15 之前的 Squid 版本中,其优先级高于源 IP 哈希。它们是互斥算法,因此这不应该成为问题。
🔗 CARP:缓存数组路由协议
| 日志条目 | CARP | |
| 选项 | carp | 对该对等节点使用 CARP 哈希算法。 |
标记为 CARP 的对等节点被分组,并使用哈希值对 URL 进行负载均衡,从而确保每个 URL 始终发送到同一对等节点。当对等节点变得不可用或恢复可用时,哈希值会进行调整以应对变化。
此算法是缓存集群中对象去重和多实例 Squid-3.1 及更早版本负载均衡的首选方法之一(在 Squid-3.2 中,SMP 支持已取代了此目的)。高效的替代方案是多播 ICP 或 HTCP。
🔗 轮询
| 日志条目 | ROUNDROBIN_PARENT | |
| 选项 | weight=N | 在每个周期中,将连接不均衡地分配给该对等节点 N 次。 |
| basetime=T | 微调 RTT 距离偏差。 |
经典的负载分配算法。它像一个圆圈一样,选择第一个对等节点,然后是第二个,然后是第三个,依此类推,直到所有对等节点都被使用,然后再次选择第一个并重复该序列。可以使用*weight=*选项进行修改以不均衡分配连接。
有一些基本细节需要注意,下面由*Grant Taylor*概述。
理论上,是的。它会在对等节点之间交替,从而假设性地使连接上的负载均衡。
🔗 偏差:基于连接
最明显的偏差是,它**不**考虑给定连接的流量类型、连接时长和活跃度。
假设我有以下(新)连接,顺序如下:
- 简单的 HEAD 请求。
- 内核源码的 HTTP 下载。
- 简单的图像 GET 请求,立即关闭。
- CONNECT 隧道。
您会发现连接 #1 和 #3 被发送到对等节点 A,而连接 #2 和 #4 被发送到对等节点 B。因此,您最终会得到两个非常*轻量*的连接在对等节点 A 上,而两个*非常重*的连接在对等节点 B 上。
连接最终被“负载均衡”(可以这么说),或者“分布式”(可能是一个更好的描述方式)到多个对等节点上。然而,如果您查看这两个连接的利用率或它们所代表的物理连接,您会发现一个被严重低估,而另一个可能已经饱和。
因此,您确实实现了连接的分布,但不一定实现了负载均衡。
🔗 加权轮询
| 日志条目 | ROUNDROBIN_PARENT | |
| 选项 | weight=N | 在每个周期中,将连接不均衡地分配给该对等节点 N 次。 |
| basetime=T | 微调 RTT 距离偏差。 |
对经典*轮询*算法的简单改编。这种算法使用对每个对等节点的 TCP 延迟(RTT 延迟)的测量来修改每个对等节点的权重。
经典的负载分配算法。它像一个圆圈一样,选择第一个对等节点,然后是第二个,然后是第三个,依此类推,直到所有对等节点都被使用,然后再次选择第一个并重复该序列。可以使用*weight=*选项进行修改以不均衡分配连接,这在 RTT 权重之外。
它最适用于 ISP 或 CDN 中的负载均衡,因为这些场景下的对等节点通常是远程的,且 RTT 较大。当对等节点非常近或在具有极低延迟的高速链路上可用时(例如典型的反向代理或小型 CDN),RTT 加权几乎无用。
在高对等节点网络上有一个潜在的好处。可以及早检测到对等节点过载。当过载时,Squid 对等节点会停止快速响应。在连接开始完全丢弃或超时(过)严重之前,延迟加权可以减少到该对等节点的负载。
考虑对等节点 A 的 RTT 响应为 5ms,而邻近网络的对等节点 B 的 RTT 为 10ms。这意味着使用对等节点 A 的偏差为 1:2。
如果您想减小或增大此偏差,可以通过在 cache_peer 上配置*basetime=T*选项来实现。它获取要从 RTT 中减去的毫秒数,然后再进行计算。
不要忘记 basetime=T 是一个固定值,并且 RTT 延迟可能因网络条件而异。因此,这只是一个偏差,而不是解决距离问题的“修复”。
🔗 首次上线父节点
| 日志条目 | FIRST_UP_PARENT |
| 选项 | (无) |
选择 squid.conf 中列出的第一个被标记为 ALIVE(存活)且可用的 cache_peer **父节点**条目。
此算法是**父节点**对等节点使用的默认算法。目前没有明确的配置选项来启用/禁用它。
导航:站点搜索,站点页面,类别,🔼 向上