摘要
Solana WebSocket API 允许您订阅实时更新,如账户变更、交易确认和新时隙,而无需轮询。本文解释了核心订阅方法、如何连接到 WebSocket 端点,以及如何在生产中处理常见故障模式。
Solana 的 WebSocket API 是实时 dApp、索引器和交易机器人的支柱。与需要轮询状态更改的 HTTP JSON-RPC 不同,WebSocket 订阅会在更改发生时立即推送更新。本文涵盖了基本的订阅方法、如何连接到 WebSocket 端点,以及在生产环境中需要注意的事项。
快速决策指南:何时使用 WebSocket 与 HTTP
在深入代码之前,请决定您是否真的需要 WebSocket。如果您的应用仅在用户操作时获取账户余额,HTTP 轮询更简单可靠。如果您需要在几秒钟内对状态更改做出反应——例如监控钱包的收款或跟踪 DEX 池——WebSocket 订阅可节省带宽并减少延迟。
在以下情况下使用 WebSocket:
- 您需要账户余额、代币转账或程序状态的实时更新。
- 您正在构建订单簿、价格行情或实时仪表板。
- 您希望避免轮询速率限制并减少 RPC 提供商的负载。
在以下情况下坚持使用 HTTP:
- 您的数据需求是偶尔的,并且可以容忍几秒钟的延迟。
- 您正在进行一次性查询或批量读取。
- 您需要 WebSocket 不提供的存档数据或历史状态。
对于大多数生产应用,混合方法效果最佳:使用 HTTP 获取初始状态,使用 WebSocket 获取实时更新。这可以保持较低的连接数和数据的新鲜度。
Solana WebSocket 端点:连接所需的信息
要使用 Solana WebSocket API,您需要一个 WebSocket 端点 URL。OnFinality 为 Solana 主网提供了一个公共 WebSocket 端点:
wss://solana.api.onfinality.io/public-ws
此端点支持通过 WebSocket 的标准 Solana JSON-RPC。为了获得更高的吞吐量和专用资源,您可以通过 OnFinality 配置专用节点,该节点为您提供具有自己速率限制的私有 WebSocket URL。
连接时,请记住以下细节:
- 传输:需要 WebSocket(wss://);主网端点不支持纯 ws://。
- 身份验证:公共端点可能有速率限制;对于生产环境,请使用 API 密钥或专用端点。
- 网络:确保您连接到正确的网络(主网与 devnet)。Devnet 有单独的端点,例如 Solana Devnet 页面 上列出的端点。
您应该了解的核心订阅方法
Solana WebSocket API 镜像了 HTTP JSON-RPC 方法,但添加了订阅变体。以下是最常用的方法:
| 方法 | 描述 | 用例 |
|---|---|---|
accountSubscribe | 当账户的 lamports 或数据更改时通知 | 监控钱包余额、代币账户 |
logsSubscribe | 流式传输与过滤器匹配的交易日志 | 跟踪程序活动、调试交易 |
programSubscribe | 当程序拥有的任何账户更改时发出警报 | 观察 DEX 池、NFT 铸造 |
slotSubscribe | 每次确认新时隙时发送通知 | 跟踪链进度、同步索引器 |
signatureSubscribe | 当交易签名被确认时通知 | 实时确认用户交易 |
rootSubscribe | 当设置新根时发送通知 | 高级共识跟踪 |
每个订阅返回一个订阅 ID,您稍后可以使用该 ID 取消订阅。您还需要处理初始响应和后续通知。
连接到 Solana WebSocket API:JavaScript 示例
以下是一个使用 Node.js 中 ws 库订阅账户更新的最小示例:
const WebSocket = require('ws');
const ws = new WebSocket('wss://solana.api.onfinality.io/public-ws');
ws.on('open', function open() {
// Subscribe to account changes for a specific public key
const accountPubkey = 'YourBase58PublicKeyHere';
ws.send(JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'accountSubscribe',
params: [
accountPubkey,
{
encoding: 'base64',
commitment: 'confirmed'
}
]
}));
});
ws.on('message', function incoming(data) {
const message = JSON.parse(data);
if (message.method === 'accountNotification') {
console.log('Account update:', message.params.result);
// Handle the update, e.g., update your UI or database
} else if (message.id === 1) {
console.log('Subscription ID:', message.result);
// Store the subscription ID to cancel later if needed
}
});
ws.on('error', function error(err) {
console.error('WebSocket error:', err);
});
请记住将 YourBase58PublicKeyHere 替换为真实的账户地址。对于生产环境,您需要添加重连逻辑并处理背压。
理解通知负载
当订阅触发时,您会收到一个通知对象,其中包含 method 字段,如 accountNotification、logsNotification 等。params.result 包含实际数据。对于 accountNotification,结果包括账户的 lamports、数据和所有者。对于 logsNotification,您会获得日志和签名。
以下是 accountNotification 负载的示例:
{
"jsonrpc": "2.0",
"method": "accountNotification",
"params": {
"result": {
"context": {
"slot": 123456
},
"value": {
"lamports": 1000000,
"data": {
"program": "",
"parsed": null,
"space": 0
},
"owner": "11111111111111111111111111111111",
"executable": false,
"rentEpoch": 0
}
},
"subscription": 123
}
}
请注意,如果您请求了该编码,data 字段可能是 base64 编码的。您需要解码它以读取账户的状态。
处理重连和心跳
WebSocket 连接可能因网络问题、服务器重启或空闲超时而断开。在生产环境中,您必须实现重连逻辑。以下是一个简单的模式:
function connect() {
const ws = new WebSocket('wss://solana.api.onfinality.io/public-ws');
ws.on('open', () => {
// Resubscribe to all active subscriptions
activeSubscriptions.forEach(sub => ws.send(sub));
});
ws.on('close', () => {
console.log('Connection closed, reconnecting in 5s...');
setTimeout(connect, 5000);
});
ws.on('error', (err) => {
console.error('Error:', err);
ws.close();
});
// Send a ping every 30s to keep the connection alive
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.ping();
}
}, 30000);
}
connect();
重新连接时,您需要重新订阅所有以前的订阅,因为服务器在断开连接后会忘记它们。保留订阅请求列表并在打开时重放它们。
常见陷阱及如何避免
- 不处理背压:如果您的应用无法足够快地处理通知,您将落后。使用队列或缓冲区来管理传入的消息。
- 忽略承诺级别:订阅默认是
finalized?实际上,某些方法的默认值是finalized,但您通常希望使用confirmed以获得更快的更新。明确指定承诺级别以匹配您的需求。 - 订阅太多账户:每个订阅都会消耗资源。如果可能,将相关账户批处理到单个程序订阅中。
- 忘记取消订阅:当您不再需要更新时,使用订阅 ID 调用
accountUnsubscribe以释放资源。 - 将 HTTP 端点用于 WebSocket:确保您使用的是
wss://URL,而不是https://。
生产就绪检查清单
在部署基于 WebSocket 的应用之前,请完成此检查清单:
- 使用具有足够速率限制的专用 WebSocket 端点以满足您的工作负载。
- 实现具有指数退避的重连。
- 重新连接后重新订阅所有活动订阅。
- 使用心跳或 ping 监控连接健康状况。
- 设置连接断开和订阅失败的警报。
- 首先使用 Solana Devnet 端点 在 devnet 上进行测试。
- 考虑使用像 OnFinality 这样的托管服务来处理基础设施扩展。
为 WebSocket 负载选择合适的基础设施
WebSocket 连接是长寿命的,并且在服务器端可能占用大量资源。如果您运行自己的 Solana 节点,则需要管理 WebSocket 服务器并确保它可以处理许多并发连接。这是托管 RPC 提供商可以节省时间的地方。
OnFinality 提供公共和专用的 Solana 端点。公共端点非常适合开发和轻度使用,但对于具有高消息吞吐量的生产应用,专用节点为您提供专用资源和更可预测的性能。您可以在我们的 RPC 定价页面 上比较选项,并在我们的 网络页面 上查看所有支持的网络。
评估提供商时,请考虑:
- 连接限制:允许多少并发 WebSocket 连接?
- 消息吞吐量:提供商能否处理您的订阅量?
- 正常运行时间和故障转移:提供商是否提供冗余基础设施?
- 支持:是否有团队可以帮助解决问题?
关键要点
- Solana 的 WebSocket API 支持账户、日志、程序、时隙和签名的实时订阅。
- 使用
wss://端点,而不是https://,并指定正确的承诺级别。 - 实现重连逻辑并在断开后重新订阅以维持可靠的流。
- 选择能够处理您的 WebSocket 负载的提供商;对于生产环境,请考虑专用节点。
- 在上线前在 devnet 上进行测试,以避免代价高昂的错误。
常见问题解答
Solana 的 HTTP 和 WebSocket API 有什么区别?
HTTP API 是请求-响应,因此您需要轮询数据。WebSocket API 在更改发生时将更新推送给您,使其对于实时应用更高效。
如何获取 Solana WebSocket 端点?
您可以使用公共端点,如 wss://solana.api.onfinality.io/public-ws,或配置专用节点以获得更高的限制。对于 devnet,请使用 devnet 特定的端点。
WebSocket 订阅应使用什么承诺级别?
这取决于您的用例。confirmed 对于大多数应用来说是一个很好的默认值,因为它平衡了速度和可靠性。finalized 较慢,但确保数据不可逆。processed 最快,但可能包含未确认的数据。
我可以使用一个订阅订阅多个账户吗?
不可以,accountSubscribe 接受单个账户。要监控多个账户,您可以创建多个订阅,或者如果它们都由同一个程序拥有,则使用 programSubscribe。
如何处理 WebSocket 断开连接?
使用退避策略实现自动重连,并在重新连接后重新订阅所有活动订阅。保留订阅请求列表以进行重放。
OnFinality 是否支持 Solana 的 WebSocket?
是的,OnFinality 为 Solana 主网和 devnet 提供 WebSocket 端点。您可以在相应的网络页面上找到 URL。
公共 WebSocket 端点的速率限制是多少?
公共端点有速率限制以确保公平使用。对于生产环境,请考虑使用专用节点以获得更高的限制和更好的性能。有关详细信息,请查看我们的 定价页面。
我可以将 WebSocket 用于 Solana devnet 吗?
是的,Solana devnet 支持 WebSocket 订阅。使用 Solana Devnet 页面 中的 devnet 端点。
监控 WebSocket 健康状况的最佳方法是什么?
定期发送 ping 并跟踪消息之间的时间。设置错过心跳或连接断开的警报。
使用 WebSocket 订阅是否有任何相关成本?
在公共端点上,可能有速率限制但没有直接成本。专用节点根据您的计划收费。有关更多信息,请参阅 RPC 定价。
如何取消订阅?
使用相应的 *Unsubscribe 方法,例如 accountUnsubscribe,并传递订阅时收到的订阅 ID。
并发 WebSocket 连接的最大数量是多少?
这取决于您的提供商。公共端点可能具有较低的限制;专用节点可以处理更多。请联系您的提供商了解具体情况。
我可以使用 Python 将 WebSocket 用于 Solana 吗?
是的,您可以使用 websockets 或 solana-py 等库连接到 WebSocket 端点。JSON-RPC 格式相同。
slotSubscribe 和 rootSubscribe 有什么区别?
slotSubscribe 在新时隙被确认时通知您,而 rootSubscribe 在设置新根(已最终确定的时隙)时通知。根更新不那么频繁。
如何获取订阅 ID?
服务器响应您的订阅请求,在 result 字段中包含订阅 ID 的 JSON-RPC 响应。
如果我发送带有无效账户的订阅请求会发生什么?
服务器将返回错误响应。确保账户存在并且是有效的 base58 公钥。
我可以订阅特定程序的日志吗?
是的,使用 logsSubscribe 并包含 mentions 过滤器的程序 ID。
如何处理大量通知?
使用消息队列缓冲通知并异步处理它们。考虑批量写入数据库。
所有 Solana RPC 提供商都支持 WebSocket 吗?
大多数提供商支持 WebSocket,但请查看其文档。OnFinality 在公共和专用端点上均支持 WebSocket。
测试 WebSocket 订阅的最佳方法是什么?
使用 wscat 等工具或编写一个简单的 Node.js 脚本订阅已知账户并验证您是否收到更新。
我可以使用 ethers.js 将 WebSocket 用于 Solana 吗?
不可以,ethers.js 用于 EVM 链。对于 Solana,请使用具有内置 WebSocket 支持的 @solana/web3.js。
如何使用 @solana/web3.js 设置 WebSocket 连接?
使用 new Connection('wss://...'),然后调用 onAccountChange 等方法进行订阅。
WebSocket 订阅的默认承诺是什么?
某些方法的默认值是 finalized,但您应始终明确指定承诺级别以避免意外。
WebSocket 是否有任何安全注意事项?
使用 wss:// 加密传输中的数据。避免通过纯 ws:// 发送敏感数据。
如何监控 WebSocket 连接的健康状况?
每 30 秒发送一次 ping 并监听 pong。如果您没有收到 pong,则认为连接已死并重新连接。
我可以同时将 WebSocket 用于 Solana 主网和 devnet 吗?
是的,您可以打开到每个网络端点的单独连接。
管理多个订阅的最佳实践是什么?
保留订阅 ID 到其用途的映射,并在重新连接时重新订阅。不再需要时取消订阅。
OnFinality 是否为其他网络提供 WebSocket 支持?
是的,OnFinality 支持许多网络的 WebSocket。有关详细信息,请查看 网络页面。
如何快速开始使用 Solana WebSocket?
使用公共端点和简单脚本订阅测试账户。然后扩展到您的用例。
使用 WebSocket 时常见错误有哪些?
常见错误包括无效 JSON、不支持的方法或速率限制。检查错误消息并相应调整。
我可以将 WebSocket 用于 Solana 移动应用吗?
是的,但请注意电池和网络使用情况。考虑使用支持后台连接的库。
如何确保我的 WebSocket 连接安全?
始终使用 wss:// 并验证服务器证书。避免通过 WebSocket 发送私钥。
accountSubscribe 和 programSubscribe 有什么区别?
accountSubscribe 监控单个账户,而 programSubscribe 监控程序拥有的所有账户。使用 programSubscribe 进行更广泛的监控。
我可以按程序 ID 过滤日志吗?
是的,在 logsSubscribe 中使用 mentions 过滤器,仅接收提及特定程序的日志。
如何取消订阅?
使用订阅 ID 发送相应的 *Unsubscribe 方法。例如,使用 ID 的 accountUnsubscribe。
WebSocket 的最大消息大小是多少?
Solana 的 WebSocket 消息可能很大,尤其是账户数据。确保您的客户端可以处理大型负载。
如何处理 WebSocket 上的速率限制?
如果您遇到速率限制,请减少订阅数量或升级到具有更高限制的专用节点。
我可以将 WebSocket 用于 Solana 无服务器功能吗?
无服务器功能不适合长寿命的 WebSocket 连接。使用持久服务器或托管服务。
学习 Solana WebSocket 的最佳方法是什么?
从官方 Solana 文档开始,并使用公共端点进行实验。然后阅读提供商特定的指南。
OnFinality 是否为 Solana devnet 提供 WebSocket?
是的,您可以在 Solana Devnet 页面 上找到 devnet WebSocket 端点。
如何获得 WebSocket 问题的支持?
联系您的 RPC 提供商的支持团队。OnFinality 为其服务提供支持。
Solana WebSocket 的未来是什么?
Solana 不断改进其 API。请关注官方公告以获取最新信息。
我可以使用 Go 应用程序将 WebSocket 用于 Solana 吗?
是的,使用 gorilla/websocket 等库连接到 WebSocket 端点。
如何在没有真实账户的情况下测试 WebSocket 订阅?
您可以订阅已知账户,如系统程序,或在 devnet 上使用测试账户。
处理 WebSocket 错误的最佳方法是什么?
记录错误并实现重试逻辑。对于持续错误,请提醒您的团队。
公共端点上的 WebSocket 订阅是否有任何成本?
公共端点是免费的,但有速率限制。对于生产环境,请考虑付费计划。
如何为我的应用选择 WebSocket 和 HTTP?
评估您的延迟要求和数据量。对于实时使用 WebSocket,对于偶尔查询使用 HTTP。
confirmed 和 finalized 有什么区别?
confirmed 表示交易已被集群接受,而 finalized 表示不可逆。使用 confirmed 以获得更快的更新。
我可以使用 Rust 应用程序将 WebSocket 用于 Solana 吗?
是的,使用 tokio-tungstenite 等库进行连接。
如何通过 WebSocket 获取当前时隙号?
订阅 slotSubscribe,您将收到时隙更新。
监控多个账户的最佳方法是什么?
如果它们共享一个程序,请使用 programSubscribe,或创建多个 accountSubscribe 调用。
如何处理 WebSocket 背压?
使用队列缓冲消息并以受控速率处理它们。
我可以使用 C# 应用程序将 WebSocket 用于 Solana 吗?
是的,使用 .NET 中的 ClientWebSocket 等库。
确保 WebSocket 连接高可用性的最佳方法是什么?
使用多个连接和故障转移逻辑。考虑具有冗余基础设施的提供商。
如何开始使用 OnFinality 的 Solana WebSocket?
访问 Solana 网络页面 获取端点和文档。
WebSocket 订阅的限制是什么?
订阅是短暂的,需要处理重连。此外,它们仅提供当前状态,不提供历史数据。
我可以将 WebSocket 用于 Solana 移动应用吗?
是的,但请注意电池和网络使用情况。考虑使用支持后台连接的库。
如何确保我的 WebSocket 连接安全?
始终使用 wss:// 并验证服务器证书。避免通过 WebSocket 发送私钥。
accountSubscribe 和 programSubscribe 有什么区别?
accountSubscribe 监控单个账户,而 programSubscribe 监控程序拥有的所有账户。使用 programSubscribe 进行更广泛的监控。
我可以按程序 ID 过滤日志吗?
是的,在 logsSubscribe 中使用 mentions 过滤器,仅接收提及特定程序的日志。
如何取消订阅?
使用订阅 ID 发送相应的 *Unsubscribe 方法。例如,使用 ID 的 accountUnsubscribe。
WebSocket 的最大消息大小是多少?
Solana 的 WebSocket 消息可能很大,尤其是账户数据。确保您的客户端可以处理大型负载。
如何处理 WebSocket 上的速率限制?
如果您遇到速率限制,请减少订阅数量或升级到具有更高限制的专用节点。
我可以将 WebSocket 用于 Solana 无服务器功能吗?
无服务器功能不适合长寿命的 WebSocket 连接。使用持久服务器或托管服务。
学习 Solana WebSocket 的最佳方法是什么?
从官方 Solana 文档开始,并使用公共端点进行实验。然后阅读提供商特定的指南。
OnFinality 是否为 Solana devnet 提供 WebSocket?
是的,您可以在 Solana Devnet 页面 上找到 devnet WebSocket 端点。
如何获得 WebSocket 问题的支持?
联系您的 RPC 提供商的支持团队。OnFinality 为其服务提供支持。
Solana WebSocket 的未来是什么?
Solana 不断改进其 API。请关注官方公告以获取最新信息。
我可以使用 Go 应用程序将 WebSocket 用于 Solana 吗?
是的,使用 gorilla/websocket 等库连接到 WebSocket 端点。
如何在没有真实账户的情况下测试 WebSocket 订阅?
您可以订阅已知账户,如系统程序,或在 devnet 上使用测试账户。
处理 WebSocket 错误的最佳方法是什么?
记录错误并实现重试逻辑。对于持续错误,请提醒您的团队。
公共端点上的 WebSocket 订阅是否有任何成本?
公共端点是免费的,但有速率限制。对于生产环境,请考虑付费计划。
如何为我的应用选择 WebSocket 和 HTTP?
评估您的延迟要求和数据量。对于实时使用 WebSocket,对于偶尔查询使用 HTTP。
confirmed 和 finalized 有什么区别?
confirmed 表示交易已被集群接受,而 finalized 表示不可逆。使用 confirmed 以获得更快的更新。
我可以使用 Rust 应用程序将 WebSocket 用于 Solana 吗?
是的,使用 tokio-tungstenite 等库进行连接。
如何通过 WebSocket 获取当前时隙号?
订阅 slotSubscribe,您将收到时隙更新。
监控多个账户的最佳方法是什么?
如果它们共享一个程序,请使用 programSubscribe,或创建多个 accountSubscribe 调用。
如何处理 WebSocket 背压?
使用队列缓冲消息并以受控速率处理它们。
我可以使用 C# 应用程序将 WebSocket 用于 Solana 吗?
是的,使用 .NET 中的 ClientWebSocket 等库。
确保 WebSocket 连接高可用性的最佳方法是什么?
使用多个连接和故障转移逻辑。考虑具有冗余基础设施的提供商。
如何开始使用 OnFinality 的 Solana WebSocket?
访问 Solana 网络页面 获取端点和文档。
WebSocket 订阅的限制是什么?
订阅是短暂的,需要处理重连。此外,它们仅提供当前状态,不提供历史数据。