记:curl 本地有响应输出,curl域名却没有响应输出问题排查

问题描述

业务反馈,调试服务时,访问域名没有响应输出,但是本地访问是有的,需要排查下为何curl 域名有问题。

 

结论

原因:服务端没有设置响应体大小Content-Length,设置Content-Length参数值后,curl域名正常。

修改后的代码(部分):

 

排查过程

1、查看进程监听地址是不是 0.0.0.0 ,如果是 127.0.0.1 或者是本地ip,那么只允许本地访问,通过域名是访问不了的

查看发现是正常监听的,排除这个原因

 

2、 curl -v 查看详细输出,看看两种方式有何不同之处

 

发现两者的状态码都是200,那证明请求是成功的;另外发现http版本不一致,尝试指定http1.0访问,域名也能正常显示了

 

把服务http版本改为http1.1后,再curl域名,发现还是没输出,还需要继续排查。

 

3、 tcpdump -i any -w captured_packets.pcap 抓包分析

 

可看出域名请求也是有响应体的,但是没正确返回到客户端;同时发现所有的响应头中都没有Content-Length参数,尝试在服务中设置这个参数后,curl域名请求正常返回输出。

 

原因分析

1、Content-Length是什么?

  1. 定义:

    • Content-Length 是 HTTP 响应头的一个参数,用于指示响应体的大小(以字节为单位),如果文本文件进行了gzip压缩,那么该值表示压缩后的文件大小
    • 在响应头部设置,如 Content-Length: 1256 
  2. 作用:

    • 它可以帮助客户端准确地确定响应体的长度,从而正确地接收和处理响应数据
    • 客户端可以根据 Content-Length 的值来确保完整地接收响应体,而不会因为意外断开连接而丢失数据。
  3. 使用场景:

    • 当服务器事先知道响应体的大小时,就可以在响应头中设置 Content-Length
    • 这通常发生在服务器可以预知响应体大小的情况下,比如返回静态文件或者动态生成的内容大小确定的响应。
  4. 与 Transfer-Encoding 的关系:

    • Content-Length 与 Transfer-Encoding: chunked 是互斥的,服务器应该只设置其中一个。
    • 当服务器无法预知响应体大小时,可以使用 Transfer-Encoding: chunked 来代替 Content-Length

 

2、不设置Content-Length会怎样?

  1. 接收不完整的响应:

    • 没有 Content-Length 头意味着客户端无法确定响应体的总大小。
    • 在传输过程中可能由于网络问题或其他原因出现中断,导致客户端无法知道何时完整地接收到了响应。
    • 会导致客户端无法正确地解析和处理响应内容
  2. 错误的内容解析:

    • 客户端无法提前知道响应体的大小,就无法正确地分配内存来存储和解析响应内容。
    • 这可能会导致客户端尝试读取超出实际响应体大小的数据,造成内存溢出或其他错误。
  3. 响应体传输不确定性:

    • 没有 Content-Length 头,客户端无法确定响应什么时候结束,需要一直等待直到连接关闭。
    • 这会导致客户端的处理逻辑变得复杂,需要特殊处理响应体的接收。
  4. 无法实现高效的缓存:

    • 缓存机制依赖于 Content-Length 头来确定缓存对象的大小。
    • 没有 Content-Length 头会降低缓存的命中率和效率。

 

3、为什么http1.0不设置Content-Length,客户端也可以正常接收响应体并输出?

因为HTTP/1.0 使用的是短连接(non-persistent connection)模式,每个请求/响应都是在一个新的连接上进行的,服务器在发送完整个响应体后,会主动关闭 TCP 连接,当客户端检测到连接关闭时,就知道响应体已经接收完毕,而不必依赖设置 Content-Length 头来知晓响应体是否发送完成。

注:服务器在发送完整个响应体后主动关闭 TCP 连接,是由Connection决定的,HTTP/1.0默认使用 Connection: close ,表示当前 HTTP 连接在响应完成后将被关闭

 

HTTP/1.1引入了持久连接(persistent connection)的概念,客户端和服务器可以在一个连接上传输多个请求和响应。为了处理这种情况,HTTP/1.1 要求服务器必须显式地告知客户端响应体的长度,以便客户端能够正确地处理后续的请求和响应;因此需要设置Content-Length或Transfer-Encoding参数。

注:HTTP/1.1中,默认 Connection: keep-alive ,表示客户端和服务器希望保持当前的 TCP 连接,以便后续可以复用该连接。

 

posted @ 2024-05-30 17:36  心恩惠动  阅读(356)  评论(0编辑  收藏  举报