云主机curl工具慢

问题现象

  • 客户的云主机每隔一段时间用curl工具获取http服务端的信息,通常情况可以正常工作。如下图所示,但同样的curl命令,多使用几次,就会出现一次curl卡住,命令不返回的情况。用户反馈使用其它网络线路节点上的虚机,访问相同http服务,不会出现。图中隐去了ip和port。
    在这里插入图片描述

定位过程

虚机侧

  • 首先使用strace命令查看curl命令卡住的用户栈,如下:
    在这里插入图片描述
  • curl工具实际上用于模拟http协议的request,它可以发送GET/PUT/POST等http request。如果不指定curl方法,默认发送GET请求。通过strace工具能看到,curl发送http request时调用了socket接口发起tcp连接服务端,上图我们隐去了服务端的地址和端口,可以看到curl卡在了connect之后的poll上。再查看curl进程的状态,调用poll接口后进程睡眠了,如下:
    在这里插入图片描述
  • 查看内核栈确实在睡眠,当服务端响应,返回tcp数据包之后,curl进程才会被唤醒。
    在这里插入图片描述

主机侧

  • 在curl命令运行时对主机侧虚机vnet网卡抓包,使用命令tcpdump -nni ${ETH} host ${IP} and port ${port}。正常运行时抓包如下:
    在这里插入图片描述
  • curl卡住时抓包如下,对比可以发现curl卡住时ip报文卡在tcp三次握手的第一次握手sync包。从左边的时间戳可以确认,sync包重传了,tcp重传的时间指数级增加:1、2、4、8、16、32。
    在这里插入图片描述
  • 抓取链路层数据,进一步分析sync包的内容,tcpdump -nnxi ${ETH} host ${host} and port ${port}
    在这里插入图片描述
  • 以上分析可以确认,云主机内部的curl命令卡住的原因是主机侧发起tcp连接时,发送的sync包卡住了,服务端没有ack包回应,因此一直在重传,虚机内部看到的现象就是curl一直阻塞。至此我们知道虚机的流量至少走到了主机的vnet侧,下一步需要确认流量是否从物理网卡发出,查看vnet桥接的ovs桥,找到其对应的物理口。
1. virsh domiflist vm
查看虚机vnet桥接的ovs桥为br-int
2. ovs-vsctl show
查看主机上ovs桥信息及其上的port
3. ovs-ofctl -O OpenFlow13 show br-int
查看br-int桥上的流表信息,找到虚机vnet口在ovs桥上对应的port
4. ovs-ofctl -O OpenFlow13 dump-flows br-int
导出ovs上的流表,查看其转发规则,找到output
  • 抓取报文,tcpdump -nneei ${ETH} host ${host},发现curl卡住时仍然有流量,并且也是sync包,因此可以sync包已经从宿主机发出,为什么服务端没有ack回应,有两种可能:
  1. 链路丢包了,根本没有到达服务端,宿主机tcp协议发包后计数器超时,触发自动重传
  2. 链路到达了服务端,但服务端的cpu忙或者http server处理有问题,没能及时回复,触发自动重传

基础知识

HTTP

  • http协议可以用于实现网络资源的操作和访问,也可以实现rest风格的API,它使用cs模式传输内容,传输的两端分别时客户端工具和服务端的web应用。其格式如下:
    在这里插入图片描述
  • 在我们的案例中curl就是一个组装http请求的工具,如果不指定method,默认为GET,内容如下:
    在这里插入图片描述
  • http协议的内容作为tcp协议的payload存在,curl在发送http请求时首先和服务端建立一个tcp的连接,我们strace跟踪到的connect系统调用就是socket编程中连接服务端的接口。tcp连接的核心工作就是进行三次握手,三次握手完成之后连接就建立了。之后curl工具可以将http的内容填入tcp连接的buffer中,传输到服务端。服务端读取tcp的内容后,从中解析出http的数据之后,传递给上层的web server程序。从而实现http协议内容的传输。当传输完成,curl断开这个tcp连接。对于http来说,它都是以短连接的方式使用tcp协议,每次发送完一个请求就会断开tcp连接。

TCP

  • tcp协议两端是应用程序,linux下一个tcp连接可以通过socket编程接口,对于tcp的服务端,它监听一个端口,每当端口有数据到达便解析并进行相应处理,然后回复。其格式如下:
    在这里插入图片描述
  • 使用tcpdump工具抓包将tcp协议的头部解析出来,使用tcpdump -i tap42a4a5cc-1a -nnx host 10.251.53.131 and port 8890 -vv查看三次握手过程中发送的tcp报文,如下:
    在这里插入图片描述
  • tcpdump的信息中,多数字段都比较明确,下面只分析Flags和options两个字段,Flags字段就是解析tcp头部中的Flags,用可读的字母表示出来,手册解释如下:
Tcpflags are some combination of S (SYN), F (FIN), P (PUSH), R (RST), U (URG), W (ECN CWR), E (ECN-Echo) or `.' (ACK), or `none' if no flags are set
  1. SYN: 表示三次握手中的同步包,用于建立tcp连接,这个包只有头部,没有数据。
  2. FIN: 表示四次挥手中的结束包,用于关闭tcp连接,这个包只有头部,没有数据。
  3. PUSH: 表示tcp协议中有数据,tcp的payload不是空的,这是真正传输数据的包。如果上层是http协议,那么它传输的就是http协议的内容,当目的端的socket的server接收到tcp连接传输的数据后,它将tcp承载的内容解析出来,交给上层的web server,web server按照http协议约定解析相关字段,进行对应处理。
  4. ACK: 标识回复包,除了连接建立时第一次握手syn包不带ACK标识,其余任何时候的包都带有ACK标识,用于告诉对端自己希望收到的下一个包的起始序号,为表示方便就用一个.代替ACK标识。
  • options字段长度可变,在0~40字节范围内,用于实现一些测试和验证的功能,下面介绍几个常见的option,更多细节参考TCP协议:
  1. MSS: Max Segment Size,用于设置tcp协议中能够发送的最大报文长度,这里的长度指的时tcp的payload,需要减去tcp头部长度,通常是MTU-40(减掉的这40字节包括20字节的TCP头部和20字节的IP头部)。
  2. TS val: Timestamps value,记录发送方在发送报文是当前系统的时间戳,这样可以计算整个包到达目的端的耗时,从而计算往返时间(Round-trip time)。
  3. wscale: Window Scale,早期的tcp协议中,接受窗口大小的最大值为65535字节,随着硬件能力的提升,能处理的窗口大小越来越大,可以进一步增大窗口大小,而tcp协议中给window size字段设计的长度是16bit,只能表示65535字节,为扩大窗口范围,给出了一个解决方案,在tcp协议的可选字段中增加wscale,表示window size的单位(窗口缩放因子)。在三次握手通信双方把自己的wscale告知对方,在正常通信解析window size时,将window size乘以2^wscale。假设wscale协商为7,如果window size的值为500,那么实际的窗口大小为500 * 2 ^ 7 = 500 * 128 = 64000。

IP

  • IP报文不保证可靠连接,它的格式如下:
    在这里插入图片描述
  • 下图为IP报文的内容分析:
    在这里插入图片描述
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

享乐主

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

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

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

打赏作者

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

抵扣说明:

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

余额充值