Xray API自动选优脚本:JSON配置与节点动态切换

本文面向能够读写 Xray JSON 的开发者与运维人员,从 gRPC API 工作机制出发,搭建节点测速、健康检查和自动切换流程。你将获得完整配置片段、脚本设计思路、权限控制方式,以及在 Linux 服务器上长期运行的工程化方案。

当节点数量增加后,手动逐个测试、复制配置和切换活动节点很快就会变成重复劳动。Xray 提供的 gRPC API 可以让外部程序读取运行状态、查询流量统计,并通过 HandlerService 动态增加或移除出站;再配合独立的健康检查脚本,就能把“测速—筛选—切换—记录”串成一个可持续运行的流程。需要先说明的是,Xray API 本身不是完整的节点调度平台,API 只负责执行控制命令,测速规则、失败阈值、切换冷却时间和权限保护仍然需要由脚本设计。

本文速览

本文面向能够读写 Xray JSON、了解 Linux 命令行和 gRPC 基础的开发者与运维人员,使用本机回环地址开放 API,搭建节点健康检查与动态切换方案。你将看到 API 配置、节点 JSON、脚本流程、权限控制、日志处理和 systemd 长期运行方式,并能根据节点数量和业务风险选择“动态修改”或“生成配置后重启”两种实现路径。

一、先理解 Xray API 能做什么

Xray 的 API 通常通过 gRPC 提供服务。核心启动后,外部程序连接 API 入站端口,再调用已经启用的服务。常见的 HandlerService 用于管理入站和出站,StatsService 用于读取流量统计;部分版本还提供与路由、观测相关的服务。不同 Xray-core 版本的 proto 定义和可用命令可能存在差异,因此脚本部署前应先确认实际核心版本、服务名称和客户端库是否匹配。

脚本读取节点调用 gRPC API发起健康检查计算优先级切换代理出站

核心保持运行,脚本通过 HandlerService 管理出站,切换速度快,适合节点数量较少、能够接受短暂控制窗口的服务。

适合:个人网关、低延迟切换、少量节点

脚本生成完整配置文件,校验通过后执行平滑重启。流程容易审计,也更适合需要严格保留配置快照的环境,但重启期间可能有短暂连接中断。

适合:生产配置、节点较多、变更需留痕

只在 v2rayN 或其他客户端中更新节点,不改变服务器端的 Xray 运行状态。实现简单,但不能替代服务器上的自动健康检查。

适合:桌面端手动维护、临时测试

结论:API 负责执行,脚本负责决策

不要把“API 返回成功”误认为“节点已经可用”。AddOutbound 成功只表示核心接受了出站对象,真正的网络可用性仍需通过代理请求、超时统计和连续失败次数确认。自动切换逻辑至少要包含成功阈值、失败阈值和冷却时间。

127.0.0.1
API 建议监听地址
10085
常见 API 端口
3 次
建议连续失败阈值
60 秒
最低切换冷却时间

二、用 JSON 开放受保护的本机 API

API 配置通常由 apiinboundsrouting 三部分组成。下面的片段展示一个只监听本机回环地址的 API 入站。api.tag 必须与路由规则中的 inboundTag 对应,outboundTag 则应指向名为 api 的出站。若配置中没有 API 出站,调用可能建立连接却无法正常执行服务请求。

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

上面的 active 只是结构示意,不代表真正的节点配置。实际使用时,节点出站应放入单独的 JSON 模板或数据库,由脚本按标签载入。API 端口不应监听在 0.0.0.0,也不要直接把 10085 暴露到公网。Xray 的 gRPC API 一旦被未授权访问,攻击者可能读取统计、修改处理器或改变出站,风险远高于普通代理端口。

API 入站

协议
dokodemo-door
监听
127.0.0.1
端口
10085
服务
HandlerService、StatsService

只允许同一台服务器上的脚本访问,不为远程管理开放端口。

节点出站

节点标签
node-hk-01
协议
VLESS 或 VMess
端口
以服务端实际值为准
切换标识
active 或 balancer 标签

每个标签必须唯一,脚本不能用模糊名称替代精确标签。

三、设计节点 JSON 与健康检查指标

