给 Solana 发很多交易的话,客户端和 RPC 之间的 HTTP 层重要。朴素的 HTTP 用法每次调用加几十到几百毫秒——来自连接建立、TLS 握手、连接复用缺失。延迟敏感代码,这是你延迟预算里有意义的一部分。
这篇覆盖怎么调 HTTP 客户端给 Solana RPC:keep-alive 设置、连接池、TLS 优化、把生产级客户端跟朴素客户端分开的模式。
每次 HTTP 调用到底做什么
你代码调 RPC 方法,HTTP 请求过这些步骤:
- DNS 查询(通常缓存)
- TCP 连接建立(~1 round trip)
- TLS 握手(~1-2 round trip)
- 发 HTTP 请求
- 服务器处理
- 收 HTTP 响应
步骤 2-3 是连接建立。它们贵——常 50-200ms,看地理。每次调用都做,开销累加。
修法:保持连接开着复用。这是"keep-alive"或"持久连接"。
Keep-Alive 默认
大多数 HTTP 客户端默认开 keep-alive——但默认不总调好给高量用。
Node.js 现代 fetch: 有默认 agent 带 keep-alive。默认能用但没调给高量用。
浏览器 fetch: 浏览器控制;你不调。
Node 里的 Axios: 用 Node HTTP agent。默认相似。
Rust 里的 Reqwest: 默认有连接池。可配。
Python requests: 每调用是默认;keep-alive 用 Session。
生产代码你通常想:
- 验证 keep-alive 开
- 给你并发配池大小
- 适当调超时
Node.js 里配 Keep-Alive
高量 Node.js 代码:
import { Connection } from "@solana/web3.js";
import { Agent } from "undici";
const agent = new Agent({
keepAliveTimeout: 30_000, // 连接闲 30s
keepAliveMaxTimeout: 600_000, // 最大 keep-alive 10min
connect: {
timeout: 10_000, // 连接超时 10s
},
pipelining: 0, // 禁用 pipelining(RPC 不受益)
});
const connection = new Connection(RPC_URL, {
commitment: "processed",
});
具体 API 看你 web3.js 版本。当前模式查 SDK 文档。
连接池规模
池大小 = 最大并发连接数。要考虑:
太小: 并发请求阻塞等连接。负载下延迟峰值。
太大: 内存开销。一些服务商按连接数限。
合适的规模: 匹配你的峰值并发。大多数机器人 10-50 够用。高量后端,几百。
Solana RPC 这块,同一个 RPC 主机会处理你大量请求;那个主机的池大小,要匹配你到它的峰值并发。
TLS 握手优化
TLS 握手在连接建立加 1-2 round trip。一旦 keep-alive 工作,是每连接一次性成本。但:
TLS 会话恢复能减少后续握手成本。大多数现代客户端自动做。
HTTP/2 允许一个连接复用多个请求。减少需要的总连接数。大多数 Solana RPC 支持 HTTP/2。
TLS 1.3 比老版本握手短。大多数现代栈默认。
大多数生产配置默认就行。你测过握手时间是瓶颈才调。
常见 HTTP 层错误
每请求一个新 HTTP 客户端。 扔掉连接复用。症状:高尾部延迟、负载下慢。
不小心禁用 keep-alive。 一些配置关掉它。验证开。
池给并发太小。 池阻塞变瓶颈、不是网络。
池太大。 内存浪费;一些服务商按连接数限流。
长寿连接累积问题。 有时非常长寿的 TCP 连接发展出问题。合理最大 keep-alive(5-30 分钟)平衡复用和刷新。
不处理重置连接。 服务器有时关连接;客户端要检测、刷新、不崩。
测 HTTP 层性能
简单诊断:
const start = Date.now();
const result = await connection.getLatestBlockhash();
const latency = Date.now() - start;
console.log(`延迟: ${latency}ms`);
正常运营时跑。看到该相似调用的延迟变化大,怀疑 HTTP 层问题。
更详细分析:
- 检查 TCP 连接生命周期(用
tcpdump这种工具或浏览器 devtools 给浏览器代码) - 跟请求执行分开计时 TLS 握手
- profile 新建 vs 复用连接的总数
大多数问题从每调用计时直方图就能看出来。
Solana 特定 HTTP 模式
Solana 写流量这块:
每 RPC 一个客户端。 别跨 RPC 共享客户端。每个 RPC 连接该有自己池。
写侧上亚秒级超时。 你 sendTransaction 超过 2-3 秒,出问题了。别等几分钟。
激进重试是 HTTP 错误、不是交易错误。 HTTP 调用失败,重试。交易提交了没上链,那是交易级问题。
确认轮询用单独连接。 发送后,轮询确认能用不同连接、不阻塞下次发送。
这周可以做什么
优化你 Solana 客户端:
- 验证 keep-alive 开。 大多数栈默认开但验证。
- 给你并发配池大小。 匹配峰值负载。
- 设显式超时。 连接、请求、总。别靠默认。
- Profile 你 HTTP 层。 每调用延迟直方图告诉故事。
- 能用就用 HTTP/2。 复用在负载下帮上。
- Rust 项目里,显式配置你的 reqwest 客户端。 别只靠
Client::new()的默认值。 - 别过度调。 大多数机器人不要极端 HTTP 优化;大多数问题在 RPC 层、不在 HTTP 层。
调好的 HTTP 试一下 BoltTx
BoltTx 端点支持 HTTP/2 和标准 keep-alive 模式。客户端做合适配置就行:
import { Connection } from "@solana/web3.js";
const connection = new Connection(
"https://bolttx.io/?api-key=YOUR_API_KEY",
"processed"
);
免费档注册。亚秒级确认行为假设客户端侧 HTTP 调好了。
常见问题
机器人一次只发一笔交易,keep-alive 帮吗? 第二笔起一点点。高量代码最有用。
该给 Solana RPC 用 HTTP/2 吗? 能用就用。大多数现代服务商支持。
流式订阅(WebSocket 之外)和 HTTP 调用比怎么样? 高量流式负载下,专用流式协议比 HTTP RPC 有优势。请求-响应类的 RPC 调用,HTTP/2 配好 keep-alive 已经够用。
能用 HTTP pipelining 吗? 理论上是;实际给 RPC 很少受益。用 HTTP/2 复用替代。
TLS 握手出现在我 Solana 发送延迟里吗? 只第一次连接。一旦 keep-alive 工作,后续发送跳过握手。