计算机网络篇
HTTP常用的状态码类别
状态码 |
类别 |
1xx |
信息响应 |
2xx |
成功消息 |
3xx |
重定向消息 |
4xx |
客户端错误消息 |
5xx |
服务端错误消息 |
HTTP常用状态码
状态码 |
含义 |
101 |
切换请求协议 |
200 |
成功 |
301 |
永久重定向,会缓存 |
302 |
临时重定向,不会缓存 |
400 |
客户端请求语法错误 |
401 |
Unauthorized 进入网址(URL)资源,需要用户身份验证 |
403 |
客户端没有访问内容权限 |
404 |
Not Found,找不到请求资源 |
499 |
对应的是 “client has closed connection”,这很有可能是因为服务器端处理的时间过长或者两次提交post过快就会出现499(并发场景下易出现)服务器错误 |
500 |
服务器错误 |
502 |
Bad Gateway 服务器网关错误,得到错误响应 |
504 |
Gateway Time-out 服务器网关超时 |
状态码499时处理方案: |
- 前端将timeout最大等待时间设置大一些
- nginx上配置proxy_ignore_client_abort on;
TCP三次握手
- 第一次:客户端向服务端发起建立连接请求。客户端进入SYN-SENT(同步已发送状态)状态
- 第二次:服务端给客户端回复一段报文。服务端进入SYN-RCVD(同步收到)状态
- 第三次:客户端收到服务端发来的报文后,会再向服务端发送报文。客户端进入ESTABLISHED(已建立连接)状态,服务端收到确认报文也进入ESTABLISHED状态
TCP四次挥手
- 第一次:客户端进程发出连接释放报文,并且停止发送数据。客户端进入FIN-WAIT-1 状态
- 第二次:服务器收到连接释放报文,发出确认报文(ACK)。 服务端进入CLOSE-WAIT(等待关闭)状态;客户端收到服务器的确认请求后,进入FIN-WAIT-2状态
- 第三次:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文。服务端进入LAST-ACK(最后确认)状态
- 第四次:客户端收到服务器的连接释放报文后,必须发出确认(ACK)后进入TIME-WAIT(时间等待)状态,经过2MSL进入CLOSE状态。服务器只要收到了客户端发出的确认,立即进入CLOSED状态
- 规定是MSL为2分钟,2MSL就是4分钟
服务器中redis time-wait过多解决办法
- 服务器端允许 time_wait 状态的 socket 被重用
- 缩减 time_wait 时间,设置为 1 MSL(即,2 mins)
net.ipv4.tcp_syncookies = 1 表示开启SYN Cookies。当出现SYN等待队列溢出时,启用cookies来处理,可防范少量SYN攻击,默认为0,表示关闭;
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
TCP协议心跳多长时间
- TCP协议中的SO_KEEPALIVE,系统默认是设置2小时的心跳频率
- 若两个小时都没有收到客户端的数据,服务端就发送一个探测报文段,以后则每隔 75 秒钟发送一次。若连续发送 10 个探测报文段后仍然无客户端的响应,服务端就认为客户端出了故障,接着就关闭这个连接
TCP的半连接队列和全连接队列
- TCP 三次握手时,客户端发送 SYN 到服务端,服务端收到之后,便回复ACK 和 SYN,状态由LISTEN 变为 SYN_RCVD,此时这个连接就被推入了SYN 队列,即半连接队列。
- 当客户端回复 ACK, 服务端接收后,三次握手就完成了。这时连接会等待被具体的应用取走,在被取走之前,它被推入 ACCEPT 队列,即全连接队列
什么是 SYN洪泛攻击
- SYN洪泛攻击利用TCP半连接状态
- 在三次握手过程中,服务器发送 [SYN/ACK] 包(第二个包)之后、收到客户端的 [ACK] 包(第三个包)之前的 TCP 连接称为半连接(half-open connect),此时服务器处于 SYN_RECV(等待客户端响应)状态。如果接收到客户端的 [ACK],则 TCP 连接成功,如果未接受到,则会不断重发请求直至成功
- 这些伪造的 [SYN] 包将长时间占用未连接队列,影响了正常的 SYN,导致目标系统运行缓慢、网络堵塞甚至系统瘫痪
- 当在服务器上看到大量的半连接状态时,特别是源 IP 地址是随机的,基本上可以断定这是一次 SYN 攻击
SYN洪泛攻击如何防范
- 通过防火墙、路由器等过滤网关防护
- 通过加固 TCP/IP 协议栈防范,如增加最大半连接数,缩短超时时间
- SYN cookies技术。SYN Cookies 是对 TCP 服务器端的三次握手做一些修改,专门用来防范 SYN 洪泛攻击的一种手段
CSRF攻击,DDoS攻击,XSS攻击
- CSRF攻击:跨站请求伪造,挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法
- CSRF(通常)发生在第三方域名,CSRF攻击者不能获取到Cookie等信息,只能使用
- 因此防护策略1阻止不明外域访问,即检查检查Referer字段
- 防护策略2:如表单提交增加校验的token
- DDoS攻击:攻击者会生成大量数据包或请求,最终使目标系统不堪重负,导致正常用户无法访问
- 防护策略可用高防服务器,增加黑名单,CDN 加速等
- XSS攻击:跨站脚本攻击,在网站上注入恶意的客户端代码
- 防护策略:跟sql注入一样,注意检查参数,进行输入过滤,有html代码时进行转义
HTTP 如何实现长连接?在什么时候会超时?
- TTP 分为长连接和短连接,本质上说的是 TCP 的长短连接。TCP 连接是一个双向的通道,它是可以保持一段时间不关闭的,因此 TCP 连接才具有真正的长连接和短连接这一说法。
- TCP 长连接可以复用一个 TCP 连接,来发起多次的 HTTP 请求,这样就可以减少资源消耗,比如一次请求 HTML,如果是短连接的话,可能还需要请求后续的 JS/CSS
- HTTP通过在头部(请求和响应头)设置Connection字段指定为keep-alive,HTTP/1.0 协议支持,但是是默认关闭的,从 HTTP/1.1 以后,连接默认都是长连接
- HTTP 一般会有 httpd 守护进程,里面可以设置keep-alive timeout,当 tcp 连接闲置超过这个时间就会关闭,也可以在 HTTP 的 header 里面设置超时时间
HTTP1.1 和 HTTP2.0区别
- HTTP1.1为文本传输,HTTP2.0压缩为二进制流式传输,但HTTP2.0未改变1.1的语义
- HTTP1.1 冗余文本过多,导致传输体积很大.
- HTTP1.1 并发能力差,网络资源利用率低(同一个TCP连接中,无法区分request/response是属于哪个请求,服务的响应需要严格按照request顺序排列)
- 浏览器同时创建多个TCP连接,实现并发下载数据。浏览器为了兼顾下载速度和资源消耗,会对同一个域名限制并发的TCP连接数量(Chrome是6个左右,剩下的请求则需要排队)
- HTTP管道化引起的请求队头阻塞,要求服务端必须按照请求发送的顺序返回响应,那如果一个响应返回延迟了,那么其后续的响应都会被延迟,直到队头的响应送达
- HTTP2.0 引入帧、流的概念,(每个传输流有个专属的流id,)在TCP连接中,可以区分出多个request/response
- HTTP2.0 一个域名只会有一个TCP连接,借助帧、流可以实现多路复用,降低资源消耗
- HTTP2.0 引入二进制编码,降低header带来的空间占用
HTTP的请求过程
- 客户端进行 DNS 域名解析,得到对应的 IP 地址
- 根据这个 IP,找到对应的服务器建立连接(三次握手)
- 建立 TCP 连接后发起 HTTP 请求(一个完整的 http 请求报文)
- 服务器响应 HTTP 请求,客户端得到 html 代码
- 客户端解析 html 代码,用 html 代码中的资源 (如 js,css, 图片等等) 渲染页面。
- 服务器关闭 TCP 连接(四次挥手)
WebSocket 与 socket 的区别
- Socket是传输控制层接口,WebSocket是应用层协议
- Socket 是一套标准,它完成了对 TCP/IP 的高度封装,屏蔽网络细节,是网编编程的标准接口
- WebSocket 是一个持久化的协议,它是伴随 H5 而出的协议,用来解决http 不支持持久化连接的问题
服务器出现了大量 CLOSE_WAIT 状态如何解决
- 服务器端收到客户端发送的FIN后,TCP 协议栈就会自动发送 ACK,接着进入CLOSE_WAIT状态。
- 但是如果服务器端不执行 socket 的 close() 操作,那么就没法进入 LAST_ACK, 导致大量连接处于 CLOSE_WAIT 状态
- 所以,如果服务器出现了大量CLOSE_WAIT状态,一般是程序 Bug,或者关闭 socket 不及时。
服务器上出现大量的TIME_WAIT连接原因及处理
- TIME_WAIT 是主动断开连接的一方会进入的状态,一般情况下,都是客户端所处的状态;服务器端一般设置不主动关闭连接
- 从服务器来讲,短时间内关闭了大量的Client连接,就会造成服务器上出现大量的TIME_WAIT连接,严重消耗着服务器的资源,此时部分客户端就会显示连接不上
- 从客户端来讲,客户端TIME_WAIT过多,就会导致端口资源被占用,因为端口就65536个,被占满就会导致无法创建新的连接
- 解决:强制关闭 (发送 RST 包越过TIME_WAIT状态,直接进入CLOSED状态)
- 解决:复用TIME_WAIT状态TCP连接 (服务器可以设置 SO_REUSEADDR 套接字选项来避免 TIME_WAIT状态,此套接字选项告诉内核,即使此端口正忙(处于TIME_WAIT状态),也请继续并重用它)
- 解决:快速回收,缩短TIME_WAIT时间 (调整系统内核参数,修改/etc/sysctl.conf文件,即修改net.ipv4.tcp_tw_reuse 和 tcp_timestamps)
net.ipv4.tcp_tw_reuse = 1 表示开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0,表示关闭;
net.ipv4.tcp_tw_recycle = 1 表示开启TCP连接中TIME-WAIT sockets的快速回收,默认为0,表示关闭。
TCP 的流量控制
- TCP 提供一种机制可以让发送端根据接收端的实际接收能力控制发送的数据量,这就是流量控制
- 经过三次握手后TCP进行流量窗口初始化,接收端和发送端都为 400 个字节
- 发送端向接收端发送200字节后发送方的win会减少200字节
- 接收端收到会放到缓冲队列里,同时将接收方计算缓冲区窗口剩余大小即400-200=200。将缩小后的滑动窗口 200 字节在 ACK 的报文首部带上传给发送方
- 发送方收到ACK报文首部滑动窗口返回的大小值继续工作,直到接受窗口 win 变为 0
- 发送方停止发送,开启一个定时任务,每隔一段时间,就去询问接受方,直到 win 大于 0,才继续开始发送
TCP 的粘包和拆包
- TCP 是面向流,没有界限的一串数据,一个完整的包可能会被 TCP 拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送
- 要发送的数据小于 TCP 发送缓冲区的大小,TCP 将多次写入缓冲区的数据一次发送出去,将会发生粘包;
- 接收数据端的应用层没有及时读取接收缓冲区中的数据,将发生粘包;
- 要发送的数据大于 TCP 发送缓冲区剩余空间大小,将会发生拆包;
- 待发送数据大于 MSS(最大报文长度),TCP 在传输前将进行拆包。即 TCP 报文长度 - TCP 头部长度 > MSS。
TCP 粘包和拆包的解决方案
- 发送端将每个数据包封装为固定长度
- 在数据尾部增加特殊字符进行分割
- 将数据分为两部分,一部分是头部,一部分是内容体;其中头部结构大小固定,且有一个字段声明内容体的大小。
TCP 的拥塞控制
- 拥塞控制是为了防止过多数据注入网络,导致网络过载。TCP的拥塞控制采用四个算法实现:慢开始、拥塞避免、快重传、快恢复。 发送方维护一个拥塞窗口(cwnd)的状态变量
- 慢开始:cwnd初始值为1,每个轮次cwnd加倍(指数递增)
- 拥塞避免:慢开始门限ssthresh,当cwnd>ssthresh时,进入拥塞避免,让cwnd每个轮次+1。出现超时,就令ssthresh = cwnd/2,重新进行慢开始
- 快重传:接收方只对最后一个收到的有序报文段进行确认,若发送方发送重复确认,就判断下一个报文段丢失,执行快重传,即立即重传下一报文段。
- 快恢复:若丢失个别报文段,执行快恢复,令ssthresh = cwnd/2, cwnd = ssthresh,直接进入拥塞避免
TCP 的重传机制
- 超时重传:若一个已经发送的报文段在超时时间内没有收到确认,就重传这个报文段
- 快速重传:
- SACK 机制:
- 重复 SACK:
TCP队头阻塞
- TCP是一个按序传输的链条,因此如果其中一个点丢失了,链路上之后的内容就都需要等待
TCP 是如何确保可靠性的呢
- 连接和断开的可靠性(三次握手,四次挥手)、有状态(哪些数据发送了,哪些没发)、可控制(超时重传、流量控制、拥塞控制等)
- TCP 的连接是基于三次握手,而断开则是基于四次挥手。确保连接和断开的可靠性
- TCP 的可靠性,还体现在有状态;TCP 会记录哪些数据发送了,哪些数据被接收了,哪些没有被接受,并且保证数据包按序到达,保证数据传输不出差错
- TCP 的可靠性,还体现在可控制。它有数据包校验、ACK 应答、超时重传 (发送方)、失序数据重传(接收方)、丢弃重复数据、流量控制(滑动窗口)和拥塞控制等机制
TCP 和 UDP 的区别
- TCP:面向连接的可靠交付,以字节流传输,效率低,耗费资源少,适用于对通信数据严格的场景,如文件传输。首部20-60字节。
- UDP:无连接的尽最大努力交付,以数据报文段传输,速度快,耗费资源少,适用于对通信速度要求高的场景,如在线视频。首部8个字节。
为什么视频用UDP
- TCP需要三次握手,建立会话需要时间;
- TCP在网络拥塞时,会调整滑动窗口大小,影响传输速度;
- UDP无连接,没有拥塞控制,会以恒定速度发送数据,缺点是造成丢包,优点是实时性好。
UDP处理丢包
- 发生丢包,就立即发送冗余包,尽快恢复数据;
- 建立长期参考帧,解决连贯性问题;
- 发生网络抖动,降低码率,保证传输数据小于网络带宽。
TCP校验和
- 目的是为了发现TCP首部和数据在发送端到接收端之间发生的任何改动。如果接收方检测到检验和有差错,则TCP段会被直接丢弃。
- 校验和的计算方法是将TCP报头和数据中所有字段的二进制值,视为一个大的整数,然后对该整数进行位数补码
- 发送方:把校验和字段设置为0,把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和,把得到的结果存入校验和字段中
- 接收方:将所有原码 相加,高位叠加, 如全为1,则正确
操作系统相关
多线程的优缺点
- 能适当提高程序的执行效率
- 能适当提高资源的利用率(CPU&内存)
- 线程上的任务执行后自动销毁
- 缺点:开启大量的线程,会占用大量的内存空间,降低程序的性能
- 缺点:线程越多,cpu在调用线程上的开销就越大
- 缺点:程序设计更加复杂,比如线程简的通信,多线程的数据共享
并发和并行有什么区别
- 并发指在同一时间段内,多个任务都能被处理,但某时某刻只有一个任务在执行,单核处理器可以做到并发
- 并行指的是在同一时刻,有多个任务在被执行,这个需要多核处理器才能完成
select、poll 和 epoll 之间的区别
- select,poll,epoll 都是 IO 多路复用的机制。I/O 多路复用就是通过一种机制监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),就通知程序进行相应的读写操作
- select (底层实现为数组,遍历数组,有连接数限制)仅仅知道有 I/O 事件发生,但并不知道是哪几个流,所以只能无差别轮询所有流,处理的流越多,无差别轮询时间就越长
- poll (底层实现为链表,所以没有连接数限制)本质上和 select 没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个 fd 对应的设备状态, 但是它没有最大连接数的限制,原因是它是基于链表来存储的
- epoll (底层实现为红黑树,通过事件回调方式)会把哪个流发生了怎样的 I/O 事件通知我们,是事件驱动的。