在 Cloudflare Workers KV 等分布式数据存储中存储 ReadableStream 的用例有哪些?

What are the use cases to store ReadableStream in the distributed data store like Cloudflare Workers KV?

Cloudflare 自己的全球分布式数据存储 – Workers KV – can accept data of three "types"stringArrayBufferReadableStream.

虽然前两个的用例足够清楚,但我正在努力弄清楚存储 ReadableStream 有何用处。我很熟悉这个概念:使用它你可以随着时间的推移“流式传输”不同的值,但是把它放在数据存储中有什么用呢?什么是典型场景?

传递 stringArrayBufferReadableStream 之间的区别不在于 存储了哪些数据,而是数据如何存储到达那里。请注意,您可以将数据存储为 string,然后再将其作为 ArrayBuffer 读取,反之亦然(string 使用 UTF-8 转换为 to/from 字节)。当您将 ReadableStream 传递给 put() 时,系统会从流中读取数据并存储该数据;它不存储流本身。同样,当使用get()时,你可以指定"stream"作为第二个参数来得到一个ReadableStream;当您从此流中读取时,它将产生值的内容。

你想要使用流的主要情况是当你想直接将 HTTP 请求的主体存储到 KV 值中时,或者当你想直接 return 一个 KV 值作为主体时一个 HTTP 响应。在这些情况下使用流可以避免一次将整个值保存在内存中的需要;相反,字节可以在到达时流过。

例如,而不是做:

// BAD
let value = await request.text();
await kv.put(key, value);

你应该这样做:

// GOOD
await kv.put(key, request.body);

当值的大小为数兆字节时,这一点尤为重要。前一个版本会将整个值读入内存以构造一个大的 string(包括将 UTF-8 解码为 UTF-16),然后立即将该值写回 KV(将 UTF-16 转换回 UTF) -8).后一个版本将字节直接从传入连接复制到 KV 中,而不会立即将整个值存储在内存中。

同样,对于响应,而不是做:

// BAD
let value = await kv.get(key);
return new Response(value);

你可以这样做:

// GOOD
let value = await kv.get(key, "readableStream");
return new Response(value);

这样,响应字节就会从 KV 流式传输到 HTTP 连接。这不仅可以节省内存和 CPU 时间,还意味着客户端可以更快地开始接收字节,因为您的 Worker 不会等到接收到所有字节才开始转发它们。