本文介绍了如何使用 Quicknode Streams 的压缩功能来减少区块链数据的带宽和有效载荷大小。通过启用压缩,用户可以在过滤后的数据上减少高达 90% 的带宽,而无需更改核心工作流程。文章提供了启用压缩的步骤、在 Node.js Express 服务器中实现解压缩的方法,以及实际示例说明带宽减少的效果。
Quicknode Streams 通过过滤帮助你仅接收你需要的相关区块链数据。启用压缩后,你可以在不改变核心工作流程的情况下,将过滤后的数据的带宽和交付有效载荷大小减少高达 90%。
本指南将引导你完成为 Streams 启用压缩、在应用程序中实施解压缩以及通过实际示例了解带宽减少的过程。
gzip 数据,包括自动和手动方法Quicknode Webhooks
喜欢 Streams 提供的实时数据功能吗?查看我们的新产品 Webhooks。它构建在 Streams 之上,并在简化的、易于使用的界面中提供预定义的过滤器模板和压缩功能。Webhooks 专门为 简单、事件驱动的通知 而设计,无需 Streams 的完整复杂性,即可更快地将实时数据发送到你的 HTTP 端点。
通过 Streams,你拥有过滤功能,可以仅接收你需要的相关链上数据。当你向过滤后的 Streams 添加压缩时,你可以显著减少带宽和交付有效载荷大小。
让我们看一个真实世界的例子,使用单个 Ethereum 区块 内的 token 转移的有效载荷大小:
注意:所有数据大小均为估计值,可能因处理的实际数据而异。