自动选优不能只保存一个节点链接。脚本至少应为每个节点保存唯一标签、协议参数、测试地址、超时时间、连续失败次数和最近一次成功时间。节点配置和运行状态最好分离:配置文件记录静态参数,SQLite、JSON 状态文件或内存对象记录动态分数。这样测速失败不会直接污染原始节点数据。

{
  "tag": "node-sg-01",
  "protocol": "vless",
  "address": "edge.example.net",
  "port": 443,
  "uuid": "替换为实际 UUID",
  "network": "tcp",
  "security": "reality",
  "health": {
    "url": "https://example.com/generate_204",
    "timeout_ms": 5000,
    "fail_limit": 3,
    "cooldown_sec": 60
  }
}

测速请求应经过待测节点,而不是直接从服务器访问目标地址。常见做法是为每个节点建立临时出站和对应的本地测试入口,或者使用脚本生成一次性测试配置。若节点已经作为固定出站载入,也可以让测试请求按照节点标签路由,再用 curl 的代理参数访问稳定的小响应地址。测试目标应返回较小内容,避免把测速变成大量下载。

指标 建议记录 判断用途 不要误判为
连接耗时 毫秒,保留 3 次结果 筛掉握手明显异常的节点 长期下载速度
HTTP 状态 200、204 或业务允许状态 确认代理请求确实完成 节点全部协议能力
连续失败 次数与最后错误 判断是否触发摘除 单次网络抖动
恢复次数 连续成功次数 判断是否允许重新加入 一次成功后的永久健康

推荐采用“连续 3 次失败才摘除、连续 2 次成功才恢复”的滞后策略。没有滞后时,节点在可用与不可用之间反复跳转,用户会遇到连接重置、登录会话中断和 DNS 请求忽快忽慢。不同节点的评分也不应只看最低延迟,可以使用加权公式,例如将成功率占 60%、中位延迟占 25%、最近失败惩罚占 15%,再设置一个最低成功率门槛。

四、动手实现测速、筛选与动态切换

  1. 读取节点清单

    脚本读取权限为 600 的节点 JSON,检查标签唯一性、地址格式、端口范围和必需协议字段。任何节点字段缺失时先跳过,并写入结构化日志。

  2. 建立 API 连接

    连接 127.0.0.1:10085,设置 3 秒 gRPC 连接超时。连接失败时不要立刻重启 Xray,应先检查核心进程、监听端口和 systemd 日志。

  3. 逐个健康检查

    按顺序测试候选节点,每个请求超时设为 5 秒,单轮测试之间可间隔 100 至 300 毫秒,避免节点数量较多时瞬间制造大量连接。

  4. 计算候选排名

    剔除连续失败达到 3 次的节点,再按成功率、延迟中位数和最近一次成功时间排序。当前活动节点未明显劣化时,设置 10% 至 20% 的切换优势门槛。

  5. 执行出站切换

    通过 HandlerService 增加目标出站、移除旧出站,或调用当前版本支持的路由覆盖能力切换 balancer 目标。执行后再次读取运行状态确认标签已生效。

  6. 写入结果日志

    记录时间、旧标签、新标签、测试耗时、失败原因和 API 返回结果。至少保留最近 7 天日志,便于判断切换是否集中发生在某个时间段。

在实现 HandlerService 调用时,不要把“删除旧节点”和“增加新节点”写成没有保护的两个独立动作。脚本应先确认新节点健康,再调用增加操作;如果增加成功,再处理旧节点。遇到 API 超时,应重新查询当前出站列表,不能根据本地变量直接重复添加,否则可能产生重复标签或状态不一致。

# 伪代码:展示控制顺序,不是可直接执行的客户端命令
for node in candidates:
    result = health_check(node, timeout=5)
    update_score(node, result)

best = choose_best_node(min_success=2)
if best.tag != current_tag and better_than_current(best, margin=0.15):
    api.add_outbound(best.config)
    verify_outbound(api, best.tag)
    api.switch_route(best.tag)
    wait(60)
    api.remove_outbound(current_tag)
    write_event(current_tag, best.tag, result)

