Skip to content

HTTP 和 Web

浏览器找到服务器之后,还得有一套双方都懂的"说话格式"——这就是 HTTP。浏览器发请求、服务端回响应,页面、图片、接口数据全靠这一来一回传。打个比方,TCP 像是拉通了双方的电话线,TLS 负责给通话加密,HTTP 则是双方约定的语言——说什么、怎么回、错了怎么办。

一、请求与响应

HTTP 请求本质上就是一段文本。一个最简单的 GET 请求长这样:

http
GET /docs/index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html

第一行是请求行——GET 是方法,/docs/index.html 是路径,HTTP/1.1 是协议版本;后面几行都是 Header,Host 必带(因为同一台服务器可能挂多个站,要靠它区分),User-Agent 告诉服务端是什么浏览器,Accept 说明客户端想收什么格式。

服务端返回的响应也是类似结构:

http
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Cache-Control: max-age=300

<html>...</html>

第一行 200 OK 是状态码和状态文本;接着是响应头,告诉客户端响应体是什么格式、要不要缓存、缓存多久;空一行之后是真正的响应体——这里是一段 HTML。

排查问题的时候,直接 curl -v https://www.example.com 就能把请求和响应的完整文本打出来,看着比浏览器 Network 面板更直观。

二、HTTP 方法

HTTP 方法告诉服务端这次请求想干什么——读、写、改还是删:

方法干什么典型场景
GET读资源打开页面、查询列表、获取详情
POST创建或者提交登录、提交表单、新建任务
PUT整体替换某个资源更新一个对象的全部字段
PATCH局部更新只改某一个字段
DELETE删除资源删除任务、删除文件

浏览器打开页面绝大多数都是 GET。前端调后端接口时,路径会写成 /api/users/api/tasks/123 这种样子——路径本身只是个名字,具体这个路径对应什么动作、由哪段代码处理,是后端路由决定的,跟方法名和路径都没有强绑定关系。所以光看一个 URL 不一定知道它是干啥的,得看代码或者接口文档。

三、Header

Header 是请求和响应里的"附加字段",信息量大,排查问题经常要看。常用的几个:

Header干什么
Host访问的域名,Nginx 靠它分流
Content-Type请求体或响应体是什么格式(application/jsontext/htmlmultipart/form-data)
Authorization登录后的认证信息,通常是 Bearer <token>
Cookie浏览器存的站点数据,登录态经常靠它
Cache-Control缓存策略,客户端和 CDN 都看这个
X-Forwarded-For代理转发之后保留的原始客户端 IP

最后这个 X-Forwarded-For 是个坑点。请求经过 Nginx、负载均衡、网关之后,后端看到的"客户端 IP"其实是上一层代理的 IP,不是用户真实 IP。如果想拿真实 IP 做风控或者日志,要靠入口层在 Header 里塞 X-Forwarded-For 这种字段,后端读这个字段才行。如果入口没配,后端拿到的就是 LB 内网 IP,排查异常请求的时候会一脸懵。

四、状态码

状态码是服务端告诉客户端"这次请求处理得怎么样"。记一下范围就行:2xx 成功、3xx 重定向或缓存、4xx 客户端这边有问题、5xx 服务端这边有问题。

具体到常用的:

状态码用户侧现象大概率卡在哪
200正常返回没问题
301/302自动跳到另一个地址重定向配置,可能是 HTTP 跳 HTTPS、或者旧域名跳新域名
304浏览器用了本地缓存缓存命中,不是错误
400请求参数格式不对前端传错字段、JSON 格式坏掉
401未登录或认证失败Token 过期、Cookie 没带
403没权限登录了但角色不够、IP 被拉黑
404页面或接口不存在路径错了、路由没配
500后端处理时报错应用代码异常、数据库连不上、下游服务挂
502网关连接后端失败后端实例没起来、端口不对、连接被拒绝
504网关等后端超时后端处理太慢、被入口层超时切了

排查时同样一个 404,根因可能完全不一样——前端路由配置错、Nginx location 没匹配上、后端路由没注册,都会让用户看到 404。502 则更具体一些,基本就是入口到后端这一段:upstream 端口配错、后端 Pod 没起来、Kubernetes Service 没有 Endpoints、后端进程崩了。看到 502,先去入口层(Nginx/Ingress)的 error log 看一眼,基本能直接定位。

五、登录状态

HTTP 协议本身是"无状态"的——服务端处理完一个请求就忘了,下一个请求过来服务端不认识你。但网站登录明显不能这样,你登录一次之后,关掉再打开浏览器还是登录态。靠的是 Cookie、Session、Token 这几种机制。

最经典的做法是 Cookie + Session:用户登录成功后,服务端生成一个会话 ID(Session ID),通过响应头里的 Set-Cookie 让浏览器存到 Cookie 里;浏览器后续请求会自动带上 Cookie,服务端拿到 Session ID 就能识别出这是哪个用户。Session 数据存在服务端(内存、Redis、数据库里),所以服务端重启或者多实例时不共享 Session,就会出现"刷新一下就掉登录"的问题。

前后端分离系统现在更常用 Token:登录接口成功后返回一个 Token(通常是 JWT),前端把 Token 存起来(localStorage 或者内存),后续每个请求在 Authorization Header 里带上 Bearer <token>。Token 不需要服务端保存会话,天然支持多实例和跨域,这也是为什么微服务架构基本都用 Token。

六、页面与接口

一个网站对外提供的东西大致分两类:静态资源和动态接口。

类型具体是什么放在哪里
静态资源HTML、CSS、JS、图片、字体Nginx、对象存储、CDN
动态接口用户数据、订单、任务、统计后端应用 + 数据库 + 缓存

传统网站(比如 PHP、JSP 那个年代)是服务端直接拼好完整 HTML 再返回,前后端不分离。现在主流是前后端分离:浏览器先拉静态资源,JS 跑起来之后再调后端 API 拿 JSON 数据,前端渲染。

页面白屏的时候排查顺序:打开浏览器 Network 颜板,先看 HTML 是不是 200(不是的话基本是入口层问题);再看 JS/CSS 文件有没有 404(前端构建路径或者发布路径有问题);最后看 API 返回什么——401 是没登录、500 是后端炸了、CORS 报错是跨域没配。这一套流程走完,白屏问题基本能定位。