一、HTTPS建立连接的过程
证书申请阶段(前置准备)
在正式建立连接前,服务器需要向证书机构(CA)申请SSL证书:
- 服务器将自己的公钥发给CA机构
- CA机构用自己的私钥对服务器的公钥进行加密,生成SSL证书
- 服务器存储SSL证书,供后续安全连接使用
连接建立详细流程
第1步:TCP三次握手 客户端与服务器先建立TCP连接(这是HTTPS的基础)
第2步:服务器发送SSL证书 服务器将SSL证书发送给客户端,证书包含:
- 证书的发布机构(CA)
- 证书的有效期
- 服务器的公钥
- 证书所有者
- 数字签名
第3步:客户端验证证书(以浏览器为例)
- 浏览器检查证书所有者、有效期等基本信息
- 查找操作系统中内置的受信任CA证书,比对颁发者
- 如果找不到,浏览器报错(证书不可信)
- 如果找到,用CA的公钥解密证书中的签名
- 用相同hash算法计算证书hash值,与解密后的签名对比
- 一致则证明证书合法,读取公钥用于后续加密
为什么需要CA?
假设没有CA,可能发生中间人攻击:
正常流程:服务器公钥 → 客户端
被攻击:服务器公钥被hack截获 → hack将自己的公钥发给客户端 → 客户端用hack公钥加密数据 → hack解密获取数据 → hack用服务器公钥加密转发
有了CA后,客户端内置的CA根证书能识别出hack的证书不合法,有效防止中间人攻击。
二、HTTP的缓存策略是怎么样的?
HTTP缓存主要分为强缓存和对比缓存两种,优先级:强缓存 > 对比缓存
强缓存
浏览器直接从本地缓存读取数据,不再向服务器发送请求
实现字段:
- Expires:缓存到期时间(绝对时间,服务器时间+缓存有效期)
- 缺点:客户端修改本地时间会导致缓存失效;本地时间与服务器时间不一致也会失效
- Cache-Control:缓存最大有效时间(相对时间)
- 优点:即使本地时间与服务器不一致,也不会导致缓存失效
- 常用取值:
max-age:最大有效时间(秒)no-cache:没有缓存s-maxage:同max-age,仅用于共享缓存(如CDN)public:多用户共享缓存(默认)private:不能多用户共享
对比缓存
先向服务器发送请求,带上缓存标识,由服务器判断是否使用缓存
Last-Modified/If-Modified-Since
- 响应头返回
Last-Modified(资源最后修改时间) - 请求头带上
If-Modified-Since(上次获取的修改时间) - 服务器判断资源是否更新:
- 有更新:返回新资源(状态码200)
- 无更新:返回304,浏览器使用缓存
缺点:
- 只能精确到秒级,1秒内多次修改无法准确标识
- 内容未变但修改时间改变,导致缓存失效
Etag/If-None-Match
- 响应头返回
Etag(资源版本号) - 请求头带上
If-None-Match(上次的版本号) - 服务器对比版本号决定返回200还是304
缓存优先级
强缓存(Cache-Control) > 强缓存(Expires) > 对比缓存(Etag) > 对比缓存(Last-Modified)
三、TCP三次握手和四次挥手是怎么样的?
三次握手(建立连接)
客户端 服务端
|----SYN---->|
|<--SYN+ACK--|
|----ACK---->|
详细流程:
- 客户端发SYN:生成随机数J作为序号,发送SYN包(seq=J),进入
SYN_SENT状态 - 服务端回应SYN+ACK:进入
SYN_RECV状态,发送SYN包(ACK=1,ack=J+1,seq=K) - 客户端发ACK:检查ACK=1且ack=J+1,发送ACK包(ACK=1,ack=K+1)
- 双方进入
ESTABLISHED状态,连接建立成功
四次挥手(断开连接)
客户端 服务端
|----FIN---->| 客户端→服务端断开
|<---ACK-----| 服务端确认
|<---FIN-----| 服务端→客户端断开
|----ACK---->| 客户端确认
详细流程:
- 客户端发FIN:发送FIN包(seq=J),进入
FIN_WAIT_1,表示客户端无数据发送 - 服务端回ACK:发送ACK包(ack=J+1),进入
CLOSE_WAIT,客户端收到后进入FIN_WAIT_2 - 服务端发FIN:服务端无数据后,发送FIN包,进入
LAST_ACK - 客户端回ACK:发送ACK包,进入
TIME_WAIT,超时后自动关闭;服务端收到ACK后进入CLOSE
TIME_WAIT的意义:如果ACK包丢失,服务端会重发FIN,客户端可以在TIME_WAIT状态下重发ACK。
四、TCP怎么保证可靠性的?
TCP通过多种机制共同保障可靠性:
1. 校验和
将数据切分成16位二进制串,求和得到校验和。接收方用相同算法计算,对比校验和是否一致,防止数据损坏。
2. 序列号/确认应答 + 超时重传
- 每个数据包都有序号
- 接收方收到数据返回ACK确认
- 超过超时时间未收到ACK,触发超时重传
- 超时时间动态变化:初始值>正常往返时间,重传失败则指数增加
- Linux中以500ms为单位,重传超时依次为500ms、2500ms、4500ms...
- 重传次数累计到阈值后,关闭连接
3. 最大消息长度(MSS)
建立连接时双方约定MSS作为发送单位,理想情况下刚好不被网络层分块。
4. 滑动窗口控制
发送方不需要等待每个包的确认,只要包在滑动窗口内就可以发送。每收到一个确认应答,窗口向后移动一位。
5. 流量控制
接收方根据缓冲区情况,动态调整滑动窗口大小,通知发送方调整发送速率,防止接收方缓冲区溢出。
五、TCP拥塞控制怎么实现?
拥塞控制由四个算法组成:慢启动、拥塞避免、拥塞发生时算法、快速恢复
1. 慢启动
- 连接刚建立时,拥塞窗口cwnd初始为1
- 每收到一个ACK确认,cwnd+1
- 每个往返时延RTT,窗口大小翻倍(指数增长)
- 目的:试探网络承受能力
2. 拥塞避免
- 当cwnd达到慢启动阈值ssthresh时,停止指数增长
- 进入线性增长:每个RTT,cwnd+1
- 目的:避免超过网络承载能力导致拥塞
3. 拥塞发生时算法
判定拥塞的依据(丢包):
- 超时重传:超过RTO未收到ACK
- 三个重复ACK:收到3个以上相同的ACK(如连续收到3个ACK=2,说明包3丢失)
处理方式:
- 将ssthresh设置为当前窗口大小的一半
- 判定拥塞后触发快速恢复
补充:快重传 收到失序报文时,接收方立即返回已收到的最新序号ACK(如收到包4但没收到包3,仍返回ACK=2)。连续3个重复ACK触发发送方快速重传丢失的包。
4. 快速恢复算法
- TCP Tahoe(早期算法):cwnd重置为1,重新慢启动
- TCP Reno(现在常用):cwnd设置为新的ssthresh,进入拥塞避免(线性增长)
六、close_wait太多怎么处理?
close_wait产生原因
四次挥手中,服务端返回ACK应答后,如果还有数据要发给客户端,会进入close_wait状态。如果被动关闭方没有及时发出FIN包,就会一直停留在close_wait状态。
解决方案
可以调整TCP空闲连接存活时间:
tcp_keepalive_time = 7200 # 默认2小时,可调小
time_wait太多的问题及处理
产生原因:高并发短连接场景下,主动关闭方进入TIME_WAIT状态,端口资源(0-65535)有限,持续高并发会导致端口耗尽。
解决方案(修改系统配置):
net.ipv4.tcp_syncookies = 1 # 开启SYN Cookies,防范SYN攻击
net.ipv4.tcp_tw_reuse = 1 # 允许TIME-WAIT sockets重新用于新连接
net.ipv4.tcp_tw_recycle = 1 # 开启TIME-WAIT sockets快速回收
net.ipv4.tcp_fin_timeout = 30 # 修改默认TIMEOUT时间
HTTP/2 有哪些新特性?
1. 二进制传输
- 采用二进制格式传输数据,而非HTTP/1.x的纯文本
- 协议解析更高效
- 将请求和响应数据分割为更小的帧,二进制编码
- 同域名下所有通信在单个连接上完成,承载任意数量双向数据流
2. Header压缩(HPACK算法)
- 客户端和服务器建立"字典",用索引号表示重复字符串
- 采用哈夫曼编码压缩整数和字符串,压缩率达50%-90%
- 首部表在连接存续期内始终存在,渐进更新
- 新请求只需发送差异数据,减少冗余
3. 多路复用
- 解决浏览器对同域名请求数量的限制
- 更容易实现全速传输
- 避免了TCP连接的慢启动过程
4. Server Push(服务器推送)
- 服务器可主动向客户端发送消息
- 例如:浏览器请求HTML时,服务器提前推送可能用到的JS、CSS文件
- 减少等待延迟
5. 提高安全性
- 虽然不强制加密,但主流浏览器只支持加密的HTTP/2
- 实际应用的HTTP/2都是加密的
- 协议标识:"h2"表示加密,"h2c"表示明文
HTTP报文结构是怎么样的?
请求报文结构
请求行 + 请求头 + 空行 + 请求内容
请求行:请求方法 + URL + 协议版本(空格分隔)
- 请求方法:GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT
请求头:key/value对,每行一对,冒号分隔
- User-Agent:浏览器类型
- Accept:可识别的响应内容类型
- Accept-Language:可接受的自然语言
- Host:请求的主机名
- Connection:连接方式(close或keepalive)
- Cookie:客户端扩展字段
空行:标识请求头结束
请求内容:POST请求的body,配合Content-Type和Content-Length使用
响应报文结构
状态行 + 响应头 + 空行 + 响应内容
状态行:HTTP协议版本 + 状态码 + 状态描述(空格分隔)
- 1xx:接收请求,继续处理
- 2xx:成功处理
- 3xx:重定向
- 4xx:客户端错误
- 5xx:服务器错误
常见状态码:
- 200 OK:请求成功
- 304 Not Modified:资源未修改,可使用缓存
- 400 Bad Request:请求语法错误
- 401 Unauthorized:未经授权
- 404 Not Found:资源不存在
- 500 Internal Server Error:服务器内部错误
- 503 Service Unavailable:服务不可用
响应头:
- Location:重定向位置
- Server:服务器软件信息
- Vary:不可缓存请求头列表
- Connection:连接方式
- Keep-Alive:保持连接时间
空行:标识响应头结束
响应内容:服务器返回的文本信息
HTTP状态码502,503,504各自代表着什么?
502 Bad Gateway
- 含义:网关(一般是Nginx)从后端服务器接收到无效响应
- 常见原因:后端服务器挂了、服务崩溃、无法响应
- 示例:后端Java应用进程突然退出
503 Service Unavailable
- 含义:服务不可用,请求过载
- 常见原因:请求超过Nginx限流设置的阈值
- 示例:服务器配置了每秒最多处理100个请求,超过则返回503
504 Gateway Timeout
- 含义:网关(一般是Nginx)从后端服务器接收响应超时
- 常见原因:后端处理时间过长,超过Nginx等待时间
- 示例:Nginx配置了60秒超时,但后端接口处理需要90秒