流式(chunked)概念
- Chunked流式接口是一种用于在网络传输中分块发送数据的方法。在传统的请求/响应模式中,数据通常以完整的实体(例如,完整的HTML页面或文件)的形式发送。而在Chunked流式接口中,数据被分成较小的块(chunks),每个块都带有自己的长度信息,并逐个发送。
- 使用Chunked流式接口,发送方可以将数据划分为较小的块,然后逐个发送,而不需要等待整个实体的完整性。这样可以提供更高的传输效率和更快的响应时间,尤其在处理大文件或大量数据时。接收方则可以逐块接收数据,并立即处理,而不需要等待完整的数据传输完成。
- 在HTTP协议中,Chunked流式传输通常用于在不知道整个响应内容长度的情况下传输数据,或者在需要逐步处理响应内容的情况下。通过使用Chunked编码,服务器可以动态生成和发送数据块,而无需事先将整个响应内容存储在内存中。
- 使用Chunked流式接口时,HTTP头部中的Transfer-Encoding字段会设置为"chunked",并且每个数据块都会在发送前带有一个表示其长度的十六进制数值。数据块之间使用特定的分隔符进行分隔。
- 总之,Chunked流式接口是一种将数据分块发送的方法,可以提高传输效率和响应速度,特别适用于处理大文件或大量数据的情况。
流式(chunked)实现思路:
流式(chunked)传输是通过在HTTP协议中使用Chunked编码来实现的。下面是流式传输的基本实现过程:
- 服务器生成数据块:服务器根据需要生成数据块,并确定每个数据块的大小。
- 数据块编码:每个数据块都以十六进制表示其大小,并在数据块内容之前添加该大小值。例如,如果一个数据块的大小为10字节,那么编码后的大小值为"A"(十六进制10),然后跟着10个字节的数据。
- 发送数据块:编码后的数据块被发送到客户端。
- 接收数据块:客户端接收到数据块后,解码数据块的大小,并根据大小值读取相应数量的字节数据。
- 处理数据块:客户端可以立即处理接收到的数据块,而不需要等待完整的响应内容。
- 重复步骤3-5:服务器继续生成和发送后续的数据块,直到所有数据块都被发送完毕。
- 结束传输:当所有数据块都发送完毕后,服务器会发送一个空的数据块,用于表示传输结束。这个空的数据块以单个的"0"(十六进制0)表示。
通过这种方式,数据可以以逐块的方式进行传输,而不需要等待完整的响应内容。客户端可以根据需要逐块接收和处理数据,从而实现流式传输的效果。
示例代码演示(服务端选择其一即可)
springboot(服务器端)中如何搭建
import org.springframework.http.ResponseEntity; import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/chunked") @Slf4j public class TestController {
@GetMapping("/chunked-test") public ResponseEntity<StreamingResponseBody> getData() {
// 创建一个发送句柄 StreamingResponseBody responseBody = outputStream -> {
// 模拟真实场景下连续发送数据 for (int i = 0; i < 10; i++) {
// 延迟等待:模拟真实场景 try {
Thread.sleep(1000); }catch (Exception e){
} // 数据块编码 String data = "{\"name\": \"name-"+i+"\"}"; // 写入数据 outputStream.write(data.getBytes()); // 发送数据 outputStream.flush(); } }; // 响应到客户端 return ResponseEntity.ok() .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(responseBody); } }
讯享网
注意: 不需要引入额外的包,正常的springboot项目即可(本文使用的egg版本为:2.6.1)
egg(服务器端)中如何搭建
- EGG代码: controller中的一个方法
讯享网import {
Controller } from 'egg'; // 创建一个sleep方法,进行延迟等待 const sleep = function (ms) {
return new Promise((resolve) => setTimeout(resolve, ms)); }; export default class TestController extends Controller {
/ * chunked发送数据 */ public async chunkedSendData() {
const {
ctx } = this; // 设置HTTP头部信息 ctx.set('Transfer-Encoding', 'chunked'); ctx.set('Content-Type', 'application/octet-stream'); try {
// 一定要设置响应状态 ctx.status = 200; // 使用egg中的响应作为发送句柄 const rawResponse = ctx.res; // 模拟真实场景下连续发送数据 for (const item of [1, 2, 3, 4, 5, 6, 7, 8]) {
// 延迟等待:模拟真实场景 await sleep(1000); // 发送数据块 rawResponse.write(JSON.stringify({
name: 'name-' + item })); } // 结束请求 rawResponse.end(); } catch {
ctx.status = 500; } } }
- 路由文件中写法(正常书写就行): router.js
import {
Application } from 'egg'; export default (app: Application) => {
const {
controller, router } = app; // chunked发送数据测试: router.get('/chunked/chunked-test', controller.test.chunkedSendData); };
注意: 不需要任何的插件,正常的Egg项目即可(本文使用的egg版本为:2.6.1)
使用nginx作为代理
- 将
/api/chunked/chunked-test请求代理到http://127.0.0.1:7001/chunked/chunked-test
讯享网server { ... location /api/chunked/ { proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Proto $scheme; // 设置不需要缓存,也就是实时输出 proxy_buffering off; // 设置http版本,支持实时输出 proxy_http_version 1.1; // chunked打开(下面两句话作用不大) chunked_transfer_encoding on; proxy_set_header Connection ""; proxy_pass http://127.0.0.1:7001/chunked/; } }
注1:Nginx自版本1.3.9起开始支持Chunked传输。此版本以及之后的版本都包含对Chunked传输的支持,无需安装模块即可支持
使用场景
- 实时输出场景(GPT)
- 数据实时要求比较高(商场首页)
注意事项
- 微信小程序作为chunked客户端,请查阅:《微信小程序之流式(chunked)响应》

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/52792.html