<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>HTTP on Leanku 的博客</title><link>https://www.leanku.com/tags/http/</link><description>Recent content in HTTP on Leanku 的博客</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Tue, 10 Sep 2024 00:00:00 +0000</lastBuildDate><atom:link href="https://www.leanku.com/tags/http/index.xml" rel="self" type="application/rss+xml"/><item><title>Fiddler 实战：从 HTTP 抓包到接口调试</title><link>https://www.leanku.com/post/discovery/fiddler-http-debugging-guide/</link><pubDate>Tue, 10 Sep 2024 00:00:00 +0000</pubDate><guid>https://www.leanku.com/post/discovery/fiddler-http-debugging-guide/</guid><description>&lt;h1 id="fiddler-使用从-http-抓包到接口调试"&gt;Fiddler 使用：从 HTTP 抓包到接口调试&lt;/h1&gt;&#10;&lt;p&gt;在开发 Web、API、移动端应用时，经常会遇到：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;前端请求到底发送了什么？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Token 和 Cookie 有没有正确携带？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;接口为什么返回 401、403 或 500？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;浏览器能访问，程序却访问失败？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;如何修改请求参数重新测试？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;后端接口还没开发好，前端怎么继续联调？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这类问题可以使用 &lt;strong&gt;Fiddler&lt;/strong&gt; 快速定位。&lt;/p&gt;&#10;&lt;p&gt;Fiddler 是一款 HTTP/HTTPS 调试代理工具，可以捕获客户端与服务器之间的网络请求，并查看、修改、重放请求和响应。&lt;/p&gt;&#10;&lt;p&gt;目前主要有 &lt;strong&gt;Fiddler Classic&lt;/strong&gt; 和 &lt;strong&gt;Fiddler Everywhere&lt;/strong&gt;。Classic 主要面向 Windows，并已经进入维护阶段；Everywhere 是当前的跨平台版本。&lt;/p&gt;&#10;&lt;h2 id="1-fiddler-是什么"&gt;1. Fiddler 是什么？&lt;/h2&gt;&#10;&lt;p&gt;正常情况下：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;浏览器&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Web Server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;服务器&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;启用 Fiddler 后：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;浏览器&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Fiddler&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Web Server&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Fiddler 作为代理，可以看到：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Request&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── URL&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Method&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Headers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Cookie&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── Body&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Response&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Status Code&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;├── Headers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── Body&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例如：&lt;/p&gt;</description></item><item><title>一个 HTTP 请求的并发链路：从 Web Server 到 MySQL</title><link>https://www.leanku.com/post/computerscience/http-request-concurrency-chain-webserver-mysql/</link><pubDate>Wed, 10 Jul 2024 00:00:00 +0000</pubDate><guid>https://www.leanku.com/post/computerscience/http-request-concurrency-chain-webserver-mysql/</guid><description>&lt;h1 id="一个-http-请求的并发链路从-web-server-到-mysql"&gt;一个 HTTP 请求的并发链路：从 Web Server 到 MySQL&lt;/h1&gt;&#10;&lt;p&gt;前面的文章分别讨论了并发是什么、进程线程协程如何执行请求、IO 多路复用如何管理大量连接，以及如何用 QPS、并发数和响应时间衡量系统。&lt;/p&gt;&#10;&lt;p&gt;但这些概念真正进入后端系统之后，会形成一条完整的链路：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Web Server / Nginx&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Application&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Process / Thread / Coroutine&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Redis / RPC / MySQL&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Response&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;真正的高并发问题，通常也不是发生在某一个组件上，而是发生在&lt;strong&gt;整个链路的容量不匹配&lt;/strong&gt;上。&lt;/p&gt;&#10;&lt;p&gt;例如：&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;Web Server 可以接收 10000 个连接，应用可以运行 1000 个协程，但 MySQL 连接池只有 50 个连接。&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;这并不意味着系统只能处理 50 个 HTTP 请求，但意味着&lt;strong&gt;同时进行数据库操作的请求最多受到这 50 个连接的约束&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;因此，理解高并发，不能只看 Web Server 或应用服务器，而要沿着一次请求完整地看下去。&lt;/p&gt;&#10;&lt;h2 id="1-一个-http-请求到底经过哪些组件"&gt;1. 一个 HTTP 请求到底经过哪些组件？&lt;/h2&gt;&#10;&lt;p&gt;假设用户访问：&lt;/p&gt;</description></item><item><title>理解并发：一个 HTTP 请求到后端到底发生了什么？</title><link>https://www.leanku.com/post/computerscience/understanding-concurrency-http-request/</link><pubDate>Mon, 10 Jun 2024 00:00:00 +0000</pubDate><guid>https://www.leanku.com/post/computerscience/understanding-concurrency-http-request/</guid><description>&lt;h1 id="理解并发一个-http-请求到后端到底发生了什么"&gt;理解并发：一个 HTTP 请求到后端到底发生了什么？&lt;/h1&gt;&#10;&lt;p&gt;在开发后端系统时，我们经常会看到这样的描述：&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;“这个接口支持 1000 并发。”&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;但“1000 并发”到底意味着什么？&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;是不是意味着服务器同时启动 1000 个线程？&lt;/li&gt;&#10;&lt;li&gt;是不是意味着 CPU 同时执行 1000 个请求？&lt;/li&gt;&#10;&lt;li&gt;如果一个请求正在等待 MySQL，CPU 又在做什么？&lt;/li&gt;&#10;&lt;li&gt;一个 PHP/Hyperf 服务为什么可以同时处理大量 HTTP 请求？&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;要真正理解高并发，不能一开始就从 QPS、限流、缓存这些概念入手，而应该先理解一个最基本的问题：&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;一个 HTTP 请求进入后端以后，到底发生了什么？&lt;/strong&gt;&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-先理解什么是并发"&gt;1. 先理解什么是并发&lt;/h2&gt;&#10;&lt;p&gt;&lt;strong&gt;并发&lt;/strong&gt;（Concurrency）描述的是：&lt;/p&gt;&#10;&lt;p&gt;&lt;strong&gt;多个任务在同一个时间段内处于进行状态，并且它们的执行过程存在交错。&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;并发和并行（Parallelism）不是同一个概念。&lt;/p&gt;&#10;&lt;p&gt;例如：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;任务 A：████████&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;任务 B： ████████&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;两个任务都在进行，但可能只有一个 CPU 核心。&lt;/p&gt;&#10;&lt;p&gt;CPU 可以先执行 A：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A A A A&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后因为 A 正在等待 IO，转而执行 B：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A A → 等待&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ↓&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; B B B B&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这属于&lt;strong&gt;并发&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;如果机器有多个 CPU 核心：&lt;/p&gt;</description></item><item><title>WebSocket 详解：实时双向通信是如何实现的？</title><link>https://www.leanku.com/post/computerscience/websocket-real-time-communication/</link><pubDate>Sat, 16 Sep 2023 00:00:00 +0000</pubDate><guid>https://www.leanku.com/post/computerscience/websocket-real-time-communication/</guid><description>&lt;h1 id="websocket-详解实时双向通信是如何实现的"&gt;WebSocket 详解：实时双向通信是如何实现的？&lt;/h1&gt;&#10;&lt;p&gt;前面几篇分别介绍了 TCP/IP、Socket、HTTP 和 HTTPS。&lt;/p&gt;&#10;&lt;p&gt;到这里，一个问题自然出现了：&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;HTTP 已经可以完成客户端和服务器之间的通信，为什么还需要 WebSocket？&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;因为传统 HTTP 的基本模型是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ Request&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ Response&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果服务器想主动通知客户端，就比较麻烦。&lt;/p&gt;&#10;&lt;p&gt;例如：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;用户收到新消息&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;订单状态发生变化&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;股票价格发生变化&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;游戏状态发生变化&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;服务器有数据更新，但客户端没有主动发请求。&lt;/p&gt;&#10;&lt;p&gt;传统方案只能不断：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client → Server：有新消息吗？&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server → Client：没有&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client → Server：有新消息吗？&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server → Client：没有&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client → Server：有新消息吗？&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server → Client：有&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这就是&lt;strong&gt;轮询&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;WebSocket 的目标就是解决这类问题：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client ⇄ Server&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;建立连接之后，双方都可以主动发送数据。&lt;/p&gt;&#10;&lt;p&gt;RFC 6455 将 WebSocket 定义为一种基于 TCP 的双向通信协议，协议由连接建立握手和数据帧传输两部分组成。&lt;/p&gt;</description></item><item><title>HTTP 详解：一次请求背后发生了什么？</title><link>https://www.leanku.com/post/computerscience/http-network-communication/</link><pubDate>Tue, 01 Aug 2023 00:00:00 +0000</pubDate><guid>https://www.leanku.com/post/computerscience/http-network-communication/</guid><description>&lt;h1 id="http-详解一次请求背后发生了什么"&gt;HTTP 详解：一次请求背后发生了什么？&lt;/h1&gt;&#10;&lt;p&gt;在 Web 开发中，HTTP 几乎无处不在。&lt;/p&gt;&#10;&lt;p&gt;浏览器访问一个页面，前端调用一个 API，PHP、Java、Go 服务之间进行 RPC，下载文件，提交表单，这些场景背后都可能使用 HTTP。&lt;/p&gt;&#10;&lt;p&gt;但很多开发者真正理解的 HTTP 只是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GET /users&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;POST /login&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;200 OK&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: application/json&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果继续往下追问：&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;浏览器输入一个 URL 后，到底发生了什么？&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;就会涉及 DNS、TCP、TLS、HTTP、连接复用、请求报文、响应报文、缓存等多个环节。&lt;/p&gt;&#10;&lt;p&gt;理解这些内容之后，很多常见问题都会变得容易：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么第一次请求比较慢？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么 HTTP/1.1 需要 Keep-Alive？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HTTP/2 为什么能够同时处理多个请求？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Cookie 和 Session 到底是什么关系？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;304 是什么意思？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么 API 经常返回 401、403、404、409？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HTTPS 到底保护了什么？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HTTP 和 Socket、TCP 又是什么关系？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;本文从一次实际请求开始，把这些概念串起来。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-http-到底是什么"&gt;1. HTTP 到底是什么？&lt;/h2&gt;&#10;&lt;p&gt;HTTP（Hypertext Transfer Protocol，超文本传输协议）是一个&lt;strong&gt;应用层的请求/响应协议&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;它的核心模型非常简单：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ HTTP Request&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ HTTP Response&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;客户端发送 Request，服务端返回 Response。&lt;/p&gt;</description></item><item><title>HTTP 详解：一次请求背后发生了什么？</title><link>https://www.leanku.com/post/computerscience/http-network-communication/</link><pubDate>Tue, 01 Aug 2023 00:00:00 +0000</pubDate><guid>https://www.leanku.com/post/computerscience/http-network-communication/</guid><description>&lt;h1 id="http-详解一次请求背后发生了什么"&gt;HTTP 详解：一次请求背后发生了什么？&lt;/h1&gt;&#10;&lt;p&gt;在 Web 开发中，HTTP 几乎无处不在。&lt;/p&gt;&#10;&lt;p&gt;浏览器访问一个页面，前端调用一个 API，PHP、Java、Go 服务之间进行 RPC，下载文件，提交表单，这些场景背后都可能使用 HTTP。&lt;/p&gt;&#10;&lt;p&gt;但很多开发者真正理解的 HTTP 只是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GET /users&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;POST /login&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;200 OK&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: application/json&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果继续往下追问：&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;浏览器输入一个 URL 后，到底发生了什么？&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;就会涉及 DNS、TCP、TLS、HTTP、连接复用、请求报文、响应报文、缓存等多个环节。&lt;/p&gt;&#10;&lt;p&gt;理解这些内容之后，很多常见问题都会变得容易：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么第一次请求比较慢？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么 HTTP/1.1 需要 Keep-Alive？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HTTP/2 为什么能够同时处理多个请求？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Cookie 和 Session 到底是什么关系？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;304 是什么意思？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么 API 经常返回 401、403、404、409？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HTTPS 到底保护了什么？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HTTP 和 Socket、TCP 又是什么关系？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;本文从一次实际请求开始，把这些概念串起来。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-http-到底是什么"&gt;1. HTTP 到底是什么？&lt;/h2&gt;&#10;&lt;p&gt;HTTP（Hypertext Transfer Protocol，超文本传输协议）是一个&lt;strong&gt;应用层的请求/响应协议&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;它的核心模型非常简单：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ HTTP Request&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ HTTP Response&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;客户端发送 Request，服务端返回 Response。&lt;/p&gt;</description></item><item><title>HTTP 详解：一次请求背后发生了什么？</title><link>https://www.leanku.com/post/computerscience/http-network-communication/</link><pubDate>Tue, 01 Aug 2023 00:00:00 +0000</pubDate><guid>https://www.leanku.com/post/computerscience/http-network-communication/</guid><description>&lt;h1 id="http-详解一次请求背后发生了什么"&gt;HTTP 详解：一次请求背后发生了什么？&lt;/h1&gt;&#10;&lt;p&gt;在 Web 开发中，HTTP 几乎无处不在。&lt;/p&gt;&#10;&lt;p&gt;浏览器访问一个页面，前端调用一个 API，PHP、Java、Go 服务之间进行 RPC，下载文件，提交表单，这些场景背后都可能使用 HTTP。&lt;/p&gt;&#10;&lt;p&gt;但很多开发者真正理解的 HTTP 只是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GET /users&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;POST /login&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;200 OK&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Content-Type: application/json&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如果继续往下追问：&lt;/p&gt;&#10;&lt;blockquote&gt;&#10;&lt;p&gt;浏览器输入一个 URL 后，到底发生了什么？&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;p&gt;就会涉及 DNS、TCP、TLS、HTTP、连接复用、请求报文、响应报文、缓存等多个环节。&lt;/p&gt;&#10;&lt;p&gt;理解这些内容之后，很多常见问题都会变得容易：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么第一次请求比较慢？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么 HTTP/1.1 需要 Keep-Alive？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HTTP/2 为什么能够同时处理多个请求？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;Cookie 和 Session 到底是什么关系？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;304 是什么意思？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;为什么 API 经常返回 401、403、404、409？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HTTPS 到底保护了什么？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;HTTP 和 Socket、TCP 又是什么关系？&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;本文从一次实际请求开始，把这些概念串起来。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-http-到底是什么"&gt;1. HTTP 到底是什么？&lt;/h2&gt;&#10;&lt;p&gt;HTTP（Hypertext Transfer Protocol，超文本传输协议）是一个&lt;strong&gt;应用层的请求/响应协议&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;p&gt;它的核心模型非常简单：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ HTTP Request&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Server&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ HTTP Response&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Client&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;客户端发送 Request，服务端返回 Response。&lt;/p&gt;</description></item></channel></rss>