通过数据压缩降低 Streams 成本

本文介绍了如何通过QuickNode Streams的数据压缩功能来降低区块链数据的成本。通过启用压缩,可以在已经过滤的数据基础上,进一步节省高达90%的成本。文章详细说明了如何在QuickNode控制台中启用GZIP压缩,并提供了使用Node.js Express服务器处理压缩数据的示例代码,包括自动解压和手动解压两种方法。

概述

QuickNode Streams 已经通过过滤区块链数据,只保留你需要的部分来帮助你降低成本。但是,如果你能进一步降低这些成本呢?启用压缩后,你可以在已过滤的数据上额外节省高达 90% 的成本,而无需改变你的核心工作流程。

本指南将引导你完成为 Streams 启用压缩、在你的应用程序中实现解压缩,以及通过实际示例计算你潜在的成本节省。

你将做什么

  • 了解 Streams 过滤和压缩的综合成本节省效果
  • 为你的 Streams 目的地启用压缩
  • 在 Node.js Express 服务器中处理压缩的 gzip 数据,包括自动和手动方法

你将需要什么

  • 具有付费计划的 QuickNode 帐户
  • JavaScript 的基本知识
  • ngrok 或类似的工具,用于将你的本地服务器暴露给互联网(用于测试目的)

QuickNode Webhooks

喜欢 Streams 提供的实时数据功能吗?查看我们的新产品 Webhooks。它建立在 Streams 之上,并在简化的、易于使用的界面中提供相同的过滤和压缩功能。Webhooks 专门为简单、事件驱动的通知而设计,提供了一种更快的方式将实时数据发送到你的 HTTP endpoints,而无需 Streams 的完整复杂性。

Streams 中的区块链数据压缩

通过 Streams,你已经具有过滤功能,可以通过仅接收你需要的链上数据来减少 payload 大小。当你将压缩添加到已过滤的 Streams 时,成本节省将变得更加显着。

  1. Streams 过滤:通过向你发送你关心的数据来减少数据量
  2. Gzip 压缩:通过高达 90% 地进一步减少已过滤的数据

让我们看一个实际的例子,使用单个以太坊区块中 token transfers 的 payload 大小:

  • 未过滤的原始数据:该区块中所有交易的原始数据约为 990 KB。
  • 使用 Streams 过滤: 通过使用 Streams 仅过滤已解码的 ERC-20 token transfers,你可以将 payload 大小减少到约 617 KB——仅通过过滤就减少了近 38% 的数据。
  • 同时使用过滤和压缩: 通过在已过滤的 stream 上启用压缩,数据会缩小到仅约 62 KB。

注意: 所有数据大小均为估计值,可能因处理的实际数据而异。

Streams 过滤和压缩

由于以太坊上每月大约有 220,000 个区块,因此成本和带宽节省可能非常可观:

方法 每月数据大小
未过滤的原始数据 218 GB
过滤 135 GB
过滤 + 压缩 13 GB

如何在 Streams 中使用压缩

在本指南中,我们将为具有 webhook destination 的 Stream 启用压缩,并设置一个 Node.js Express 服务器来处理压缩的数据。

步骤 1:在你的 Stream 中启用 GZIP 压缩

你只需在 QuickNode 仪表板中单击一下即可启用压缩。

  1. 导航到 QuickNode 仪表板中的 Streams 部分
  2. 选择你要修改的 Stream 或创建一个新的 Stream
  3. (可选)在 Stream dataset 部分中过滤你的 Stream。 随意使用模板(例如,解码的 ERC20 transfers)或创建一个自定义模板
  4. 在 Stream 的 Destination 部分中,从 Payload compression 下拉菜单中选择 Gzip
  5. 检查 Estimated data volume 如何变化以反映启用压缩后减小的大小

注意: 压缩功能适用于 Webhook 和 S3 destinations。

启用压缩后,QuickNode 将开始以压缩的 gzip 格式发送此 Stream 的所有 webhook payloads。 webhook 还将包括 header Content-Encoding: gzip,以表明 payload 已压缩。因此,你的应用程序应检查此 header 以确定是否需要解压缩。

现在让我们构建将接收压缩数据的 Node.js Express 服务器。你的服务器启动并运行后,我们将完成 Stream 的创建。

