入门指南 预计阅读 13 分钟

V2Ray 新手十问十答:订阅、内核、协议与客户端选择快速扫盲

本指南面向能够直接读写 Xray JSON 配置的技术用户,拆解 gRPC API 的工作方式,并提供可运行的节点健康检查与自动切换方案。你将学会结合 StatsService、HandlerService、延迟阈值和故障回退机制,构建更可靠的自动化代理运维流程。

节点自动切换并不是把配置文件里的服务器地址随机替换掉,而是让一个独立的控制程序持续观察候选节点的真实连接结果,再通过 Xray API 调整路由或出站配置。本文面向能够直接读写 Xray JSON 配置的技术用户,重点说明 gRPC API、StatsServiceHandlerService、延迟探测、失败计数和回退机制之间如何配合,最后给出一套适合单机运行的自动择优思路。

本文速览

你将先建立 Xray API 的最小配置,再区分“统计计数”和“真实延迟测试”各自负责的工作,随后按照候选节点、阈值、冷却时间和回退节点设计自动切换流程。示例以 Xray API 监听 127.0.0.1:10085 为基础,适合 v2rayN 等客户端生成的配置,也适合自行维护 Xray JSON 的桌面或服务器环境。

Xray API到底控制什么

Xray API 是运行中内核提供的 gRPC 管理接口。它与普通代理入站不是一回事:SOCKS、HTTP 或透明代理入站负责接收应用流量,API 入站则负责接收管理请求。控制程序连接 API 后,可以查询运行统计、读取系统指标、添加或删除入站和出站,并通过 HandlerService 修改运行中的处理器。

自动择优通常需要同时处理三类数据。第一类是节点是否真的能建立代理连接,这需要通过候选出站发起实际探测;第二类是该节点近期是否持续产生错误或没有流量,可以通过 StatsService 查询计数器;第三类是当前配置应该把业务流量送到哪个节点,这通常由路由规则中的 outboundTag 或 balancer 选择器决定。三者不能混为一谈:统计服务可以告诉你失败次数,但不会自动测出网页首字节延迟,也不会替你迁移已经建立的 TCP 连接。

控制程序启动读取候选节点真实连接探测查询运行统计计算健康分数更新代理出站

一个容易被忽略的限制是,API 切换只影响后续被路由的新连接。已经建立的 WebSocket、HTTP/2、TCP 或长连接不会因为当前出站标签改变而自动迁移。因而自动切换的目标应当是“停止把新请求送往故障节点”,而不是承诺所有正在传输的连接无感重连。浏览器通常会在连接失败后重试,但下载、长轮询和实时通信程序是否重连,仍取决于应用自身。

结论:先把切换范围定义清楚

最稳妥的第一版只负责改变新连接的默认代理出站,并保留一个始终可用的回退节点;不要一开始就尝试重建整个 Xray 配置或强行迁移已有连接。

API 服务的 JSON 配置与安全边界

启用 API 至少要有一个 api 配置段和一个标记为 api 的入站。下面的示例把管理端口绑定到回环地址,避免局域网中的其他设备直接调用控制接口。端口 10085 只是示例,只要没有被其他程序占用即可;如果 v2rayN 已经生成了 API 入站,应先检查现有标签和端口,再决定是否合并,不能在同一地址端口上重复监听。

{
  "log": {
    "loglevel": "warning"
  },
  "api": {
    "services": [
      "StatsService",
      "HandlerService"
    ],
    "tag": "api"
  },
  "inbounds": [
    {
      "listen": "127.0.0.1",
      "port": 10085,
      "protocol": "dokodemo-door",
      "settings": {
        "address": "127.0.0.1"
      },
      "tag": "api"
    }
  ],
  "routing": {
    "rules": [
      {
        "type": "field",
        "inboundTag": [
          "api"
        ],
        "outboundTag": "api"
      }
    ]
  }
}

这个入站的作用是把发往 API 端口的 gRPC 请求交给 API 出站。API 标签、入站标签和路由规则中的标签必须互相对应。若只配置了 api.services,却没有可访问的 API 入站,控制程序会在连接阶段得到拒绝或超时;若有入站却没有把 inboundTag 路由到 api 出站,管理请求可能被当成普通流量处理。

最小管理接口

监听地址
127.0.0.1
端口
10085
服务
StatsService、HandlerService
用途
统计与运行时管理

单机控制程序使用回环地址即可,不要默认暴露到公网。

候选出站约定

节点标签
node-a、node-b
默认标签
proxy
回退标签
fallback
探测入口
probe-socks

标签应稳定且唯一,自动化程序不要依赖订阅显示名称。

