详情

首页手游攻略 thousand_island:实践指南

thousand_island:实践指南

佚名 2026-09-12 20:40:01

面对实际交付,我看thousand_island的重点不在星标,而在这项能力:千岛是一个纯粹的 Elixir 套接字服务器。在部署与运行环境场景里,常见问题是权限、依赖和环境差异会放大维护成本,这正是评估时需要盯住的地方。试跑可以从在非生产环境复现一次安装与运行开始,并把依赖锁定、权限边界、日志、回滚和资源消耗写进验收记录。整体来看,它适合愿意维护环境并重视故障恢复的工程团队拿来做对照测试,最终决定仍应回到真实结果和维护状态。

千岛是一个现代的、纯粹的 Elixir 套接字服务器,其灵感很大程度上来自于 牧场。它的目的是易于理解 并进行推理,同时至少与替代方案一样稳定和高性能。 非正式测试将牧场和千岛的水平大致相同 性能和开销;在最繁忙的服务器上缺少合成场景, 他们在所有意图和目的上表现都是平等的。

千岛完全是用 Elixir 编写的,几乎没有依赖( 唯一使用的库是 遥测)。 该应用程序强烈拥护 OTP 设计原则,并强调可读性、 简单的代码。希望千岛有能力支持 作为要求最高的服务,它也作为一种简单平易近人的方式很有用 惯用的 OTP 设计模式的参考。

用途

千岛作为监督树实施,旨在托管 在主机应用程序内部,通常作为嵌入到更高级别的依赖项 协议库如Bandit。除了 监督千岛进程树,应用程序与千岛交互 岛屿主要通过 ThousandIsland.Handler 行为。

处理程序

ThousandIsland.Handler 行为定义了千岛群岛的接口 用于将 ThousandIsland.Sockets 传递到应用程序级别;他们在一起 构成大多数应用程序与千岛群岛的主要界面。 千岛提供了一些简单的协议处理程序作为示例; 这些可以在 示例 中找到 该项目的文件夹。一个简单的实现如下所示:

defmodule Echo do
  use ThousandIsland.Handler

  @impl ThousandIsland.Handler
  def handle_data(data, socket, state) do
    ThousandIsland.Socket.send(socket, data)
    {:continue, state}
  end
end

{:ok, pid} = ThousandIsland.start_link(port: 1234, handler_module: Echo)

有关更多信息,请参阅 ThousandIsland.Handler 文档。

启动千岛服务器

千岛服务器以监督树的形式存在,由调用启动 到 ThousandIsland.start_link/1. 支持多种选项;有关完整的说明,请参阅 【千岛 docs.

连接耗尽和关闭

ThousandIsland.Server进程只是一个标准的Supervisor,所以所有的 适用有关关闭和关闭超时的通常规则。紧接着 开始关闭序列 ThousandIsland.ShutdownListener 将导致 套接字关闭,这又会导致所有的Acceptor 进程也会关闭。至此,只剩下监督了 树是几层主管,无论 Handler 进程是什么 启动关闭时正在进行。此时,标准Supervisor关闭 超时语义为现有连接提供了完成任务的机会。 Handler 进程陷阱退出,因此它们在关闭后继续运行,直到它们 完成或在关闭超时到期后为 :brutal_killed。

shutdown_timeout 配置选项允许对 关闭超时值。默认为 15000 毫秒。

记录和遥测

作为一个底层库,千岛故意不做任何内联 任何类型的日志记录。 ThousandIsland.Logger 模块定义了许多 帮助跟踪各种日志级别的连接的功能,以及此类日志记录 可以针对已运行的服务器动态启用和禁用。这个 日志记录由内部遥测事件支持。

千岛群岛发出一组丰富的遥测事件,包括每个事件的跨度 服务器、接受者进程和单个客户端连接。这些遥测 事件记录在 ThousandIsland.Telemetry 模块中。

实施说明

在顶层,Server 协调涉及响应的流程 套接字上的连接。 Server 管理两个顶级进程: Listener 它负责实际绑定到端口并管理结果 侦听器套接字,以及负责管理的 AcceptorPoolSupervisor AcceptorSupervisor 进程池。

每个 AcceptorSupervisor 进程(默认有 100 个)管理两个进程: 一个 Acceptor 接受与服务器侦听器套接字建立的连接, 以及一个 DynamicSupervisor,用于监督支持个人的流程 客户端连接。每次客户端连接到服务器的端口时,其中之一 Acceptors 以套接字的形式接收连接。然后它创建 基于配置的处理程序的新进程来管理此连接,以及 立即等待另一个连接。值得注意的是Acceptor 进程是长期存在的,并且通常在该进程的整个时期内都存在 Server 正在运行。

处理程序进程与客户端连接的生命周期相关联,并且是 仅在客户端连接时启动。其寿命长于 底层连接取决于配置的处理程序模块的行为。 在典型情况下,其生命周期与底层连接的生命周期直接相关。

这种分层方法减少了连接等待被接受所花费的时间, 并且还减少了创建新内容时对 DynamicSupervisor 访问的争用 Handler 进程。每个AcceptorSupervisor子树的功能几乎 自主地提高可扩展性和崩溃弹性。

从图形上看,这就像这样:

graph TD;
  Server(Server: supervisor, rest_for_one)-->Listener;
  Server-->AcceptorPoolSupervisor(AcceptorPoolSupervisor: dynamic supervisor);
  AcceptorPoolSupervisor--1...n-->AcceptorSupervisor(AcceptorSupervisor: supervisor, rest_for_one)
  AcceptorSupervisor-->DynamicSupervisor
  AcceptorSupervisor-->Acceptor(Acceptor: task)
  DynamicSupervisor--1...n-->Handler(Handler: gen_server)
  Server-->ShutdownListener;

千岛内部不使用命名进程或其他“全局”状态 (遥测事件名称除外)。完全支持单节点 托管任意数量的 Server 进程,每个进程不同的端口。

安装

千岛是 ,可用十六进制 表示。套餐 可以通过将 thousand_island 添加到 mix.exs 中的依赖项列表来安装:

def deps do
  [
    {:thousand_island, "~> 1.0"}
  ]
end

文档可以在 https://thousand-island.hexdocs.pm 中找到。

点击查看更多
推荐专题
热门阅读