知名网站开发哪里有运营一款app的费用
news/
2025/9/30 1:10:52/
文章来源:
知名网站开发哪里有,运营一款app的费用,淘宝运营培训视频,免费的网站软件下载安装TCP是一个有状态通讯协议#xff0c;所谓的有状态是指通信过程中通信的双方各自维护连接的状态。一、TCP keepalive先简单回顾一下TCP连接建立和断开的整个过程。(这里主要考虑主流程#xff0c;关于丢包、拥塞、窗口、失败重试等情况后面详细讨论。)首先是客户端发送syn(Syn…TCP是一个有状态通讯协议所谓的有状态是指通信过程中通信的双方各自维护连接的状态。一、TCP keepalive先简单回顾一下TCP连接建立和断开的整个过程。(这里主要考虑主流程关于丢包、拥塞、窗口、失败重试等情况后面详细讨论。)首先是客户端发送syn(Synchronize Sequence Numbers同步序列编号)包给服务端告诉服务端我要连接你syn包里面主要携带了客户端的seq序列号服务端回发一个synack其中syn包和客户端原理类似只不过携带的是服务端的seq序列号ack包则是确认客户端允许连接最后客户端再次发送一个ack确认接收到服务端的syn包。这样客户端和服务端就可以建立连接了。整个流程称为三次握手。建立连接后客户端或者服务端便可以通过已建立的socket连接发送数据对端接收数据后便可以通过ack确认已经收到数据。数据交换完毕后通常是客户端便可以发送FIN包告诉另一端我要断开了另一端先通过ack确认收到FIN包然后发送FIN包告诉客户端我也关闭了最后客户端回应ack确认连接终止。整个流程成为四次挥手。TCP的性能经常为大家所诟病除了TCPIP额外的header以外它建立连接需要三次握手关闭连接需要四次挥手。如果只是发送很少的数据那么传输的有效数据是非常少的。是不是建立一次连接后续可以继续复用呢的确可以这样做但这又带来另一个问题如果连接一直不释放端口被占满了咋办。为此引入了今天讨论的第一个话题TCP keepalive。所谓的TCP keepalive是指TCP连接建立后会通过keepalive的方式一直保持不会在数据传输完成后立刻中断而是通过keepalive机制检测连接状态。Linux控制keepalive有三个参数保活时间net.ipv4.tcp_keepalive_time、保活时间间隔net.ipv4.tcp_keepalive_intvl、保活探测次数net.ipv4.tcp_keepalive_probes默认值分别是 7200 秒(2 小时)、75 秒和 9 次探测。如果使用 TCP 自身的 keep-Alive 机制在 Linux 系统中最少需要经过 2 小时 9*75 秒后断开。譬如我们SSH登录一台服务器后可以看到这个TCP的keepalive时间是2个小时并且会在2个小时后发送探测包确认对端是否处于连接状态。之所以会讨论TCP的keepalive是因为发现服器上有泄露的TCP连接# ll /proc/11516/fd/10lrwx------ 1 root root 64 Jan 3 19:04 /proc/11516/fd/10 - socket:[1241854730]# dateSun Jan 5 17:39:51 CST 2020已经建立连接两天但是对方已经断开了(非正常断开)。由于使用了比较老的go(1.9之前版本有问题)导致连接没有释放。解决这类问题可以借助TCP的keepalive机制。新版go语言支持在建立连接的时候设置keepalive时间。首先查看网络包中建立TCP连接的DialContext方法中if tc, ok : c.(*TCPConn); ok d.KeepAlive 0 {setKeepAlive(tc.fd, true)ka : d.KeepAliveif d.KeepAlive 0 {ka defaultTCPKeepAlive}setKeepAlivePeriod(tc.fd, ka)testHookSetKeepAlive(ka)}其中defaultTCPKeepAlive是15s。如果是HTTP连接使用默认client那么它会将keepalive时间设置成30s。var DefaultTransport RoundTripper Transport{Proxy: ProxyFromEnvironment,DialContext: (net.Dialer{Timeout: 30 * time.Second,KeepAlive: 30 * time.Second,DualStack: true,}).DialContext,ForceAttemptHTTP2: true,MaxIdleConns: 100,IdleConnTimeout: 90 * time.Second,TLSHandshakeTimeout: 10 * time.Second,ExpectContinueTimeout: 1 * time.Second,}下面通过一个简单的demo测试一下代码如下func main() {wg : sync.WaitGroup{}c : http.DefaultClientfor i : 0; i 2; i {wg.Add(1)go func() {defer wg.Done()for {r, err : c.Get(http://10.143.135.95:8080)if err ! nil {fmt.Println(err)return}_, err ioutil.ReadAll(r.Body)r.Body.Close()if err ! nil {fmt.Println(err)return}time.Sleep(30 * time.Millisecond)}}()}wg.Wait()}执行程序后可以查看连接。初始设置keepalive为30s。然后不断递减至0后又会重新获取30s。整个过程可以通过tcpdump抓包获取。# tcpdump -i bond0 port 35832 -nvv -A其实很多应用并非是通过TCP的keepalive机制探活的因为默认的两个多小时检查时间对于很多实时系统是完全没法满足的通常的做法是通过应用层的定时监测如PING-PONG机制(就像打乒乓球一来一回)应用层每隔一段时间发送心跳包如websocket的ping-pong。二、TCP Time_wait第二个希望和大家分享的话题是TCP的Time_wait状态。、为啥需要time_wait状态呢为啥不直接进入closed状态呢直接进入closed状态能更快地释放资源给新的连接使用了而不是还需要等待2MSL(Linux默认)时间。有两个原因一是为了防止“迷路的数据包”如下图所示如果在第一个连接里第三个数据包由于底层网络故障延迟送达。等待新的连接建立后这个迟到的数据包才到达那么将会导致接收数据紊乱。第二个原因则更加简单如果因为最后一个ack丢失那么对方将一直处于last ack状态如果此时重新发起新的连接对方将返回RST包拒绝请求将会导致无法建立新连接。为此设计了time_wait状态。在高并发情况下如果能将time_wait的TCP复用time_wait复用是指可以将处于time_wait状态的连接重复利用起来。从time_wait转化为established继续复用。Linux内核通过net.ipv4.tcp_tw_reuse参数控制是否开启time_wait状态复用。读者可能很好奇之前不是说time_wait设计之初是为了解决上面两个问题的吗如果直接复用不是反而会导致上面两个问题出现吗这里先介绍Linux默认开启的一个TCP时间戳策略net.ipv4.tcp_timestamps 1。时间戳开启后针对第一个迷路数据包的问题由于晚到数据包的时间戳过早会被直接丢弃不会导致新连接数据包紊乱针对第二个问题开启reuse后当对方处于last-ack状态时发送syn包会返回FIN,ACK包然后客户端发送RST让服务端关闭请求从而客户端可以再次发送syn建立新的连接。最后还需要提醒读者的是Linux 4.1内核版本之前除了tcp_tw_reuse以外还有一个参数tcp_tw_recycle这个参数就是强制回收time_wait状态的连接它会导致NAT环境丢包所以不建议开启。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/922385.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!