生产环境不建议把 API 监听在 0.0.0.0。Xray 的这类管理接口通常依赖网络隔离而不是用户名密码来保护;一旦端口被其他用户访问,对方可能查询统计,甚至修改运行中的处理器。若确实需要远程管理,应在防火墙、隧道或受控管理网络中限制来源,并为管理通道增加额外的访问控制。修改前也应保存原始 JSON,避免控制程序异常时无法恢复。

StatsService 与真实延迟要分工

StatsService 的核心价值是读取计数器。常见计数器按入站、出站和用户统计流量,名称通常类似 outbound>>>node-a>>>traffic>>>uplinkoutbound>>>node-a>>>traffic>>>downlink。要让这些计数器可用,需要在配置中打开统计,并在对应出站上设置 tag。不同 Xray 版本和客户端生成方式可能有字段差异,实际部署后应先用 API 的统计查询确认返回的名称,不要只凭手写字符串判断。

{
  "stats": {},
  "policy": {
    "levels": {
      "0": {
        "statsUserUplink": true,
        "statsUserDownlink": true
      }
    },
    "system": {
      "statsInboundUplink": true,
      "statsInboundDownlink": true,
      "statsOutboundUplink": true,
      "statsOutboundDownlink": true
    }
  }
}

统计查询适合回答“节点近期有没有产生流量”“切换后流量是否真的转移”“某个出站是否持续出现异常计数”等问题。它不适合单独回答“哪个节点当前延迟最低”。如果节点没有新请求,统计值可能长时间不变;如果节点已经建立了长连接,计数仍会增长,但这不代表新建连接一定成功。因此自动择优应把统计值当作辅助信号,而不是唯一健康指标。

延迟探测可以从本机为每个候选节点准备独立的 SOCKS 入站,例如 probe-aprobe-b,每个入站固定路由到对应的出站。控制程序通过这些本地端口发起 HTTPS HEAD 或短连接 GET,请求一个稳定、响应体很小的测试地址,并记录 TCP 建连、TLS 完成和首字节时间。测试地址应选择你能够稳定访问、返回内容固定且不会触发大量重定向的服务;不要把某个大型网页首页当成唯一基准。

信号推荐用途常见误判
真实代理延迟判断新连接的交互速度一次低延迟被当成长期稳定
连续失败次数触发暂时摘除节点把单次超时当成永久失效
StatsService 流量计数确认出站是否正在承载流量没有流量被误判为节点故障
错误率与超时率识别持续性线路问题忽略测试请求本身可能被目标站限制
恢复探测结果决定是否把节点放回候选池刚成功一次就频繁来回切换

按阈值、冷却与回退实现自动切换

自动化逻辑最好先定义状态机,而不是写一个“延迟最高就换节点”的条件。每个节点至少有健康状态、最近一次成功时间、连续失败次数、最近延迟和冷却截止时间。初始状态可以是 unknown;探测成功后进入 healthy,连续失败达到阈值后进入 unhealthy,等待冷却时间后重新探测。这样能够避免网络抖动造成节点在 A、B 之间快速来回切换。

  1. 准备标签

    outbounds 中为每个节点设置稳定的 tag,例如 node-anode-b,另保留一个明确的 fallback。不要使用会随订阅更新改变的显示名称作为程序主键。

  2. 建立探测入口

    为候选节点分配独立的本地 SOCKS 端口,例如 1108111082。每个探测入口只路由到一个目标出站,避免测试请求被默认代理标签再次转发。

  3. 记录健康状态

    每 30 秒探测一次,每个节点连续执行 3 次。把超时、DNS 失败、TLS 握手失败和 HTTP 非预期状态分别记录,成功一次不能立即清除全部失败历史。

  4. 计算切换条件

    可将连续失败达到 3 次或连续 2 个周期平均延迟超过 800 毫秒作为摘除条件;当前节点失败时,优先选择最近三次成功率最高且延迟低于 500 毫秒的节点。

  5. 更新运行配置

    通过 HandlerService 的运行时操作调整出站,或修改由路由使用的活动标签。更新后立刻发起一次验证请求,并把切换时间、旧标签、新标签和原因写入独立日志。

这里的阈值不是通用真理,而是避免频繁切换的起点。对于网页浏览,连续失败 2 至 3 次通常已经足够触发备用节点;对于长连接业务,应该提高失败确认次数,并设置更长的冷却时间。延迟阈值还要结合本地网络基线:如果直连测试本身就稳定在 400 毫秒,那么把 300 毫秒作为代理异常阈值没有意义。

