如何提供流式(chunked)接口

流式(chunked)概念

  • Chunked流式接口是一种用于在网络传输中分块发送数据的方法。在传统的请求/响应模式中,数据通常以完整的实体(例如,完整的HTML页面或文件)的形式发送。而在Chunked流式接口中,数据被分成较小的块(chunks),每个块都带有自己的长度信息,并逐个发送。

  • 使用Chunked流式接口,发送方可以将数据划分为较小的块,然后逐个发送,而不需要等待整个实体的完整性。这样可以提供更高的传输效率和更快的响应时间,尤其在处理大文件或大量数据时。接收方则可以逐块接收数据,并立即处理,而不需要等待完整的数据传输完成。

  • 在HTTP协议中,Chunked流式传输通常用于在不知道整个响应内容长度的情况下传输数据,或者在需要逐步处理响应内容的情况下。通过使用Chunked编码,服务器可以动态生成和发送数据块,而无需事先将整个响应内容存储在内存中。

  • 使用Chunked流式接口时,HTTP头部中的Transfer-Encoding字段会设置为"chunked",并且每个数据块都会在发送前带有一个表示其长度的十六进制数值。数据块之间使用特定的分隔符进行分隔。

  • 总之,Chunked流式接口是一种将数据分块发送的方法,可以提高传输效率和响应速度,特别适用于处理大文件或大量数据的情况。

流式(chunked)实现思路:

流式(chunked)传输是通过在HTTP协议中使用Chunked编码来实现的。下面是流式传输的基本实现过程:

  1. 服务器生成数据块:服务器根据需要生成数据块,并确定每个数据块的大小。

  2. 数据块编码:每个数据块都以十六进制表示其大小,并在数据块内容之前添加该大小值。例如,如果一个数据块的大小为10字节,那么编码后的大小值为"A"(十六进制10),然后跟着10个字节的数据。

  3. 发送数据块:编码后的数据块被发送到客户端。

  4. 接收数据块:客户端接收到数据块后,解码数据块的大小,并根据大小值读取相应数量的字节数据。

  5. 处理数据块:客户端可以立即处理接收到的数据块,而不需要等待完整的响应内容。

  6. 重复步骤3-5:服务器继续生成和发送后续的数据块,直到所有数据块都被发送完毕。

  7. 结束传输:当所有数据块都发送完毕后,服务器会发送一个空的数据块,用于表示传输结束。这个空的数据块以单个的"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)
  • 数据实时要求比较高(商场首页)

注意事项

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

光速度的进程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值