# tcpfit 按每台机器实测推导的 TCP 调优工具. 不套用固定参数, 实测 BDP 与限速器拐点. 本脚本由 [kylin010](https://github.com/Kylin010) 编写和维护. ## 安装 ```bash bash <(curl -fsSL https://raw.githubusercontent.com/Kylin010/tcpfit/main/tcpfit.sh) ``` 跑完直接出菜单, 选 1 全自动. 脚本会装到 `/usr/local/bin/tcpfit`, 以后敲 `tcpfit` 即可. ## 三种用法 | 用法 | 命令 | |---|---| | 一键跑 | `bash <(curl -fsSL .../main/tcpfit.sh)` | | 装好后 | `tcpfit` | | 子命令 | `tcpfit tune --role proxy --bw 500` | 菜单需要终端. 远程执行用 `ssh -t <主机> tcpfit`, 脚本里用子命令. ## 菜单 ``` 1. 一键调优 Auto-tune (recommended) ~10 min 2. 基础调优 Base tuning only ~1 min 3. 拐点测试 Policer sweep ~8 min 4. 加 swap Add swap (low-memory box) ──────────────────────────────────────────── 5. 查看状态 Status 6. 端口验证 Verify port capability ~1 min 7. 回滚改动 Rollback all changes 8. 检查更新 Check for updates 9. 调优存档 Tuning archives u. 卸载 tcpfit ``` 脚本不会自动更新. 装好之后跑的一直是装的那一版, 想升级用菜单 8 或 `tcpfit update` —— 它只检查, 发现新版本会问你要不要更新. 一键调优只问三个问题: 带宽、测速对端、机器用途. 确认之后跑到底不再打断. 带宽那一问支持四种输入: | 输入 | 行为 | |---|---| | 数字 | 按该带宽推导缓冲区, 然后实测拐点 | | 回车 | 现场实测带宽, 然后实测拐点; 预计流量超过 50 GB 先问 | | `m` | 直接填限速值, 跳过拐点扫描 | | `0` | 不做整形 | ## 子命令 ```bash tcpfit detect # 机器画像 tcpfit probe --peer <近处iperf3服务器> # 探测可用带宽 tcpfit tune --role proxy --bw 500 # 基础调优 tcpfit tune --role proxy --bw 500 --save 换机房前 # 调优并给存档命名 tcpfit sweep --peer <近处iperf3服务器> --nominal 500 # 扫拐点, 加 --yes 跳过流量确认 tcpfit shape --rate 510 # 应用整形 tcpfit shape --off # 移除整形, 保留基础调优 tcpfit harden --swap 2G # 加 swap tcpfit verify --peer <近处iperf3服务器> # 测速验证 tcpfit status # 当前配置 tcpfit rollback # 回滚全部改动 tcpfit update # 检查更新 tcpfit archive list # 列出存档 tcpfit archive save "晚间配置" # 保存当前状态 tcpfit archive restore 0010 # 恢复第 10 份存档 tcpfit archive rename 0010 "备用配置" # 存档改名 tcpfit archive show 0010 # 查看某份存档的内容 tcpfit archive delete 0010 # 删除指定存档(别名 rm) tcpfit uninstall --keep-archives # 卸载,保留存档和快照 ``` ## PPPoE / 拨号线路 家宽 PPPoE、以及任何默认路由长这样的机器: ``` default dev ppp0 scope link # 点对点, 没有 via ``` 0.5.8 起支持. 这类机器每次重拨都是新接口, qdisc 和路由窗口会跟着消失, 所以 tcpfit 会往 `/etc/ppp/ip-up.d/50-tcpfit` 放一个钩子, 让整形和 initcwnd 在拨通后自动回来. 钩子只对调优时那块网卡生效, 不会碰机器上别的 ppp 链路. 没有 `/etc/ppp/ip-up.d` 的机器不受影响, 不会被创建任何东西. ## 多机(未上线) 多机编排还没在真实环境验证过, 暂时不建议使用. 下面的用法仅供参考. ```bash cp inventory/servers.example.yml inventory/servers.yml chmod 600 inventory/servers.yml vi inventory/servers.yml python3 orchestrator/fleet.py detect python3 orchestrator/fleet.py tune python3 orchestrator/fleet.py sweep python3 orchestrator/fleet.py shape --auto python3 orchestrator/fleet.py verify ``` 选项: `--only 机器名` `--tag 标签` `-j 并发数` `--dry-run`. 临时执行任意命令: `fleet.py run -- uptime`. ## 它改了什么 | 类别 | 参数 | |---|---| | 拥塞控制 | `tcp_congestion_control=bbr` + `default_qdisc=fq` | | 缓冲区 | `tcp_rmem` / `tcp_wmem` / `rmem_max` / `wmem_max` / `tcp_mem` | | 窗口 | `tcp_window_scaling` / `tcp_moderate_rcvbuf` / `tcp_adv_win_scale` | | 队列 | `netdev_max_backlog` / `netdev_budget` / `somaxconn` 等 | | 连接 | `tcp_tw_reuse` / `tcp_fin_timeout` / `ip_local_port_range` 等 | | 起步 | `tcp_slow_start_after_idle=0` / `initcwnd 32` | | 出向整形 | HTB 全局上限 + fq 叶子 pacing | 基础调优设 30 个 sysctl 参数, 加 swap 时再设 `vm.swappiness`. 缓冲区和整形值按每台机器实测推导, 不是固定值. ## 拐点扫描怎么工作 先不限速跑一次, 看有没有东西在打你: | 结果 | 动作 | |---|---| | 丢包低 | 没有限速器, 不整形 | | 丢包高 | 有限速器, 从实测吞吐往上扫找拐点 | | 吞吐 > 10000 Mbit | 超出扫描上限, 不扫(可用 `--cap` 调整) | 扫描前按实测速率估流量. 超过 50 GB, 或明显超过开始前给你的预估时先问, 默认不扫. 拐点在"不限速吞吐"的**上面** —— 打穿限速器会让吞吐掉下来, 所以往上找. ## 回滚 ```bash tcpfit rollback # 按快照逐项写回, 不是恢复默认 tcpfit rollback --purge-swap # 同时删掉 harden 建的 /swapfile tcpfit shape --off # 只去掉整形 ``` 首次改动前自动存快照到 `/var/lib/tcpfit/pre-tune.snapshot`, 记录全部 33 项参数的原始值. 0.5.7 起,原始快照同时保留为 `0000 出厂状态`,不可改名或单独删除。 `archive restore 0000` 与 `rollback` 使用同一回滚流程;“出厂状态”指首次调优前的快照。 普通存档位于 `/var/lib/tcpfit/archives/`。基础调优后自动保存,一键调优则在最终整形、验证完成后保存。 序号可以输入 `10` 或 `0010`;名字含空格时请加引号。 恢复普通存档会同步 sysctl 启动配置、整形服务和 initcwnd 持久化。路由只套用存档里的窗口值,不写回旧网关。 恢复失败可能已经应用部分设置,请按提示检查后重试。 `tcpfit uninstall` 默认删除存档;需要保留则加 `--keep-archives`。 若回滚失败,卸载会停止并保留存档。卸载不删除 swap、iperf3 或 ping。 swap 默认不动 —— 删掉正在用的 swap 可能让机器立刻 OOM, 要一并撤销得显式加 `--purge-swap`. 改动只落在这些文件, 不碰 `/etc/sysctl.conf`: ``` /etc/sysctl.d/99-tcpfit.conf /etc/systemd/system/tcpfit-qdisc.service /usr/local/sbin/tcpfit-qdisc.sh /etc/modules-load.d/tcpfit-bbr.conf /var/lib/tcpfit/ ``` initcwnd 的开机持久化按机器只用其中一种: ``` /etc/ppp/ip-up.d/50-tcpfit /etc/systemd/network/<网卡配置名>.network.d/50-tcpfit-initcwnd.conf /etc/networkd-dispatcher/routable.d/50-tcpfit-initcwnd /etc/systemd/system/tcpfit-initcwnd.service /usr/local/sbin/tcpfit-initcwnd.sh ``` ### initcwnd 持久化 initcwnd 设在默认路由上, 网卡重连、网络服务重启都会把它冲掉. tcpfit 按机器选一种: | 机器 | 做法 | |---|---| | PPP 拨号 | pppd 拨通后的钩子 | | networkd 管的 DHCP 网卡, systemd 255+(Ubuntu 24.04 / Debian 13) | 写进 networkd 配置 | | networkd 管的其他网卡(Ubuntu 22.04 等) | networkd-dispatcher 钩子 | | 其他有 systemd 的机器 | 开机执行一次的单元 | 写进 networkd 配置时不重载网络, networkd 下次重启或开机后才完全生效. systemd 255 以下的机器, 网络服务重启后要等网卡重连或开机才补回. 用了 `harden --swap` 还会创建 `/swapfile` 并往 `/etc/fstab` 加一行 —— 这两个 `rollback` 默认不动, 要一并撤销加 `--purge-swap`. 缺 iperf3 时经你确认后会用包管理器安装它. ## 已知限制 - 瓶颈在国际链路而非端口时, 整形不会带来提升, 但输出看起来一切正常 - 扫满区间仍没找到拐点时不会整形, 结果页会说明原因; 已知限速值的话用 `m` 手动指定 - 需要 Linux + systemd + iproute2. OpenVZ/LXC 上 `tc` 和 `initcwnd` 可能受限 - `sweep` 需要一台近处的 iperf3 对端 ## 从 nettune 升级 老机器上的产物文件名还是 `nettune-*`, 新版本会自动检测并搬迁, 快照和 rollback 都保留. 直接跑新版即可. ## 许可证 [MIT](LICENSE)