每 30 秒执行:
  for node in candidates:
    result = probe(node, timeout=5s)
    update_success_failure(node, result)

  if active.failed_consecutive >= 3:
    next = choose(
      healthy_nodes,
      success_rate desc,
      median_latency asc
    )
    if next exists:
      switch_to(next)
    else:
      switch_to(fallback)

  if active is fallback and candidate passes 3 probes:
    switch_to(best_candidate)

选择算法建议使用中位数而不是单次最低延迟。比如某节点五次结果为 82、85、79、91、86 毫秒,中位数为 85;另一个节点为 45、62、310、58、900 毫秒,虽然最低值只有 45 毫秒,但它更可能造成页面间歇性卡顿。可以把成功率放在第一排序条件,把中位数延迟作为第二条件,再用最近成功时间打破相同分数。

HandlerService 的改动方式与风险

HandlerService 适合管理运行中的入站和出站,但“自动切换节点”究竟调用哪一个方法,取决于配置结构。若每个节点都是独立出站,控制程序可以使用运行时处理器操作添加、删除或调整出站;如果节点已经放在 balancer 中,则应围绕选择器和路由配置设计,不要在每次探测时重复添加同名出站。重复添加可能导致标签冲突、配置状态与本地文件不一致,甚至让重启后的配置恢复到旧状态。

一种较容易维护的方案是固定保留所有候选出站,仅改变代理路由指向的活动节点。若当前 Xray 版本或客户端封装没有提供直接改变选择器的接口,可以让控制程序生成一份完整配置,先在临时文件中完成 JSON 校验,再以受控方式重启内核。重启方案会中断现有连接,优点是状态清晰,缺点是切换瞬间所有连接都会断开。因此,优先采用可验证的运行时 API;只有当运行时修改能力不足时,才考虑重载或重启。

运行时修改

影响范围
主要是后续新连接
中断程度
通常较小
主要风险
内存状态与文件配置不一致
适合
高可用、频繁探测

每次修改都要记录操作,并定期把有效状态落盘。

生成后重启

影响范围
所有运行中连接
中断程度
切换时明显
主要风险
配置错误导致无法启动
适合
低频维护、结构简单

重启前先执行 JSON 语法检查,并保留上一份可用配置。

无论采用哪种方式,都应把“切换成功”定义为可验证事件,而不是 API 返回成功就算完成。切换后至少检查三项:新的本地代理请求是否确实能完成;对应出站的 StatsService 计数是否增长;日志中是否出现新的节点标签以及没有连续的 timeouthandshake failed。如果 API 修改成功但业务流量仍走旧节点,通常是路由规则优先级、缓存连接或客户端重新生成配置覆盖了运行时修改。

故障回退、审计与常见问题

回退机制应当独立于普通择优逻辑。推荐设置一个明确的 fallback 节点,或者保留直连作为最后的安全策略,具体取决于业务是否允许直连。所有候选节点都失败时,不要让程序在空列表上反复调用 HandlerService;应进入保护状态,降低探测频率,例如从 30 秒延长到 120 秒,并保留最后一次有效配置。恢复时也不要立即恢复到“延迟最低”的节点,最好要求候选节点连续三次探测成功。

日志至少记录时间、当前节点、候选节点、探测耗时、失败类型、StatsService 计数快照和切换原因。不要记录 UUID、订阅地址、Reality 私钥或完整节点 JSON。对于自动修改配置的程序,还应限制文件权限,避免普通网页进程、日志收集器或其他本地用户读取敏感字段。若运行环境有多个 Xray 实例,必须为每个实例使用独立 API 端口和独立控制状态文件。

StatsService 能直接测出节点延迟吗?

不能。StatsService 主要返回流量和运行统计,延迟应通过独立探测入口发起真实代理请求测量。统计结果更适合确认出站是否承载流量,以及辅助判断错误是否持续发生。

调用 HandlerService 后,正在下载的任务会自动换节点吗?

通常不会。运行时切换主要影响新建连接,已经建立的 TCP、HTTP/2 或 WebSocket 连接仍由原出站处理。是否重连由下载器或业务程序决定。

为什么延迟只有 120 毫秒,网页仍然经常超时?

延迟只代表某次探测的响应时间,不能覆盖丢包、TLS 握手、目标站限制和高峰期拥塞。请增加三到五次探测,记录失败率,并检查 Xray 日志中的 timeout、DNS 和握手错误。

订阅更新后自动切换程序找不到节点了?

通常是节点标签被客户端重新生成,导致控制程序保存的 node-a 等标识失效。应在订阅更新后重新建立标签映射,或使用稳定的配置模板生成出站,再启动健康检查。

下载v2rayN