Addo Zhang
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 开源 Katran:一种可扩展的网络负载均衡器 > Katran 创造了一种基于软件的负载均衡解决方案,它重新设计了数据转发平面,利用了最近内核工程中的创新。 全球数十亿人使用 Facebook 的服务,我们的基础设施工程师创造了一系列系统,优化了网络流量,为每个人提供了快速可靠的访问方式。今天,我们开源了这项工作的一部分,发布了 [Katran 转发平面软件库](https://github.com/facebookincubator/katran),该库驱动 Facebook 基础设施中使用的网络负载均衡器。Katran 提供了一种基于软件的负载均衡解决方案,完全重新设计了转发平面,充分利用了最近内核工程中的两项创新:快速数据路径(XDP)和 eBPF 虚拟机。Katran 目前在 Facebook 的服务点(PoPs)的后端服务器上部署,它帮助我们提高了网络负载均衡的性能和可扩展性,减少了如在没有传入包时的繁忙循环等效率低下的问题。我们将其分享给开源社区,希望其他人可以提高他们负载均衡器的性能,并把 Katran 作为未来工作的基础。 ### 在 Facebook 规模上处理请求的挑战 为了管理 Facebook 规模的流量,我们部署了一个分布全球的服务点网络,作为我们数据中心的代理。鉴于请求量极高,服务点和数据中心都面临着如何让大量的(后端)服务器对外界呈现为一个单一虚拟单元,以及如何在这些后端服务器之间有效分配工作负载的挑战。 这些挑战通常是通过在每个位置公布一个虚拟 IP 地址(VIP)来解决的。然后,目标为 VIP 的数据包被无缝地分发到后端服务器中。然而,分发算法需要考虑到后端服务器通常在应用层操作并终止 TCP 连接的事实。这个任务由网络负载均衡器(通常被称为 4 层负载均衡器或 L4LB,因为它操作数据包而不是处理应用级请求)来处理。图 1 说明了 L4LB 与其他网络组件的关系。 ![](https://hackmd.io/_uploads/SJBL-R0Sh.png) * 图 1: 网络负载均衡器在多个后端服务器前面,后端服务器运行后端应用,将每个客户端连接的所有数据包一致性地发送到一个特定的后端服务器。 ### 高性能负载均衡器的需求 L4LB 的性能对于管理延迟和扩展后端服务器的数量至关重要,因为 L4LB 位于需要处理每个传入数据包的路径上。性能通常以 L4LB 可处理的峰值数据包数(pps)来衡量。传统上,工程师更倾向于使用硬件解决方案,因为它们通常使用如特殊应用集成电路(ASIC)或现场可编程门阵列(FPGA)等加速器来减轻主 CPU 的负担。然而,以硬件为中心的方法的一个缺点是,它限制了系统的灵活性。要有效地服务 Facebook 的需求,网络负载均衡器必须: - **在通用 Linux 服务器上运行。** 这让我们可以在现有大量的部署服务器上部分或全部运行负载均衡器。基于软件的负载均衡器满足了这个标准。 - **与服务器上的其他服务共存。** 这就消除了运行专门的负载均衡器的服务器的需要,从而提高了容错能力。 - **允许低中断维护。** Facebook 的软件必须能够快速地演进,以支持新的或改进的产品和服务。负载均衡器和后端层的维护和升级是常态,而不是例外。在这些事件中最小化中断可以让我们更快地迭代。 - **提供简单的检测和调试。** 所有大型分布式基础设施都必须应对异常和意外事件,所以减少调试和排查问题的时间非常重要。负载均衡器需要可检测,对像 tcpdump 这样的标准工具友好。 为了解决这些需求,我们设计了一个高性能的软件网络负载均衡器。我们的第一代 L4LB 基于 IPVS 内核模块,服务于 Facebook 超过四年。然而,它在与其他服务共存的目标上有所不足,特别是后端。在第二次迭代中,我们利用了快速数据路径(XDP)框架和新的 BPF 虚拟机(eBPF)在大量机器上运行软件负载均衡器和后端。图 2 展示了两代间的主要区别。 ![](https://hackmd.io/_uploads/r1OiWRAS2.png) * 图 2:两代L4LB 之间的区别。注意,两者都是运行在后端服务器上的软件负载均衡器。Katran(右)允许我们将负载均衡器和后端应用程序一起部署,从而增加负载均衡器的容量。 ### 我们的第一代 L4LB:基于 OSS 软件构建 对于我们的第一代 L4LB,我们大量依赖现有的开源组件来实现大部分功能。这种方法帮助我们在几个月内就在大型部署中替换了硬件解决方案。设计有四个主要组件: - **VIP 宣告:** 这个组件简单地向世界宣告 L4LB 负责的虚拟 IP 地址,通过与 L4LB 前面的网络组件(通常是一个交换机)进行对等。然后,交换机使用等价多路径(ECMP)机制将数据包分配到宣告 VIP 的 L4LB 中。我们使用 [ExaBGP](https://l.facebook.com/l.php?u=https%3A%2F%2Fgithub.com%2FExa-Networks%2Fexabgp%2Fwiki&h=ATNk25DSMdvOPMdj8QHrw4VT2HEgMNHizYGHV_kKTIVTBS0c-V8b1bvScts3S8ifFMuCteYyRI_AFP_1XrLTVj_QgKCDDsdpj-_pbyAsyDy-xjRLSJdVEsHEga4uyOSaxFLjgcY-0BhuMdWwVbz7rg) 进行 VIP 宣告,因为它轻量级且设计灵活。 - **后端服务器选择:** 为了将来自客户端的所有数据包发送到同一个后端,L4LB 使用一个依赖于传入数据包的 5 元组(源地址,源端口,目的地址,目的端口和协议)的一致性哈希。使用一致性哈希确保所有属于一个传输连接的数据包都发送到同一个后端,无论接收数据包的 L4LB 是哪一个。这消除了在多个 L4LB 之间同步状态的需要。当后端离开或加入后端池时,一致性哈希也保证了现有连接的最小中断。 - **转发平面:** 一旦 L4LB 选择了合适的后端,需要将数据包转发到该主机。为了避免像保持 L4LB 和后端主机在同一 L2 域这样的限制,我们使用一个简单的 IP-in-IP 封装。这让我们可以将 L4LB 和后端主机放在不同的机架上。我们使用 [IPVS 内核模块](https://l.facebook.com/l.php?u=http%3A%2F%2Fwww.linuxvirtualserver.org%2F&h=ATNMmTklY_BIznC0ZQODRc0GMcMKdjH77U0mKd9rlzwI8VxuJz8TlZlYsGSJWBESJhuIvi2z5lAia1YcE_DCKE3KzqEL2hxme1gYkPZvG33YlSevsd8cTJKi7vllJvz8pPBDgIdROvcRwdJPeCEjsM) 提供转发平面和封装。将 VIP 配置在后端的回环接口上。这允许后端在返回路径上将数据包直接发送到客户端(而不是 L4LB)。 这种优化通常称为直接服务器返回 (DSR),允许 L4LB 仅受传入数据包量的约束。 - **控制平面:** 该组件具有多种功能,包括对后端服务器进行健康检查,通过配置文件提供简单的界面来添加或删除 VIP,并提供简单的 API 来查看 L4 负载均衡器和后端服务器的状态。我们自行开发了这个组件。 每个 L4LB 也将每个 5 元组的后端选择保存在表中,以避免在将来的数据包上重复计算哈希。这种状态是一种纯粹的优化,并不是正确性所必需的。这个设计满足了 Facebook 工作负载中列出的几个需求,但有一个主要的缺点:将 L4LB 和后端在同一主机上共存增加了设备故障的可能性。即使有了本地状态,L4LB 仍然是一个 CPU 密集型组件。为了分离故障域,我们在一组不连续的机器上运行 L4LBs 和后端服务器。在这种设置中,L4LB 的数量少于后端服务器,这使得 L4LB 更容易受到突然增加的负载的影响。数据包必须穿越常规的 Linux 网络堆栈才能被 L4LB 处理,这加剧了问题。 ![](https://hackmd.io/_uploads/S1rZfA0r2.png) * 图 3:我们的第一代 L4LB 的概述。请注意,负载均衡器和后端应用程序运行在不同的机器上。不同的负载均衡器可以在没有任何状态同步的情况下做出一致的决定。使用数据包封装允许在不同的机架上放置运行负载均衡器和后端应用程序的服务器。在典型的部署中,L4LB 的数量与后端应用程序服务器的数量之比非常小。 ### Katran:重塑转发平面 Katran,我们的第二代 L4LB,通过完全重新设计的转发平面,在前一版本上进行了显著的改进。内核领域中的两个最新发展推动了新设计: - XDP 提供了一个快速的、可编程的网络数据路径,无需采用全功能的内核旁路方法,并与 Linux 网络堆栈协同工作。(XDP 的详细概述可在 [这里](https://www.iovisor.org/technology/xdp?fbclid=IwAR1JaM0fay10lfzV8jBKkvH1UdVPaR_fw0nhDXmW58ow7QG_zpeiCdZ0QzY) 找到。) - eBPF 虚拟机提供了一种灵活、高效、更可靠的方式来与 Linux 内核交互,通过在内核的特定点运行用户空间提供的程序来扩展其功能。eBPF 已经给多个领域带来了显著的改进,包括跟踪和过滤。(更多的细节可以在 [这里](https://www.iovisor.org/technology/ebpf?fbclid=IwAR3xxK9v3Uebv2X-W92dhT6NQOmmXV8bL4p3Sqkln36BNLdMW648qVC5tkY) 找到。) 整个系统的架构与第一代 L4LB 相似:首先,ExaBGP 向世界宣布哪些 VIP 是由特定的 Katran 实例负责的。其次,目标为 VIP 的数据包通过 ECMP 机制发送到 Katran 实例。最后,Katran 选择一个后端并将数据包转发到正确的后端服务器。主要的差异在于最后一步。 **早期和高效的数据包处理:** Katran 使用 XDP 结合 BPF 程序进行数据包转发。当在驱动模式中启用 XDP 时,数据包处理程序(BPF 程序)在网卡(NIC)接收到数据包后在内核拦截之前立即运行。XDP 在每个进入的数据包上调用 BPF 程序。如果 NIC 有多个队列,那么所有队列将并行调用该程序。处理数据包的 BPF 程序是无锁的,并使用每个 CPU 独立版本的 BPF maps。由于这种并行性,性能随着 NIC 的 RX 队列数量线性增长。Katran 还支持 "通用 XDP" 模式(而不是驱动模式)的操作,但这会带来性能成本。 **廉价且更稳定的哈希:** Katran 使用了扩展版的 Maglev 哈希来选择后端服务器。这个扩展版哈希的特性包括对后端服务器故障的弹性、更均匀的负载分配以及为不同后端服务器设置不相等权重的能力。最后一个特性非常重要,它使我们能够轻松地处理我们在 PoPs 和数据中心的硬件刷新:我们可以通过简单地设置适当的权重来引入新一代硬件。尽管其功能强大,但计算此哈希的代码小到足以完全放入 L1 缓存。 **更强大的本地状态:** Katran 在处理数据包和计算哈希的效率上,与本地状态表的相互作用结果是有趣的。我们观察到,相当频繁的情况下,计算哈希在计算上比查找 5 元组到后端服务器选择的本地状态表更容易。这对于本地状态表查找需要遍历到共享最后级缓存的情况更为明显。为了以自然的方式利用这种现象,我们实现了查找表作为一个 LRU- 缓存驱逐。LRU 缓存大小在启动时可配置,并作为一个可调参数,以在计算和查找之间达到平衡。我们选择这些值是基于经验的,以优化 pps。此外,Katran 提供了一个运行时“仅计算”开关,在主机上出现灾难性内存压力的情况下可以完全忽略 LRU 缓存。 **适应 RSS 封装:** [接收方扩展](https://l.facebook.com/l.php?u=https%3A%2F%2Fwww.kernel.org%2Fdoc%2FDocumentation%2Fnetworking%2Fscaling.txt&h=ATOeXGfQePXXsqxmGgjyv7on4BYMoKkTy39C_INyq5ciKdozJWVI1OvpxnU-6JT4eDnn7D0UiII85_9Ff_WEFgtXCneDHHnueBhFZ8HLAjMKEts5GFgjVXLRIVjDHjxtjw1VTpG3)(RSS) 是 NIC 中的一项重要优化,旨在通过将数据包从每个流引导到单独的 CPU 来在 CPU 之间均匀分布负载。Katran 对其进行封装以与 RSS 结合使用。与使用同一外部源为每个 IP-in-IP 数据包进行封装不同,不同流(例如,具有不同 5 元组)的数据包使用不同的外部源 IP 进行封装,但同一流的数据包始终被分配相同的外部源 IP。 ![](https://hackmd.io/_uploads/Sk5YGRABh.png) * 图 4:Katran 为高速处理数据包提供了一条快速路径,而无需诉诸成熟的内核旁路。请注意,数据包仅穿过内核/用户空间边界一次。 这使我们能够在不牺牲性能的情况下托管 L4LB 和后端应用程序。 这些特性显着增强了 L4LB 的性能、灵活性和可扩展性。Katran 的设计还摆脱了接收路径上的繁忙循环,如果没有传入数据包,它几乎不占用任何 CPU。与成熟的内核绕过解决方案(例如 DPDK)相比,使用 XDP 允许我们在同一主机上与任何应用程序一起运行 Katran 而不会造成任何性能损失。如今,Katran 在我们的 PoP 中与后端服务器一起运行,L4LB 与后端的比率有所提高。这也提高了对负载峰值、主机故障和维护的弹性。重新设计的转发平面是这一转变的核心。我们相信其他系统可以通过使用我们的转发平面而受益,因此我们开源了代码,并包括几个如何使用它来制作 L4LB 的示例。 **其他注意事项** Katran 在某些能够提高性能的假设和约束下运行。在实践中,我们发现这些限制相当合理,并且没有阻碍我们的部署。我们相信,使用库的大多数用户会发现这些限制很容易满足。我们将它们列在下面: - Katran 仅在直接服务器返回(DSR)模式下工作。 - Katran 是决定发送到 VIP 的数据包的最终目的地的组件,因此网络需要首先将数据包路由到 Katran。这要求网络拓扑是基于 L3 的,例如,数据包是通过 IP 而不是 MAC 地址进行路由的。 - Katran 无法转发分段的数据包,也无法自行进行分段。这可以通过增加网络内部的最大传输单元(MTU)或更改后端的广播 TCP MSS 来解决此问题。(即使已经增加了MTU,也建议执行后一步。) - Katran 不支持设置 IP 选项的数据包。最大数据包大小不能超过3.5 KB。 - Katran 建立在假设的基础上,即它将用于“负载均衡器绑定在一个接口上”的场景,这个场景里单个接口将用于“从用户到 L4 负载均衡器(入口)”和“从 L4 负载均衡器到 L7 负载均衡器(出口)”的流量。 尽管存在这些限制,我们相信 Katran 为希望建立高效负载均衡器的用户和组织提供了出色的转发平面。我们期待回答有关我们的 [GitHub存储库](https://github.com/facebookincubator/katran)的任何问题,并且随时欢迎提交 PR!

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully