TCP_UDP_HTTP
TCP_state
主动/被动是从client角度进行解释的.
TCP_connection
3次握手
- C -> S : 发送SYN标记的报文(中间状态:c-syn_send,s:syn_rcvd)
- S -> C : 发送ACK, SYN 2个标记的报文
- C -> S : 发送ACK, 报文(带数据)
建立链接时状态的变化
- 服务端: CLOSED -> LISTEN -> SYN_RCVD -> ESTABLISHED
- 客户端: CLOSED -> SYN_SEND -> ESTABLISHED
SYN_SEND: SYN has been send SYN_RCVD: SYN has been rcvd
TCP_connection_close
- 全双工(断开的是数据传输方向),需要断开2次
-
C->S: 发送FIN
-
S->C: 发送ACK(关闭client -> Server的数据传输, 但是客户端还可以发送ack)
-
S->C : FIN
-
C->S : ACk (关闭server -> Client的数据传输,谁发送就断开谁)
主动关闭/被动关闭
如上图,·主动/被动是站在app(client)的角度
-
主动关闭:客户端先发起的FIN:
EXTABLISH->TIME_WAIT->CLOSED- Server端的TIME_WAIT时间一直使用端口
TIME_WAIT阶段可能发生SOCKET IN USE ERROR;server端在等待2MSL时一直占用端口;所以需要优雅关机- TIME_WAIT:主动关闭时,server和client之间的4次握手全部完成时,server需要继续等待关闭的时间,默认2MSL
-
被动关闭:客户端后发起FIN:
ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED- 简单点: ESTABLISHED -> CLOSE_WAIT -> CLOSED
CLOSE_WAIT: 等待客户端发起FIN,并发送LAST_ACK(server不会再发送数据了)
keeplive_connection
长链接不像短链接一样每个请求建立一次TCP链接,而是多个请求共用一个TCP链接; 所以在配置长链接是一般需要从2个角度的配置 长链接的超时时间 和 长链接允许的最大请求数; 长链接省去了tcp三次握手的时间。
ping一下大约0.93ms(一次往返)相当于三次握手也是一次往返(TCP第三次握手不用返回);即tcp链接省去了ping一次的耗时;假如你的服务每天的pv是1亿,那么使用长连接节约的总时间为:1亿1ms=10^81ms=10^51s=10^51h/3600≈27.78h。神奇的是,亿万级pv的服务使用长连接一天内节约的总时间为27.78小时(竟然大于一天)
keepalive_config
优化web服务设置长链接2个方面: client - nginx, nginx - tomcat;
client_nginx
- 客户端设置请求头Keep-Alive
- nginx 设置 keepalive
# conf/nginx.conf
http{
keepalive_timeout 300s 120s;
keepalive_requests 300;
}
keepalive_timeout timeout [header_timeout]
- timeout: 设置keep-alive的客户端连接在服务器端保持开启的超时值,单位S,表示一个长链接在nginx端的超时时间timout秒后nginx会主动断开,timout默认75s,值为0会禁用keep-alive客户端连接;
- header_timeout 可选,在响应请求的的header域中设置
Keep-Alive: timeout=time
keepalive_requests 100
默认100, 客户端长链接在nginx端能处理请求的最大数量,nginx对每个TCP链接设置计数器,当处理的http请求数达到上限,则断开链接.
keepalive_requests设置较小且QPS(PV)访问过大时, nginx主动断开链接, netstat客户端服务器,会出现大量的
TIME_WAIT
nginx_tomcat
-
- 在nginx端设置upstream
upstream{
keepalive 1000;
}
location{
proxy_http_version 1.1;
proxy_set_header Connection "";
}
keepalive 1000: 每个worker进程保持的到upstream服务器的最大的空闲长连接数; 不是woker进程到upstream的最大长连接数;
proxy_http_version 1.1; http 1.1 版本支持长链接
proxy_set_header Connection "";清空client端请求的header,即使在client-nginx是短链接的情况下,不影响nginx-tomcat之间建立长链接
-
- tomcat配置conf/server.xml
<Connector port="8080"
protocol="org.apache.coyote.http11.Http11NioProtocol"# 支持非阻塞IO
maxThreads="768" # 连接器创建的处理请求的最大线程数
minSpareThreads="512" # 最小空闲县城
acceptCount="128" # accept请求链接的队列长度
connectionTimeout="1000" #等待时间
maxConnections="1024" # 服务器最大的链接
keepAliveTimeout="300000" # 长链接超时
maxKeepAliveRequests="768" # 长链接请求数
enableLookups="false" # 禁用DNS查询
URIEncoding="UTF-8" #默认是ISO,有可能导致get参数中文乱码,设置为UTF-8
redirectPort="8443"
compression="on" # 连接器是否启用HTTP/1.1GZIP压缩为了节省服务器带宽
compressionMinSize="1024" # 相应数据的最小大小
compressableMimeType="text/html,text/xml,text/javascript,text/css,text/plain,application/json,application/xml" # http压缩的文件类型
server="webserver" /> # http 相应头的Server信息
key
Q
为什么建立连接协议是三次握手,而关闭连接却是四次握手呢
三次握手建立链接时,ACK+SYN一起发送 或者 ACK+数据 一起发送时能够节省是为了提高发送的效率;节省传输的时间;
四次握手断开链接时; FIN和ACK没有一起发送是 因为 TCP是全双工的链接,数据双向传输; FIN表示发送方不再发送数据;当一方发送FIN时,需要立刻收到ACK回复;但另一方仍然可能需要继续发送数据,所以不能立即发送FIN, 所以FIN 和 ACK 不能在一起发送, 从而需要4次握手
为什么TIME_WAIT状态还需要等2MSL后才能返回到CLOSED状态
TIME_WAIT 出现在主动关闭链接时,服务端4次握手全部完成时等待的状态,为了防止因为网络问题服务端最后发送的ACK客户端没有收到,客户端此时会重新发送FIN, 此时服务端可以用来重新发送ACK
什么情况下出现TIME_WAIT,有什么用?系统配置解决大量的TIME_WAIT
一般出现的在主动关闭链接时,客户端和服务端使用短链接,而且频繁的出现 建立链接 + 断开链接 操作
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
# TIME_WAIT 48 #主动关闭的链接,
# CLOSE_WAIT 2228 #被动关闭的链接,半关闭, client不再发送数据
# ESTABLISHED 86 #建立的链接
解决方案1: 配置长链接,处理好http链接的关闭问题
## tcp相关的系统配置: vim /etc/sysctl.conf
## 编辑完 /etc/sysctl.conf,要重启network 才会生效 /etc/rc.d/init.d/network restart
## 然后,执行sysctl命令使修改生效,基本上就算完成了。
#表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_syncookies=1
#表示开启重用。允许将TIME_WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1
#表示开启TCP连接中TIME_WAIT sockets的快速回收,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1
# 修改系統默认的 TIMEOUT 时间
net.ipv4.tcp_fin_timeout=30
#表示当keepalive起用的时候,TCP发送keepalive消息的频度。缺省是2小时,改为20分钟。
net.ipv4.tcp_keepalive_time = 1200
#表示用于向外连接的端口范围。缺省情况下很小:32768到61000,改为1024到65000。
net.ipv4.ip_local_port_range = 1024 65000
#表示SYN队列的长度,默认为1024,加大队列长度为8192,可以容纳更多等待连接的网络连接数。
net.ipv4.tcp_max_syn_backlog = 8192
#表示系统同时保持TIME_WAIT套接字的最大数量,如果超过这个数字,TIME_WAIT套接字将立刻被清除并打印警告信息。 默认为180000,改为5000。对于Apache、Nginx等服务器,上几行的参数可以很好地减少TIME_WAIT套接字数量,但是对于 Squid,效果却不大。此项参数可以控制TIME_WAIT套接字的最大数量,避免Squid服务器被大量的TIME_WAIT套接字拖死。
net.ipv4.tcp_max_tw_buckets = 5000
TCP/UDP的定义的不同,TCP如何实现有序传输.解释TCP快速重传,拥塞机制,怎么解决粘包问题
tcp的转包工具:tcpdump
Https与Http的区别,解决的什么问题?如何实现的
- 网络传输的协议层:(http请求涉及的协议)
- 应用层:HTTP/DNS(域名解析协议:domain-ip)/FTP
- 传输层:TCP/UDP
- 网络层:IP/ARP(address resolution protocol地址解析协议:根据IP获取mac)
- 数据链路层
- HTTP + SSL = HTTPS(TSL是SSL的升级版本,主要为了解决数据传输的安全问题)
- 对称加密: 可能存在密钥泄漏的问题
- 非对称加密: 可能出现虚假中介问题
- 非对称加密 + CA充当权威第三方 => openssl 完成
java.net.SocketException
导致“Connection reset”的原因是服务器端因为某种原因关闭了Connection,而客户端依然在读写数据,此时服务器会返回复位标志RST,然后此时客户端就会提示java.net.SocketException: Connection reset
- Connection reset: 服务器返回了“RST”时,如果此时客户端正在从Socket套接字的输出流中读数据则会抛
- Connection reset by peer:服务器返回了“RST”时,如果此时客户端正在往Socket套接字的输入流中写数据则会抛