spring boot使用http响应头传输:编码,但是tcp发送两个数据包即使响应很小

Posted

技术标签:

【中文标题】spring boot使用http响应头传输:编码,但是tcp发送两个数据包即使响应很小【英文标题】:springboot use http respose header transfer:encoding, but tcp send two packet even if the response is small 【发布时间】:2021-12-04 05:48:24 【问题描述】:
@SpringBootApplication
@RestController
public class HttpChunkedApplication 

    public static void main(String[] args) 
        SpringApplication.run(HttpChunkedApplication.class, args);
    

    @PostMapping("/home/getMsg")
    public ChunkedRsp login( HttpServletResponse response )
        return new ChunkedRsp("aaa","bbb","ccc");
    

@Data
public class ChunkedRsp 
   private String A;
   private String B;
   private String C;

    public ChunkedRsp(String a, String b, String c) 
        A = a;
        B = b;
        C = c;
    

运行应用程序,然后

    sudo tcpdump -i any -nnAls0 端口 8080 curl -X POST http://0.0.0.0:8080/home/getMsg

tcpdump 显示两个数据包: tcp dump packet when I curl

【问题讨论】:

鼓励提问Minimum, verifiable example 【参考方案1】:

您所描述的正是分块编码应该如何工作(参见例如Wikipedia):

每个块都以它的长度(十六进制)和\r\n为前缀, 序列0\r\n\r\n表示消息结束。

发送的 TCP 段数取决于您的 TCP/IP 堆栈(操作系统)。如果连接TCP_NO_DELAY选项为false,则段将合并:参见this question。

Tomcat 默认将套接字上的TCP_NO_DELAY 选项设置为true(参见documentation)。要禁用它,请修改您的连接器配置:

<Connector port="8080"
           socket.tcpNoDelay="false"
           ... />

并在真实连接上测试您的服务器(不是环回设备127.0.0.1,它非常快)。

【讨论】:

springboot 在返回对象时会使用分块响应。如果返回一个字符串,则响应不会被分块。 是的,确实如此。所以你的问题不是两个 TCP 段,而是 Spring Boot 使用分块编码的事实?你应该通过修改你的问题来澄清它。 为什么分块响应会发送两个 TCP 段?我发现 outputStream.flush() 会发送两个 TCP 段,但 outputStream.write() 会将两个 TCP 段合并为一个。

以上是关于spring boot使用http响应头传输:编码,但是tcp发送两个数据包即使响应很小的主要内容,如果未能解决你的问题,请参考以下文章

HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP

HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP

禁用传输编码:在 Spring Webflux 响应中分块

使用 Spring Boot 到达静态内容时如何添加响应标头?

socket转发http请求注意事项

如何在 Spring(Boot)中装饰 REST 响应?