由于 Ethereum 上每月大约有 220,000 个区块,因此带宽和交付有效载荷大小的减少可能是巨大的:
| 方法 | 每月数据大小 |
|---|---|
| 未过滤的原始数据 | 218 GB |
| 过滤 | 135 GB |
| 过滤 + 压缩 | 13 GB |
在本指南中,我们将为具有 webhook 目标地的 Stream 启用压缩,并设置一个 Node.js Express 服务器来处理压缩的数据。
你只需在 Quicknode 仪表板 中单击一下即可启用压缩。
注意:压缩功能适用于 Webhook 和 S3 目标地。
启用压缩后,Quicknode 将开始以压缩的 gzip 格式发送此 Stream 的所有 webhook 有效载荷。Webhook 还将包括头 Content-Encoding: gzip,以表明有效载荷已压缩。因此,你的应用程序应检查此头以确定是否需要解压缩。
现在,让我们构建将接收压缩数据的 Node.js Express 服务器。我们将在你的服务器启动并运行后完成 Stream 的创建。
要处理压缩数据,你需要在应用程序中解压缩它。在此示例中,我们将使用 Node.js Express 服务器来接收压缩数据并解压缩它。
创建一个新的 Node.js 项目:
mkdir streams-compression-example
cd streams-compression-example
npm init -y
安装服务器所需的依赖项:
npm install express
以下代码设置了一个基本的 Express 服务器,以演示如何处理来自 Streams 的压缩的有效载荷。它包括两个不同的路由:
/webhook/auto:这是主要路由。它使用 express.raw({ inflate: true }) 中间件,该中间件会自动检测 Content-Encoding: gzip 头并解压缩请求主体。这使得有效载荷可以直接在 req.body 中使用,就像它从未被压缩一样。
/webhook/manual:这个可选路由向你展示了如果你需要更多地控制该过程,如何手动处理解压缩。我们将在本指南的后面添加此路由的代码。
创建一个服务器文件 (app.js) 并添加以下代码:
app.js
const express = require("express");
const zlib = require("zlib");
const app = express();
// Helper function to convert bytes to kilobytes
// 辅助函数,用于将字节转换为千字节
const bytesToKB = (bytes) => (bytes / 1024).toFixed(2);
// Route 1: Auto-inflate enabled (Express handles decompression)
// 路由 1:启用自动解压缩(Express 处理解压缩)
app.post(
"/webhook/auto",
express.raw({ inflate: true, type: "*/*", limit: "10mb" }), // Adjust limit as needed
// 根据需要调整限制
(req, res) => {
console.log("\n=== AUTO-INFLATE ROUTE ===");
console.log("Headers:", req.headers);
// req.body is already decompressed
// req.body 已经被解压缩
const decompressedSize = req.body.length;
console.log(
`Decompressed payload size: ${bytesToKB(
decompressedSize
)} KB (${decompressedSize} bytes)`
);
try {
const data = JSON.parse(req.body.toString());
console.log("Payload data:", data);
res.status(200).json({
status: "OK",
method: "auto-inflate",
decompressedSizeKB: bytesToKB(decompressedSize),
});
} catch (err) {
console.error("Parse error:", err);
res.status(400).send("Invalid JSON");
}
}
);
// Route 2: Manual decompression (inflate disabled)
// 路由 2:手动解压缩(禁用解压缩)
// This route is optional and shows how to manually decompress if needed
// 此路由是可选的,展示了如果需要如何手动解压缩
// Code will be added later in this guide
// 代码将在本指南后面添加
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Webhook server listening on port ${PORT}`);
console.log(`Test the endpoints:`);
console.log(` - http://localhost:${PORT}/webhook/auto (auto-inflate)`);
console.log(` - http://localhost:${PORT}/webhook/manual (manual decompression)`);
});
启动你的服务器:
node app.js
要使用 Streams 测试你的服务器,你需要将其暴露给互联网。你可以使用 ngrok 之类的工具或将其部署到云服务。对于本地测试,请在新终端窗口中运行以下命令:
ngrok http 3000 # or other port if you changed it
# 如果你更改了端口,则使用其他端口
这会将你的服务器暴露给互联网上的一个随机端口。复制转发 URL(例如,https://xxxx.ngrok.io)并通过在末尾添加 /webhook/auto 将其粘贴到 Streams 目标 URL 中。(例如,https://xxxx.ngrok.io/webhook/auto)
设置目标 URL 后,你可以通过将示例有效载荷发送到你的 Stream 来测试你的服务器。
首先,通过单击 Quicknode 仪表板 中的“检查连接”按钮来检查连接。然后,通过单击“发送有效载荷”按钮将示例有效载荷发送到你的 Stream。这将触发对你的服务器的 webhook 调用。
服务器将记录头、解压缩的有效载荷大小和已解析的 JSON 数据。由于 有效载荷 是自动解压缩的,因此你可以通过检查请求中的 content-length 头来检查实际的压缩有效载荷大小(以字节为单位)。发送测试有效载荷后,检查运行 ngrok 的终端,你将看到类似以下内容:

如你所见,服务器会自动解压缩 有效载荷,你可以直接在 req.body 中访问数据。就这样。
在 Express 中间件中将 inflate 选项设置为 true 会自动解压缩 有效载荷。但是,如果你因任何原因要手动解压缩 有效载荷,则可以使用 zlib 模块来执行此操作。这是一个如何执行此操作的示例。只需将此路由添加到你现有的 app.js 文件中。
此代码段将 /webhook/manual 路由添加到你的服务器。与自动解压缩路由不同,此路由处理原始请求主体。它将传入的压缩数据收集到缓冲区中,检查 content-encoding 头,如果它是 gzip,则使用 Node.js 的内置 zlib.gunzip 方法解压缩 有效载荷。
此方法还会计算并记录压缩率,向你显示压缩数据和解压缩数据之间的确切大小差异。
app.js (续)
// Continue from the previous app.js code snippet
// 从之前的app.js代码片段继续
// Route 2: Manual decompression (inflate disabled)
// 路由 2:手动解压缩(禁用解压缩)
// This route is optional and shows how to manually decompress if needed
// 此路由是可选的,展示了如果需要如何手动解压缩
app.post("/webhook/manual", (req, res) => {
console.log("\n=== MANUAL DECOMPRESSION ROUTE ===");
console.log("Headers:", req.headers);
// Store the content-encoding header and then delete it
// 存储 content-encoding 头,然后删除它
// to prevent Express from throwing an error
// 以防止 Express 抛出错误
const contentEncoding = req.headers["content-encoding"];
delete req.headers["content-encoding"];
let chunks = [];
req.on("data", (chunk) => {
chunks.push(chunk);
});
req.on("end", () => {
const compressedBuffer = Buffer.concat(chunks);
const compressedSize = compressedBuffer.length;
console.log(
`Compressed payload size: ${bytesToKB(
compressedSize
)} KB (${compressedSize} bytes)`
);
// Check if content was compressed
// 检查内容是否被压缩
if (contentEncoding === "gzip") {
zlib.gunzip(compressedBuffer, (err, decompressedBuffer) => {
if (err) {
console.error("Decompression error:", err);
return res.status(500).send("Decompression error");
}
const decompressedSize = decompressedBuffer.length;
console.log(
`Decompressed payload size: ${bytesToKB(
decompressedSize
)} KB (${decompressedSize} bytes)`
);
const compressionRatio = (
(1 - compressedSize / decompressedSize) *
100
).toFixed(1);
console.log(`Compression ratio: ${compressionRatio}% reduction`);
try {
const data = JSON.parse(decompressedBuffer.toString());
console.log("Payload data:", data);
res.status(200).json({
status: "OK",
method: "manual-decompression",
compressedSizeKB: bytesToKB(compressedSize),
decompressedSizeKB: bytesToKB(decompressedSize),
compressionRatio: `${compressionRatio}%`,
});
} catch (err) {
console.error("Parse error:", err);
res.status(400).send("Invalid JSON");
}
});
}
});
req.on("error", (err) => {
console.error("Request error:", err);
res.status(500).send("Request error");
});
});
之后,你可以通过将压缩的 有效载荷 发送到 /webhook/manual 来测试手动解压缩路由。日志输出将显示压缩大小、解压缩大小和压缩率,如下所示。

测试压缩后,你现在可以单击 Quicknode 仪表板 中的“创建 Stream”按钮来最终确定并激活你的 Stream 以接收压缩的实时数据。
你已成功学习如何为 Quicknode Streams 启用压缩以及如何在 Express.js 应用程序中处理压缩的数据。该实现非常简单,只需几行代码即可处理解压缩,而节省是立竿见影且巨大的。
如果你有任何疑问,请直接 联系我们。如果你有任何想法或建议,例如你希望我们支持的新的目标地、功能、指标或数据集。
此外,请关注我们的 Twitter,加入我们的 Discord 和 Telegram 公告频道,以了解最新动态。
如果你有任何反馈或对新主题的要求,请 告诉我们。我们很乐意听取你的意见。
- 原文链接: quicknode.com/guides/qui...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!