不同 Xray-core 版本对路由服务和 balancer 覆盖命令的支持细节可能不同。若当前版本没有可靠的动态路由切换接口,不要伪造一个不存在的 gRPC 方法;可以让脚本生成完整 JSON,先运行配置测试,再通过 systemd 重启核心。对生产环境而言,能回滚、可审计通常比少几秒中断更重要。

结论:先确认切换能力,再决定 API 方案

如果只能稳定调用 HandlerService,建议把节点生命周期控制在“加入、验证、移除”范围内;如果版本同时支持可靠的路由或 balancer 覆盖,再使用固定出站池和活动目标切换。不要因为文档中出现 API 服务名称,就假定所有版本都支持同一组请求字段。

五、权限、故障处理与 Linux 长期运行

运行脚本的系统用户不应拥有整个应用目录的写权限。可以建立专用用户,例如 xray-automation,只允许读取节点模板、写入状态目录和连接本机 API。节点 JSON 中可能包含 UUID、密码或 Reality 密钥,文件权限建议设为 600,父目录设为 700,日志中不得打印完整订阅地址、UUID 或私钥。

文件权限

节点配置
root:xray-automation
权限
600
状态目录
700
API 监听
127.0.0.1:10085

脚本只读取必要配置,敏感字段通过环境变量或受限文件提供。

运行策略

检查周期
60 至 180 秒
单次超时
5 秒
失败阈值
连续 3 次
重启策略
失败后指数退避

避免每次测速异常都重启核心,先区分节点故障和 API 故障。

systemd 服务可以使用 Restart=on-failure,但不要设置过短的重启间隔。建议使用 RestartSec=10,并为脚本增加单实例锁,防止上一次检查未结束时下一次任务重复修改出站。部署后先执行一次前台运行,确认 API 连接、健康检查、日志和切换动作全部正常,再交给 systemd 托管。

[Unit]
Description=Xray node selector
After=network-online.target xray.service
Wants=network-online.target

[Service]
Type=simple
User=xray-automation
ExecStart=/usr/local/bin/xray-node-selector --config /etc/xray/nodes.json
Restart=on-failure
RestartSec=10
NoNewPrivileges=true
PrivateTmp=true

[Install]
WantedBy=multi-user.target

报错:rpc error: code = Unavailable

原因与解法:API 端口未监听、核心已退出或脚本连接了错误地址——先执行 ss -lntp | grep 10085,再检查 Xray 服务日志和脚本中的端口。

报错:address already in use

原因与解法:旧出站或旧脚本实例仍占用本地测试端口——使用单实例锁,清理残留进程,并为每个临时测试入口分配唯一端口。

报错:failed to add outbound

原因与解法:节点 JSON 字段与当前核心版本不兼容,或标签已存在——先用相同核心执行配置校验,检查标签唯一性和协议字段类型。

报错:health check timeout

原因与解法:节点、目标站或服务器出口存在超时,不一定是 API 故障——分别测试其他节点,并记录 TCP、TLS 和 HTTP 阶段耗时后再决定是否摘除。

只调用 StatsService 能自动选出最快节点吗?

不能。StatsService 主要提供流量与计数信息,不能替代真实代理请求。应结合经节点转发的 HTTP 健康检查,并用连续结果计算排名。

健康检查每分钟执行一次会不会太频繁?

对少量节点和小响应地址通常可以,但节点超过 50 个时应分批检查,并把周期调整到 120 至 180 秒,避免产生不必要的连接和日志。

切换后旧连接会立即断开吗?

取决于实现方式。新请求可以走新出站,但已经建立的连接可能仍由旧出站维持;若直接移除旧出站,长连接可能被中断,因此应先设置冷却时间。

API 是否应该开放给远程监控服务器?

默认不建议。优先让监控程序通过本机代理、受限 SSH 隧道或专用安全通道访问;不要把未经认证的 Xray API 端口直接映射到公网。

完成部署后,至少连续观察 24 小时:记录每次切换的原因、节点成功率、平均延迟和切换后的恢复情况。如果切换次数异常高,先提高冷却时间和切换优势门槛;如果所有节点同时失败,则应检查服务器出口、DNS、目标测试站和 Xray 核心状态,而不是继续增加节点。真正可靠的自动选优系统不是“越快切换越好”,而是在可验证、可回滚和最少干扰业务之间取得平衡。

V2Ray客户端下载