<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>后端开发 on Jinnchang</title><link>https://jinnchang.github.io/categories/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91/</link><description>Recent content in 后端开发 on Jinnchang</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sun, 19 Apr 2026 22:15:28 +0800</lastBuildDate><atom:link href="https://jinnchang.github.io/categories/%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91/index.xml" rel="self" type="application/rss+xml"/><item><title>WebSocket</title><link>https://jinnchang.github.io/posts/web-socket/</link><pubDate>Wed, 15 Apr 2026 10:00:00 +0800</pubDate><guid>https://jinnchang.github.io/posts/web-socket/</guid><description>&lt;blockquote&gt;
&lt;p&gt;WebSocket 是一种在单个 TCP 连接上实现全双工通信的协议，让服务器能够主动向客户端推送数据，告别低效的轮询。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="核心概念"&gt;
 核心概念
 &lt;a class="heading-link" href="#%e6%a0%b8%e5%bf%83%e6%a6%82%e5%bf%b5"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;WebSocket（协议标识 &lt;code&gt;ws://&lt;/code&gt; 或加密的 &lt;code&gt;wss://&lt;/code&gt;）解决了 HTTP 请求-响应模型的单向限制。建立连接后，客户端和服务端可以随时互相发送数据，无需等待对方先发起请求。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;握手过程&lt;/strong&gt;：客户端发送 HTTP 请求，携带 &lt;code&gt;Upgrade: websocket&lt;/code&gt; 头；服务端响应 &lt;code&gt;101 Switching Protocols&lt;/code&gt;，连接升级为 WebSocket，后续数据以帧（frame）格式传输。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;实时聊天、消息通知&lt;/li&gt;
&lt;li&gt;在线游戏、协作编辑&lt;/li&gt;
&lt;li&gt;实时监控面板、数据流推送&lt;/li&gt;
&lt;li&gt;远程控制、即时通讯&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;WebSocket vs HTTP&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;维度&lt;/th&gt;
 &lt;th&gt;HTTP&lt;/th&gt;
 &lt;th&gt;WebSocket&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;通信方向&lt;/td&gt;
 &lt;td&gt;客户端请求 → 服务端响应&lt;/td&gt;
 &lt;td&gt;全双工，双向随时&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;连接生命周期&lt;/td&gt;
 &lt;td&gt;短连接（请求结束即断开）&lt;/td&gt;
 &lt;td&gt;持久连接&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;头部开销&lt;/td&gt;
 &lt;td&gt;每次请求携带完整 Header&lt;/td&gt;
 &lt;td&gt;握手后帧头极小（2-14 字节）&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;服务端推送&lt;/td&gt;
 &lt;td&gt;不支持（需轮询/SSE）&lt;/td&gt;
 &lt;td&gt;原生支持&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;协议标识&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;http://&lt;/code&gt; / &lt;code&gt;https://&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;ws://&lt;/code&gt; / &lt;code&gt;wss://&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;可以用 mermaid 图来直观展示握手过程：&lt;/p&gt;
&lt;div class="mermaid"&gt;
sequenceDiagram
participant Client as 客户端
participant Server as 服务端

Client-&gt;&gt;Server: GET /chat HTTP/1.1\nUpgrade: websocket\nConnection: Upgrade\nSec-WebSocket-Key: xxx
Server--&gt;&gt;Client: HTTP/1.1 101 Switching Protocols\nUpgrade: websocket
Note over Client,Server: 连接已建立，进入 WebSocket 模式
Client-&gt;&gt;Server: [Frame] 你好！
Server--&gt;&gt;Client: [Frame] 欢迎加入聊天
Client-&gt;&gt;Server: [Frame] 最近如何？
Server--&gt;&gt;Client: [Frame] 一切正常

&lt;/div&gt;

&lt;h2 id="安装配置"&gt;
 安装配置
 &lt;a class="heading-link" href="#%e5%ae%89%e8%a3%85%e9%85%8d%e7%bd%ae"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;浏览器端原生支持 WebSocket API，无需安装任何库。&lt;/p&gt;</description></item><item><title>Server-Side Rendering</title><link>https://jinnchang.github.io/posts/ssr/</link><pubDate>Sun, 05 Apr 2026 08:45:00 +0800</pubDate><guid>https://jinnchang.github.io/posts/ssr/</guid><description>&lt;blockquote&gt;
&lt;p&gt;将 HTML 在服务器端生成后返回浏览器，解决 SPA 首屏加载慢、SEO 不友好的核心痛点。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="核心概念"&gt;
 核心概念
 &lt;a class="heading-link" href="#%e6%a0%b8%e5%bf%83%e6%a6%82%e5%bf%b5"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;SSR（Server-Side Rendering）&lt;/strong&gt; 指的是在服务器端完成页面渲染，将完整的 HTML 返回给浏览器，而非传统的客户端 JavaScript 动态生成 DOM。&lt;/p&gt;
&lt;p&gt;对比两种渲染方式：&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;渲染方式&lt;/th&gt;
 &lt;th&gt;HTML 来源&lt;/th&gt;
 &lt;th&gt;首屏速度&lt;/th&gt;
 &lt;th&gt;SEO&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;CSR（客户端渲染）&lt;/td&gt;
 &lt;td&gt;空 HTML + JS 构建&lt;/td&gt;
 &lt;td&gt;慢，需下载执行 JS&lt;/td&gt;
 &lt;td&gt;搜索引擎抓取困难&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;SSR（服务端渲染）&lt;/td&gt;
 &lt;td&gt;服务器返回完整 HTML&lt;/td&gt;
 &lt;td&gt;快，直接渲染&lt;/td&gt;
 &lt;td&gt;友好&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;SSR 的渲染流程：&lt;/p&gt;