步骤 2:设置你的应用程序以处理压缩数据

要处理压缩数据,你需要在应用程序中对其进行解压缩。在此示例中,我们将使用 Node.js Express 服务器来接收压缩数据并对其进行解压缩。

2.1 创建一个 Node.js 项目

创建一个新的 Node.js 项目:

mkdir streams-compression-example
cd streams-compression-example
npm init -y

2.2 安装依赖项

安装服务器所需的依赖项:

npm install express

2.3 创建一个服务器

下面的代码设置了一个基本的 Express 服务器,以演示如何处理来自 Streams 的压缩 payloads。它包括两个不同的路由:

  • /webhook/auto: 这是主要路由。它使用 express.raw({ inflate: true }) 中间件,该中间件会自动检测 Content-Encoding: gzip header 并解压缩 request body。这使得 payload 可以直接在 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)`);
});

2.4 运行服务器

启动你的服务器:

node app.js

2.5 暴露你的服务器

要使用 Streams 测试你的服务器,你需要将其暴露给互联网。你可以使用 ngrok 之类的工具,也可以将其部署到云服务。对于本地测试,请在新终端窗口中运行以下命令:

ngrok http 3000 # or other port if you changed it
# 如果你更改了端口,则使用其他端口

这会将你的服务器暴露给互联网上的一个随机端口。复制转发 URL(例如,https://xxxx.ngrok.io)并通过在末尾添加 /webhook/auto 将其粘贴到 Streams destination URL 中。(例如,https://xxxx.ngrok.io/webhook/auto

2.6 测试服务器

设置 destination URL 后,你可以通过将示例 payload 发送到你的 Stream 来测试你的服务器。

首先,通过单击 QuickNode 仪表板中的 Check Connection 按钮来检查连接。然后,通过单击 Send Payload 按钮将示例 payload 发送到你的 Stream。这将触发对你的服务器的 webhook 调用。

服务器将记录 headers、解压缩的 payload 大小和已解析的 JSON 数据。由于 payload 已自动解压缩,因此你可以通过检查请求中的 content-length header 来检查实际压缩的 payload 大小(以字节为单位)。在发送测试 payload 后,检查运行 ngrok 的终端,你将看到如下内容:

压缩 - 自动方法

如你所见,服务器会自动解压缩 payload,你可以直接在 req.body 中访问数据。完毕。

2.7 手动解压缩(可选)

在 Express 中间件中将 inflate 选项设置为 true 会自动解压缩 payload。但是,如果你出于任何原因想要手动解压缩 payload,则可以使用 zlib 模块来执行此操作。这是一个如何操作的示例。只需将此路由添加到你现有的 app.js 文件中。

此代码段将 /webhook/manual 路由添加到你的服务器。与自动解压路由不同,此路由处理原始 request body。它将传入的压缩数据收集到缓冲区中,检查 content-encoding header,如果是 gzip,则使用 Node.js 的内置 zlib.gunzip 方法来解压缩 payload。

此方法还计算并记录压缩率,向你显示压缩数据和解压缩数据之间的确切大小差异。

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 header,然后删除它
  // 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");
  });
});

之后,你可以通过将压缩的 payload 发送到 /webhook/manual 来测试手动解压缩路由。日志输出将显示压缩大小、解压缩大小和压缩率,如下所示。

压缩 - 手动方法

在测试压缩后,你现在可以通过单击 QuickNode 仪表板中的 Create a Stream 按钮来最终确定并激活你的 Stream,以接收压缩的实时数据。

结论

你已成功学习如何为 QuickNode Streams 启用压缩以及如何在 Express.js 应用程序中处理压缩数据。实现非常简单,只需几行代码即可处理解压缩,而节省是立竿见影且可观的。

如果你有任何疑问,请直接 联系我们。如果你有任何想法或建议,例如新的 destinations、功能、指标或数据集,你希望我们支持。

此外,请在 Twitter 上关注我们,并加入我们的 DiscordTelegram 公告频道,以随时了解最新信息。

更多资源

我们 ❤️ 反馈!

如果你有任何反馈或对新主题有任何要求,请 告诉我们。我们很乐意听取你的意见。

  • 原文链接: quicknode.com/guides/qui...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。