&lt;div class="mermaid"&gt;
flowchart LR
A[浏览器请求] --&gt; B[服务器接收]
B --&gt; C[执行组件渲染]
C --&gt; D[生成完整 HTML]
D --&gt; E[返回浏览器]
E --&gt; F[浏览器直接显示页面]

&lt;/div&gt;

&lt;h2 id="为什么需要-ssr"&gt;
 为什么需要 SSR
 &lt;a class="heading-link" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e9%9c%80%e8%a6%81-ssr"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;客户端渲染（React/Vue SPA）有三个本质问题：&lt;/p&gt;</description></item><item><title>Server-Sent Events</title><link>https://jinnchang.github.io/posts/sse/</link><pubDate>Wed, 01 Apr 2026 13:10:00 +0800</pubDate><guid>https://jinnchang.github.io/posts/sse/</guid><description>&lt;blockquote&gt;
&lt;p&gt;基于标准 HTTP 的单向实时通信协议，适用于服务端向客户端推送数据的场景。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="核心概念"&gt;
 核心概念
 &lt;a class="heading-link" href="#%e6%a0%b8%e5%bf%83%e6%a6%82%e5%bf%b5"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;SSE 是 HTML5 标准的一部分，允许服务端通过一个持久的 HTTP 连接向客户端持续推送数据流。与 WebSocket 不同，SSE 是&lt;strong&gt;单向&lt;/strong&gt;的（服务端 → 客户端），但也因此更加轻量。&lt;/p&gt;
&lt;div class="mermaid"&gt;
sequenceDiagram
participant Browser as 浏览器 EventSource
participant Server as 服务端
Browser-&gt;&gt;Server: GET /stream (Accept: text/event-stream)
Server--&gt;&gt;Browser: 200 OK (Content-Type: text/event-stream)
Note over Server: 连接保持打开
Server--)Browser: data: {"msg": "hello"}\n\n
Server--)Browser: data: {"msg": "update"}\n\n
Server--)Browser: data: {"msg": "done"}\n\n

&lt;/div&gt;

&lt;p&gt;SSE 消息格式：&lt;/p&gt;
&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;event: message
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;id: 1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;data: {&amp;#34;content&amp;#34;: &amp;#34;Hello SSE&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;retry: 3000
&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>OAuth</title><link>https://jinnchang.github.io/posts/oauth/</link><pubDate>Sun, 01 Mar 2026 17:15:00 +0800</pubDate><guid>https://jinnchang.github.io/posts/oauth/</guid><description>&lt;p&gt;OAuth 2.0 是目前最主流的授权框架，允许第三方应用在无需获取用户密码的前提下，安全地访问受保护的资源。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;假设读者具备基础的 HTTP 和 Web 开发经验。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="核心概念"&gt;
 核心概念
 &lt;a class="heading-link" href="#%e6%a0%b8%e5%bf%83%e6%a6%82%e5%bf%b5"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="四个角色"&gt;
 四个角色
 &lt;a class="heading-link" href="#%e5%9b%9b%e4%b8%aa%e8%a7%92%e8%89%b2"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h3&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;角色&lt;/th&gt;
 &lt;th&gt;说明&lt;/th&gt;
 &lt;th&gt;示例&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;Resource Owner&lt;/td&gt;
 &lt;td&gt;资源所有者（用户）&lt;/td&gt;
 &lt;td&gt;登录 Google 的张三&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Client&lt;/td&gt;
 &lt;td&gt;请求资源的第三方应用&lt;/td&gt;
 &lt;td&gt;&amp;ldquo;用 Google 登录&amp;rdquo; 的博客网站&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Authorization Server&lt;/td&gt;
 &lt;td&gt;授权服务器，验证用户并发放 Token&lt;/td&gt;
 &lt;td&gt;accounts.google.com&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Resource Server&lt;/td&gt;
 &lt;td&gt;资源服务器，存放受保护资源&lt;/td&gt;
 &lt;td&gt;Google Contacts API&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="授权流程概览"&gt;
 授权流程概览
 &lt;a class="heading-link" href="#%e6%8e%88%e6%9d%83%e6%b5%81%e7%a8%8b%e6%a6%82%e8%a7%88"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h3&gt;
&lt;div class="mermaid"&gt;
sequenceDiagram
participant U as 用户
participant C as 第三方应用
participant AS as 授权服务器
participant RS as 资源服务器

U-&gt;&gt;C: 1. 点击"授权登录"
C-&gt;&gt;AS: 2. 跳转至授权页
AS-&gt;&gt;U: 3. 用户登录并确认授权
U-&gt;&gt;C: 4. 返回授权码 (code)
C-&gt;&gt;AS: 5. 用 code 换取 access_token
AS-&gt;&gt;C: 6. 返回 access_token
C-&gt;&gt;RS: 7. 携带 token 请求资源
RS-&gt;&gt;C: 8. 返回受保护资源


&lt;/div&gt;

&lt;h3 id="为什么不用密码直连"&gt;
 为什么不用密码直连？
 &lt;a class="heading-link" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%b8%8d%e7%94%a8%e5%af%86%e7%a0%81%e7%9b%b4%e8%bf%9e"&gt;
 &lt;i class="fa-solid fa-link" aria-hidden="true" title="Link to heading"&gt;&lt;/i&gt;
 &lt;span class="sr-only"&gt;Link to heading&lt;/span&gt;
 &lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;传统方式：第三方应用直接索要用户名和密码 → 密码泄露风险、无法精细化控制权限、用户无法单独撤销第三方访问。&lt;/p&gt;</description></item></channel></rss>