<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>潘锦的空间 &#187; 架构</title>
	<atom:link href="https://www.phppan.com/tag/%e6%9e%b6%e6%9e%84/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.phppan.com</link>
	<description>SaaS SaaS架构 团队管理 技术管理 技术架构 PHP 内核 扩展 项目管理</description>
	<lastBuildDate>Sat, 25 Apr 2026 00:56:17 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.9.40</generator>
	<item>
		<title>多 Agent 架构上下文传递的 4 种策略</title>
		<link>https://www.phppan.com/2026/03/four-strategies-for-context-passing-in-a-multi-agent-architecture/</link>
		<comments>https://www.phppan.com/2026/03/four-strategies-for-context-passing-in-a-multi-agent-architecture/#comments</comments>
		<pubDate>Sat, 07 Mar 2026 02:18:10 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[multi-agent architecture]]></category>
		<category><![CDATA[上下文]]></category>
		<category><![CDATA[上下文管理]]></category>
		<category><![CDATA[多 Agent]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">https://www.phppan.com/?p=2474</guid>
		<description><![CDATA[在多 Agent 系统里，上下文怎么传，决定了系统的稳定性上限、成本下限、以及排障时的血压。 最开始，很多团队 [&#8230;]]]></description>
				<content:encoded><![CDATA[<section id="nice" data-tool="mdnice编辑器" data-website="https://www.mdnice.com">
<p data-tool="mdnice编辑器">在多 Agent 系统里，上下文怎么传，决定了系统的稳定性上限、成本下限、以及排障时的血压。</p>
<p data-tool="mdnice编辑器">最开始，很多团队把它当成「把聊天记录拼一拼」的问题。上线后就会这样的问题：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>同样的输入，输出飘得离谱。这里的问题是上下文污染和信息密度不稳定。</section>
</li>
<li>
<section>Token 成本控不住。明明一个任务只需要 10 句关键信息，每次都喂 200 句。</section>
</li>
<li>
<section>自动化评测很难做。回归集跑出来波动大到没法设阈值，最后只能靠人工验收。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">从工程的角度简单定义一下「上下文传递」：<strong>在一条多步协作链路里，把下游完成任务所需的信息，以可控成本、可追踪方式送到它面前</strong>。这里面有两个关键词：<strong>可控</strong>、<strong>可追踪</strong>。</p>
<p data-tool="mdnice编辑器">下面聊下我理解的 4 种主流策略拆解：原理、适用场景、落地细节、坑、性能和效果的取舍。</p>
<h1 data-tool="mdnice编辑器"><span class="content">先定义一下上下文</span></h1>
<p data-tool="mdnice编辑器">很多争论的根源是大家说的「上下文」不是一个东西。可以在团队里先把上下文分层，后面所有策略都能对齐。这里我们把「上下文」拆成 4 类：</p>
<ol data-tool="mdnice编辑器">
<li>
<section><strong>任务上下文</strong>：当前这一步要干什么，验收标准是什么。</section>
</li>
<li>
<section><strong>状态上下文</strong>：链路运行到哪了，已经产生了哪些中间产物。</section>
</li>
<li>
<section><strong>记忆上下文</strong>：用户偏好、历史约束、长期设定，和当前任务不完全同一层级。</section>
</li>
<li>
<section><strong>证据上下文</strong>：引用了哪些原始材料（文档片段、对话原句、文件、数据库记录），用于追溯和评测。</section>
</li>
</ol>
<h1 data-tool="mdnice编辑器"><span class="content">策略 1：共享状态或黑板模式</span></h1>
<p data-tool="mdnice编辑器">这套是 LangGraph、CrewAI 这类框架最常见的默认选项。工程上它像一个「全局状态对象」，也像一个「写满便签的白板」。</p>
<h2 data-tool="mdnice编辑器"><span class="content">机制</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section>所有 Agent 对同一个 State 读写。</section>
</li>
<li>
<section>Agent A 产出结果写入 State 的某个字段。</section>
</li>
<li>
<section>Agent B 读取字段，继续处理，再写回。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">如果我们不想把大对象放内存，也可以用文件系统或对象存储做「外置状态」，State 里只放路径和元信息。像 Manus 文章中说的「将文件系统作为存储，直接共享文件系统的路径，渐进式披露」，就是这么个逻辑：<strong>把大内容放外面，把指针放 State 里</strong>。</p>
<h2 data-tool="mdnice编辑器"><span class="content">什么时候用</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section><strong>复杂图流转</strong>：有回路、有分支、有重试、有人工介入的链路。</section>
</li>
<li>
<section><strong>任务跨度长</strong>：要做断点续跑、要保留每一步证据，方便回放和审计。</section>
</li>
<li>
<section><strong>需要可视化排障</strong>：一个状态树摆在那，定位问题快很多。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这类场景里，黑板是省心的。我们不用操心「A 怎么把消息发给 B」，大家都围着同一块板子写字。</p>
<h2 data-tool="mdnice编辑器"><span class="content">落地时的坑</span></h2>
<h3 data-tool="mdnice编辑器"><span class="content">坑 1：状态对象会长成「垃圾堆」</span></h3>
<p data-tool="mdnice编辑器">共享状态天然会诱导人偷懒：什么都往里塞。结果一周后 State 变成一个混杂体：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>当前任务指令</section>
</li>
<li>
<section>全量聊天记录</section>
</li>
<li>
<section>RAG 检索结果</section>
</li>
<li>
<section>中间产物全文</section>
</li>
<li>
<section>模型输出草稿</section>
</li>
</ul>
<p data-tool="mdnice编辑器">后果是下游 Agent 读到的信息密度越来越低，注意力越来越散。我们会直观感受到「同一个 Agent，越跑越不稳定」。</p>
<p data-tool="mdnice编辑器">共享状态可以用，前提是要给 State 立规矩。规矩不是写在 Confluence 上那种，是写进代码和评测里那种。</p>
<p data-tool="mdnice编辑器">常用的做法是给 State 分区，至少三块：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>「control」：流程控制字段（步数、路由、重试次数）</section>
</li>
<li>
<section>「artifacts」：产物指针（文件路径、对象存储 key、哈希）</section>
</li>
<li>
<section>「capsules」：给 LLM 的上下文胶囊（后面会讲）</section>
</li>
</ul>
<p data-tool="mdnice编辑器">State 里尽量少放大段文本，放「引用」和「摘要」。</p>
<h3 data-tool="mdnice编辑器"><span class="content">坑 2：并发写</span></h3>
<p data-tool="mdnice编辑器">多 Agent 并行时很容易出现：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>两个 Agent 同时更新同一字段，后写覆盖前写。</section>
</li>
<li>
<section>一个 Agent 基于旧 State 做决策，写回时把别人新写入的字段抹掉。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">解决思路按分布式系统处理：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>字段级别乐观锁（版本号 / compare-and-swap）</section>
</li>
<li>
<section>append-only 日志字段，避免覆盖（把「更新」变成「追加事件」），Gemini Cli 就是这个逻辑</section>
</li>
<li>
<section>把「写入」限定为少数字段，其他字段只读</section>
</li>
</ul>
<h3 data-tool="mdnice编辑器"><span class="content">坑 3：评测没法做「输入对齐」</span></h3>
<p data-tool="mdnice编辑器">共享状态经常带来一个隐性问题：每次运行 State 的非关键字段变化很大，导致没法保证下游 Agent 的输入一致。回归测试时同一条用例，今天多了两段日志，明天多了一个草稿，指标就会飘。</p>
<p data-tool="mdnice编辑器">建议：<strong>评测时固定「胶囊输入」</strong>，State 可以变，但进入 LLM 的那段上下文要可快照、可对比、可复现。</p>
<h2 data-tool="mdnice编辑器"><span class="content">成本 vs 效果的取舍</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section><strong>效果</strong>：流程可扩展，复杂图最好用。</section>
</li>
<li>
<section><strong>成本</strong>：需要治理 State 的 schema、并发、版本、清理策略。</section>
</li>
<li>
<section><strong>性能</strong>：状态越大，序列化 / 反序列化越痛；如果每一步都把 State 发给 LLM，更是直接烧钱。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">共享状态是一把大锤。能砸钉子，也能把玻璃砸碎。关键看有没有「状态卫生」这件事。</p>
<h1 data-tool="mdnice编辑器"><span class="content">策略 2：消息传递与直接调用</span></h1>
<p data-tool="mdnice编辑器">这套有点像微服务架构：上游把消息打包发给下游，下游处理完再回一个结果。</p>
<h2 data-tool="mdnice编辑器"><span class="content">机制</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section>Agent A 产出一个「消息」发给 Agent B。</section>
</li>
<li>
<section>消息可以走 HTTP、RPC、队列，也可以是框架内的函数调用。</section>
</li>
<li>
<section>每条消息都应该有明确的结构和版本。</section>
</li>
</ul>
<h2 data-tool="mdnice编辑器"><span class="content">什么时候用</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section><strong>流水线式任务</strong>：每一步都很明确，上游输出就是下游输入。</section>
</li>
<li>
<section><strong>要强可观测性</strong>：链路追踪、审计、回放都好做。</section>
</li>
<li>
<section><strong>团队边界清晰</strong>：不同组负责不同 Agent，接口契约能拉齐。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这类场景用消息传递灵活性更强一些，但是如果规模不大，直接单体应用来搞，函数间调用吧。</p>
<h2 data-tool="mdnice编辑器"><span class="content">落地时的坑</span></h2>
<h3 data-tool="mdnice编辑器"><span class="content">坑 1：消息里塞进「全量上下文」</span></h3>
<p data-tool="mdnice编辑器">很多团队为了省事，会把上游拿到的所有东西都塞进消息里。看起来省了裁剪逻辑，实际上把问题推给了下游：下游 LLM 要在一堆噪声里找信号。</p>
<p data-tool="mdnice编辑器">如果走消息传递，<strong>消息必须有「字段语义」</strong>。比如：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>「task」字段是当前要做的事</section>
</li>
<li>
<section>「constraints」字段是硬性限制</section>
</li>
<li>
<section>「evidence」字段是引用（原文片段或路径）</section>
</li>
<li>
<section>「history」字段如果存在，必须明确是「最近 N 轮且强相关」</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这里的关键词是「必须明确」。否则会出现消息看着结构化，内容依然是散装的。</p>
<h3 data-tool="mdnice编辑器"><span class="content">坑 2：接口版本失控</span></h3>
<p data-tool="mdnice编辑器">多 Agent 系统迭代快，接口字段会频繁变动。如果经历过一次「某个 Agent 升级后，下游全挂」就会理解版本的重要性。</p>
<p data-tool="mdnice编辑器">建议至少做到：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>每条消息带「schema_version」</section>
</li>
<li>
<section>下游支持 1~2 个旧版本的兼容解析</section>
</li>
<li>
<section>重要字段改动要有灰度期，别全量切</section>
</li>
</ul>
<p data-tool="mdnice编辑器">Agent 世界里「prompt 和策略」变化太快，不做版本控制就是赌博。</p>
<h3 data-tool="mdnice编辑器"><span class="content">坑 3：把「LLM 输出」当成接口返回</span></h3>
<p data-tool="mdnice编辑器">LLM 输出天然存在幻觉。如果我们直接把自由文本当成 RPC 返回，然后让下游再去解析，事故率会非常高。</p>
<p data-tool="mdnice编辑器">有一个简单的方法：<strong>固定栏位的轻量输出格式</strong>，别一上来就上复杂 schema，也别放任自由发挥。它在工程上有一个很大的价值：解析稳定，回归测试有抓手。</p>
<p data-tool="mdnice编辑器">类似于这样：</p>
<pre class="custom" data-tool="mdnice编辑器"><code class="hljs">PROMPT:
...

NEGATIVE:
...

PARAMS:
- aspect: 16:9
- notes: ...
</code></pre>
<h2 data-tool="mdnice编辑器"><span class="content">成本 vs 效果的取舍</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section><strong>效果</strong>：可追踪性强，调试体验好。</section>
</li>
<li>
<section><strong>成本</strong>：要做接口契约、版本管理、兼容逻辑。</section>
</li>
<li>
<section><strong>性能</strong>：网络开销和序列化开销可控；真正的成本往往来自传了多少无用字段。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">如果业务链路更像「微服务编排」，消息传递会比共享状态更干净。</p>
<h1 data-tool="mdnice编辑器"><span class="content">策略 3：上下文压缩与自然语言传递</span></h1>
<p data-tool="mdnice编辑器">核心思路：<strong>下游 Agent 不该负责考古</strong>。</p>
<p data-tool="mdnice编辑器">把「长历史」变成「短胶囊」，把「噪声」变成「任务卡」，再交给执行 Agent。</p>
<h2 data-tool="mdnice编辑器"><span class="content">机制</span></h2>
<p data-tool="mdnice编辑器">上游做三件事：</p>
<ol data-tool="mdnice编辑器">
<li>
<section>从历史里抽取和当前任务强相关的信息</section>
</li>
<li>
<section>把冲突的约束做决策或提出澄清问题</section>
</li>
<li>
<section>输出一个高密度、可控的自然语言指令</section>
</li>
</ol>
<h2 data-tool="mdnice编辑器"><span class="content">「上下文胶囊（context capsule）」</span></h2>
<p data-tool="mdnice编辑器">把给下游 Agent 的输入，固定成一个胶囊，结构大概是：</p>
<ul data-tool="mdnice编辑器">
<li>
<section><strong>必须给</strong>：任务卡（Planner 压缩/改写后的自然语言描述）</section>
</li>
<li>
<section><strong>可选给</strong>（按需）：</p>
<ul>
<li>
<section>最近 N 轮「与任务强相关」的对话原句（最多 3–8 句）</section>
</li>
<li>
<section>一段「用户偏好/风格记忆」摘要（1–3 句）</section>
</li>
</ul>
</section>
</li>
<li>
<section><strong>坚决不直接给</strong>：全量聊天记录（除非做的就是风格延续式创作，而且做了脱敏）</section>
</li>
</ul>
<p data-tool="mdnice编辑器">它解决的是「你能不能控制它理解什么」。</p>
<p data-tool="mdnice编辑器">示例：</p>
<blockquote class="custom-blockquote multiquote-1" data-tool="mdnice编辑器"><p><strong>任务卡</strong>：生成一张用于电商 banner 的图。主体是一只穿宇航服的柯基站在月球上，远处能看到地球。风格写实摄影，冷色调，高对比，电影感侧逆光。横向 16:9。不要任何文字、logo、血腥或恐怖元素。用户偏好极简、冷色、不要文字。若信息缺失请提 1–3 个澄清问题，否则直接输出可用于生图的 prompt 与 negative prompt。</p></blockquote>
<p data-tool="mdnice编辑器">这段话有几个关键点：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>主体、场景、风格、画幅、禁忌、用户偏好都在</section>
</li>
<li>
<section>有「缺失信息时的行为规则」</section>
</li>
<li>
<section>不需要表单，依然可评测、可回归</section>
</li>
</ul>
<h2 data-tool="mdnice编辑器"><span class="content">工具描述要写成「契约」</span></h2>
<p data-tool="mdnice编辑器">工具描述很重要。</p>
<p data-tool="mdnice编辑器">我更喜欢把工具说明写成「契约」，至少包含：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>工具支持的参数（prompt / negative / size / seed / style 等）</section>
</li>
<li>
<section>哪些信息必须出现（画幅、用途、限制）</section>
</li>
<li>
<section>输出必须遵守的格式（哪怕只有 PROMPT/NEGATIVE/PARAMS）</section>
</li>
</ul>
<h2 data-tool="mdnice编辑器"><span class="content">可能翻车的地方</span></h2>
<p data-tool="mdnice编辑器">以一个增强提示词的 Agent 为例</p>
<h3 data-tool="mdnice编辑器"><span class="content">翻车 1：指代延续没被写进任务卡</span></h3>
<p data-tool="mdnice编辑器">用户说「按刚才那张风格」「把她换成红裙子」，Planner 如果没有把「刚才那张」总结成可引用的描述，下游增强 Agent 根本无从得知。</p>
<p data-tool="mdnice编辑器">补救方式使用「证据上下文」：把关键原句作为 1~3 条引用附在胶囊里。</p>
<h3 data-tool="mdnice编辑器"><span class="content">翻车 2：约束冲突没被处理</span></h3>
<p data-tool="mdnice编辑器">用户一会儿要极简纯色，一会儿又要复杂赛博城市场景。Agent 去解决冲突会很糟糕，因为它的职责是「增强表达」，不是「做产品决策」。</p>
<p data-tool="mdnice编辑器">冲突要在 Planner 层解决：要么做裁决（按最新指令为准、按用户偏好为准），要么问澄清问题。别把锅甩给执行 Agent。</p>
<h3 data-tool="mdnice编辑器"><span class="content">翻车 3：压缩带来的信息损失</span></h3>
<p data-tool="mdnice编辑器"><strong>上下文压缩是有损的。</strong> 压缩做得越狠，成本越低，翻车概率越高；压缩做得越松，成本越高，稳定性也未必更好，因为噪声会上来。</p>
<p data-tool="mdnice编辑器">建议做一个「胶囊长度预算」，按任务类型分档：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>低风险任务（格式化、简单问答）：胶囊可以短到 200~400 tokens</section>
</li>
<li>
<section>中风险任务（生成、改写、推理）：600~1200 tokens</section>
</li>
<li>
<section>高风险任务（工具调用、多约束、多回合创作）：1200~2000 tokens，再往上就该考虑别的策略了</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这样，可以让成本和稳定性可控一些。</p>
<h2 data-tool="mdnice编辑器"><span class="content">成本 vs 效果的取舍</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section><strong>效果</strong>：稳定性提升非常明显，Token 成本能压下来，评测也更容易做。</section>
</li>
<li>
<section><strong>成本</strong>：要多一个 Planner/Summarizer 步骤，链路延迟会上升；压缩质量要靠回归集打磨。</section>
</li>
<li>
<section><strong>工程判断</strong>：这套是「多 Agent 真正开始像工程系统」的起点。</section>
</li>
</ul>
<h1 data-tool="mdnice编辑器"><span class="content">策略 4：路由分发与层级管理</span></h1>
<p data-tool="mdnice编辑器">如果说策略 3 解决的是「给下游喂什么」，策略 4 解决的是「谁有资格看到什么」。</p>
<p data-tool="mdnice编辑器">我喜欢用「最小信息原则」去设计多 Agent：每个 Agent 只拿自己需要的那一部分上下文，别让它看到不该看的东西。</p>
<h2 data-tool="mdnice编辑器"><span class="content">机制</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section>一个 Supervisor（主管）拿到全量上下文。</section>
</li>
<li>
<section>Supervisor 拆任务、选 Agent、裁剪上下文。</section>
</li>
<li>
<section>子 Agent 只看到被裁剪后的输入，产出结果回传 Supervisor。</section>
</li>
<li>
<section>Supervisor 汇总，决定下一步。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">把「路由」和「信息裁剪」集中起来做，能显著减少上下游互相污染。</p>
<p data-tool="mdnice编辑器">这本质就是一个主从的逻辑。</p>
<h2 data-tool="mdnice编辑器"><span class="content">什么时候用</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section><strong>权限和合规敏感</strong>：有 PII、有商业机密、有分级数据。</section>
</li>
<li>
<section><strong>子 Agent 职责清晰</strong>：比如「检索」「评审」「生成」「合规检查」。</section>
</li>
<li>
<section><strong>系统要长期维护</strong>：人员流动、策略变动、模型替换都很频繁。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">层级路由把复杂性收敛到 Supervisor 这一点上。依赖它，也更容易把它做好。</p>
<h2 data-tool="mdnice编辑器"><span class="content">落地时的坑</span></h2>
<h3 data-tool="mdnice编辑器"><span class="content">坑 1：Supervisor 变成性能瓶颈</span></h3>
<p data-tool="mdnice编辑器">所有东西都过 Supervisor，它会成为热点：吞吐、延迟、可用性全压在它身上。</p>
<p data-tool="mdnice编辑器">解决办法通常有三种：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>Supervisor 只做「路由与裁剪」，不要在它身上做重推理</section>
</li>
<li>
<section>对路由做缓存（同一类任务走同一条路径）</section>
</li>
<li>
<section>Supervisor 逻辑尽量确定性，LLM 参与度降低</section>
</li>
</ul>
<p data-tool="mdnice编辑器">我见过很多团队把「大脑」写成一个超级 prompt，然后让它既拆任务又生成内容又做审查。这样迟早会蹦。</p>
<h3 data-tool="mdnice编辑器"><span class="content">坑 2：裁剪策略一开始过度依赖「拍脑袋」</span></h3>
<p data-tool="mdnice编辑器">裁剪不是凭感觉。裁剪是一套数据工程问题：哪些字段必须给，哪些字段给了会干扰。</p>
<p data-tool="mdnice编辑器">用「失败用例驱动」去迭代裁剪：每次线上翻车，都回放当时给子 Agent 的胶囊，问一个很残酷的问题：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>该给的没给，是哪一类信息缺失？</section>
</li>
<li>
<section>不该给的给了，是哪一类噪声触发了跑偏？</section>
</li>
</ul>
<p data-tool="mdnice编辑器">把这两类问题沉淀成裁剪规则，会越做越稳。</p>
<h3 data-tool="mdnice编辑器"><span class="content">坑 3：子 Agent 之间产生「隐性耦合」</span></h3>
<p data-tool="mdnice编辑器">很多系统表面上是层级的，实际上子 Agent 会通过共享外部资源互相影响，比如：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>共用同一个向量库检索空间，检索结果被不同策略污染</section>
</li>
<li>
<section>共用同一个临时文件目录，路径命名冲突</section>
</li>
<li>
<section>共用同一个「用户偏好记忆」，写入时缺少版本控制</section>
</li>
</ul>
<p data-tool="mdnice编辑器">如果走 Supervisor 模式，「写入边界」会比较重要：哪些 Agent 允许写记忆，哪些只能读；写入要不要审批；写入是否带证据引用。</p>
<h2 data-tool="mdnice编辑器"><span class="content">成本 vs 效果的取舍</span></h2>
<ul data-tool="mdnice编辑器">
<li>
<section><strong>效果</strong>：稳定性和安全性非常强，复杂系统更容易控住。</section>
</li>
<li>
<section><strong>成本</strong>：Supervisor 设计难度高，容易成为瓶颈；需要更完善的可观测性和回放能力。</section>
</li>
<li>
<section><strong>工程判断</strong>：当开始被「数据泄露」「上下文污染」「责任边界不清」折磨时，Supervisor 往往是解药。</section>
</li>
</ul>
<h1 data-tool="mdnice编辑器"><span class="content">选择策略时，如何判断</span></h1>
<p data-tool="mdnice编辑器">可以用四个可执行的问题来选方案：</p>
<ol data-tool="mdnice编辑器">
<li>
<section><strong>谁需要看到全量上下文？谁只需要胶囊？</strong><br />
如果答案是「大多数都只需要胶囊」，策略 3 和 4 优先级会上来。</p>
</section>
</li>
<li>
<section><strong>要不要并发？要不要异步？</strong><br />
需要并发、异步，策略 5 的价值会非常直接。</p>
</section>
</li>
<li>
<section><strong>失败主要来自哪里：信息缺失，还是噪声过多？</strong><br />
信息缺失优先补证据引用；噪声过多优先做裁剪和胶囊预算。</p>
</section>
</li>
<li>
<section><strong>是否真的在做回归评测？</strong><br />
没有回归，就别指望系统会「越调越稳」。上下文传递策略的好坏，最终都要落在可复现输入上。</p>
</section>
</li>
</ol>
<h1 data-tool="mdnice编辑器"><span class="content">小结</span></h1>
<p data-tool="mdnice编辑器"><strong>不做结构化，并不等于不做「约束与契约」</strong>。</p>
<p data-tool="mdnice编辑器">我见过的高质量落地项目，往往走的是「看起来很自然，实际上约束很硬」的路线。用户体验上像聊天，工程实现上像协议。</p>
<p data-tool="mdnice编辑器">如果准备做多 Agent 的上下文传递，至少把三件事落下来：</p>
<ul data-tool="mdnice编辑器">
<li>
<section>「上下文胶囊」：任务卡 + 少量强相关原句 + 记忆摘要</section>
</li>
<li>
<section>「工具契约」：写清楚工具能力边界和必填信息</section>
</li>
<li>
<section>「受控输出格式」：固定栏位，解析稳定，评测可做</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这三件事做完，再谈共享状态、Supervisor、消息传递，才有意义。</p>
<p data-tool="mdnice编辑器">以上。</p>
</section>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2026/03/four-strategies-for-context-passing-in-a-multi-agent-architecture/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AI Agent 架构常用的 4 种设计模式</title>
		<link>https://www.phppan.com/2025/10/4-common-design-patterns-for-ai-agent-architecture/</link>
		<comments>https://www.phppan.com/2025/10/4-common-design-patterns-for-ai-agent-architecture/#comments</comments>
		<pubDate>Sun, 19 Oct 2025 00:36:19 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[AIAgent]]></category>
		<category><![CDATA[AIAgent架构]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">https://www.phppan.com/?p=2423</guid>
		<description><![CDATA[AI Agent 持续火爆，不仅仅是产品上，在融资市场也同样火爆，各种产品都在往上靠。但对于 AI Agent [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="color: #191b1f;" data-first-child="" data-pid="_lA29klx">AI Agent 持续火爆，不仅仅是产品上，在融资市场也同样火爆，各种产品都在往上靠。但对于 AI Agent 该如何架构，有人关注，但少有人刻意去了解和分析。一些常见的问题有：如单个 Agent 搞不定复杂任务，多个 Agent 又容易失控，成本高，在不同的场景应该使用什么样的架构等等。</p>
<p style="color: #191b1f;" data-pid="aeh8yY5j">这篇文章我会尝试分享一下 AI Agent 的 4 个常用设计模式。</p>
<h2 style="font-weight: 500; color: #191b1f;">1. 什么是 Agent 设计模式</h2>
<p style="color: #191b1f;" data-pid="xsB7qpYY">设计模式这个概念最早来自建筑行业，后来被软件工程借鉴过来。Christopher Alexander 在《建筑的永恒之道》里说，每个模式都是一个三元组：在特定的上下文中，解决特定的问题，采用特定的方案。</p>
<p style="color: #191b1f;" data-pid="APTa_4nM">放到 AI Agent 领域，设计模式就是构建智能体系统的常见架构方法。每种模式都提供了一个组织系统组件、集成模型、编排单个或多个 Agent 来完成工作流的框架。</p>
<p style="color: #191b1f;" data-pid="ga-eGfqz">为什么需要设计模式？因为 Agent 系统的复杂性在于它需要自主决策、动态规划、处理不确定性。我们需要有特定场景下的特定解决方案，不过于复杂，也不过于简单，刚刚好。</p>
<p style="color: #191b1f;" data-pid="0PhEL_C9">选择设计模式前，需要考虑几个关键因素：任务复杂度、响应时间要求、成本预算、是否需要人工参与。想清楚这些，才能选对模式。</p>
<h2 style="font-weight: 500; color: #191b1f;">2. 单 Agent 模式</h2>
<h2 style="font-weight: 500; color: #191b1f;">2.1 模式定义</h2>
<p style="color: #191b1f;" data-pid="xQcNNn-0">单 Agent 模式是最基础的设计模式。整个系统只有一个 Agent，通过一个 AI 模型、一组预定义的工具、一个精心设计的系统提示词来完成任务。</p>
<p style="color: #191b1f;" data-pid="r9v7WMFg">这也是我们实际工作中常用的设计模式。</p>
<p style="color: #191b1f;" data-pid="0G6phGlp">Agent 依赖模型的推理能力来理解用户请求、规划执行步骤、选择合适的工具。</p>
<p style="color: #191b1f;" data-pid="x7EnQkW2">这个模式的架构很简单：</p>
<p style="color: #191b1f;" data-pid="krihuKlV">用户输入 → Agent（模型+工具+提示词） → 输出结果</p>
<p style="color: #191b1f;" data-pid="TqZPYe9d">所有的决策和执行都在一个 Agent 内完成。</p>
<h2 style="font-weight: 500; color: #191b1f;">2.2 解决的问题</h2>
<p style="color: #191b1f;" data-pid="vOCTZ5df">单 Agent 模式主要解决的是需要多步骤处理但逻辑相对清晰的任务。比如：</p>
<ul style="color: #191b1f;">
<li data-pid="DOn1peUe">需要调用多个 API 获取信息然后综合</li>
<li data-pid="x4P3KXjI">需要访问数据库查询后给出答案</li>
<li data-pid="E8y0gOhX">需要执行一系列操作来完成用户请求</li>
</ul>
<p style="color: #191b1f;" data-pid="ptzNz3Un">这些任务用传统的非 Agent 系统也能做，但整个逻辑非常固化，都是规则，而使用了 Agent 后，它能动态决策，自行做工具调用。</p>
<h2 style="font-weight: 500; color: #191b1f;">2.3 核心组件</h2>
<p style="color: #191b1f;" data-pid="ktWirYrn">AI 模型：这是 Agent 的大脑，负责理解、推理和决策。模型的能力直接决定了 Agent 的上限。选择模型时要平衡能力和成本，不是所有任务都需要用最强的模型。</p>
<p style="color: #191b1f;" data-pid="HKdu6OWL">工具集：Agent 能调用的外部功能，比如搜索引擎、数据库、API、计算器等。工具定义要清晰，包括什么时候用、怎么用、预期结果是什么。工具太多会增加选择难度，太少又限制能力。</p>
<p style="color: #191b1f;" data-pid="hML4VNj6">系统提示词：定义 Agent 的角色、任务、行为规范。好的提示词能较大幅提升 Agent 的表现。要明确告诉 Agent 它是谁、要做什么、有哪些限制、如何处理异常情况。</p>
<p style="color: #191b1f;" data-pid="2FOmmpZi">记忆系统：虽然不是必需的，但记忆系统能让 Agent 保持上下文，避免重复操作。可以是简单的对话历史，也可以是复杂的向量数据库。</p>
<h2 style="font-weight: 500; color: #191b1f;">2.4 工作流程</h2>
<ol style="color: #191b1f;">
<li data-pid="Yy900fSV">接收请求：Agent 接收用户的输入，可能是文本、语音或其他格式</li>
<li data-pid="I-bzkEwA">理解意图：通过模型分析用户想要什么，需要哪些信息</li>
<li data-pid="jcxlexbr">制定计划：决定需要执行哪些步骤，调用哪些工具</li>
<li data-pid="Ir2A6LxL">执行操作：按计划调用工具，获取必要信息</li>
<li data-pid="kZnwBViq">综合结果：把各种信息整合成最终答案</li>
<li data-pid="YgFuCpS4">返回响应：将结果返回给用户</li>
</ol>
<p style="color: #191b1f;" data-pid="4amgy1sm">整个过程是线性的，但 Agent 可以根据中间结果调整计划。</p>
<h2 style="font-weight: 500; color: #191b1f;">2.5 应用场景</h2>
<p style="color: #191b1f;" data-pid="gGvxaiIH">客服助手：处理常见的客户询问，比如查订单、改地址、退换货。Agent 可以访问订单系统、物流系统、用户数据库，一站式解决客户问题。</p>
<p style="color: #191b1f;" data-pid="1AGXSWCL">研究助手：帮助用户收集和总结信息。比如搜索特定主题的最新进展，整理成报告。Agent 可以调用搜索 API、访问学术数据库、生成摘要。</p>
<p style="color: #191b1f;" data-pid="cmrhGq7R">个人助理：管理日程、发邮件、设置提醒。Agent 可以访问日历、邮箱、任务管理工具，帮用户处理日常事务。</p>
<h2 style="font-weight: 500; color: #191b1f;">2.6 优势与局限</h2>
<p style="color: #191b1f;" data-pid="8WIppWlh">优势：</p>
<ul style="color: #191b1f;">
<li data-pid="r2lk87IO">架构简单，容易实现和维护</li>
<li data-pid="N2X9oQLx">成本可控，只需要调用一个模型</li>
<li data-pid="4Bw0ObQO">响应速度快，没有多 Agent 协调的开销</li>
<li data-pid="JM9-8y_F">调试方便，所有逻辑在一个地方</li>
</ul>
<p style="color: #191b1f;" data-pid="tYeCTZEN">局限：</p>
<ul style="color: #191b1f;">
<li data-pid="QL373JKh">处理复杂任务能力有限</li>
<li data-pid="qnULdE_m">工具太多时容易混乱</li>
<li data-pid="9t1ybLXo">单点故障，Agent 出问题整个系统就挂了</li>
<li data-pid="D0f42DxD">难以并行处理多个子任务</li>
</ul>
<h2 style="font-weight: 500; color: #191b1f;">2.7 实施建议</h2>
<p style="color: #191b1f;" data-pid="JZ-4uJkP">从简单开始：先实现核心功能，确保基本流程跑通，再逐步添加工具和能力。</p>
<p style="color: #191b1f;" data-pid="crJDl7Wt">工具要精不要多：与其给 Agent 20 个工具，不如精选 5-8 个最常用的。每个工具的使用场景要明确。</p>
<p style="color: #191b1f;" data-pid="OwGwumIC">提示词要迭代优化：没有一次就完美的提示词。要根据实际使用情况不断调整，特别是边界情况的处理。</p>
<p style="color: #191b1f;" data-pid="b84iR4KU">加入失败处理：工具调用可能失败，模型推理可能出错。要有明确的错误处理机制，比如重试、降级、转人工。</p>
<p style="color: #191b1f;" data-pid="glcID9Q7">监控关键指标：响应时间、成功率、工具调用次数、token 消耗等。这些数据是优化的基础。</p>
<h2 style="font-weight: 500; color: #191b1f;">3. ReAct 模式</h2>
<h2 style="font-weight: 500; color: #191b1f;">3.1 模式定义</h2>
<p style="color: #191b1f;" data-pid="TJVRT90F">ReAct（Reasoning and Acting）模式是一种让 Agent 交替进行推理和行动的设计模式。不同于简单的输入输出，ReAct 模式让 Agent 在一个循环中不断地思考、行动、观察，直到找到问题的答案。</p>
<p style="color: #191b1f;" data-pid="5QjK0sCu">这个模式的核心思想是把 Agent 的思维过程显式化。每一步都要说明在想什么、要做什么、观察到什么，形成一个完整的推理链条。这不仅提高了结果的可靠性，也让整个过程变得可解释。</p>
<h2 style="font-weight: 500; color: #191b1f;">3.2 解决的问题</h2>
<p style="color: #191b1f;" data-pid="5vNfc07d">ReAct 模式解决的是那些需要多步探索和动态调整策略的复杂问题：</p>
<ul style="color: #191b1f;">
<li data-pid="JOATz_m3">答案不是显而易见的，需要逐步收集信息</li>
<li data-pid="2h6Z9kOo">初始计划可能不完善，需要根据中间结果调整</li>
<li data-pid="BfsIvNqI">需要试错和迭代才能找到最优解</li>
<li data-pid="QV4GF-ix">推理过程和结果同样重要，需要可解释性</li>
</ul>
<p style="color: #191b1f;" data-pid="5Sey_qKA">传统的一次性推理经常不够用，需要 Agent 能够根据新信息不断调整自己的理解和策略。</p>
<h2 style="font-weight: 500; color: #191b1f;">3.2 核心机制</h2>
<p style="color: #191b1f;" data-pid="XQKAVOK3">Thought（思考）：Agent 分析当前状况，推理下一步该做什么。这包括理解已有信息、识别缺失信息、评估可能的行动方案。思考过程要明确表达出来，比如「我需要知道 X 才能回答 Y」。</p>
<p style="color: #191b1f;" data-pid="02ZLx3JR">Action（行动）：基于思考结果，Agent 决定采取什么行动。通常是调用某个工具获取信息，也可能是进行计算或转换。行动要具体，包括使用什么工具、传入什么参数。</p>
<p style="color: #191b1f;" data-pid="yktvJ8eu">Observation（观察）：Agent 接收行动的结果，理解新获得的信息。观察不是简单的记录，而要分析这些信息对解决问题有什么帮助，是否需要调整策略。</p>
<p style="color: #191b1f;" data-pid="vrrfgqJY">这三个步骤形成一个循环，不断重复直到找到满意的答案或达到终止条件。</p>
<h2 style="font-weight: 500; color: #191b1f;">3.3 工作流程</h2>
<div class="highlight" style="color: #191b1f;">
<pre><code class="language-text">用户输入问题
↓
初始思考：理解问题，确定需要什么信息
↓
循环开始：
  → 思考：基于当前信息，决定下一步
  → 行动：执行决定的操作
  → 观察：分析操作结果
  → 判断：是否已经可以回答问题？
     ├─ 否：继续循环
     └─ 是：退出循环
↓
综合所有信息，生成最终答案
↓
返回给用户
</code></pre>
</div>
<p style="color: #191b1f;" data-pid="8e5orTD6">每个循环都在积累信息，逐步接近答案。关键是 Agent 要能判断什么时候信息足够了。</p>
<h2 style="font-weight: 500; color: #191b1f;">3.4 典型应用场景</h2>
<p style="color: #191b1f;" data-pid="RIKlNdM9">复杂问题求解：比如数学应用题，需要分步骤求解。Agent 先理解问题，识别已知和未知，然后逐步计算中间结果，最后得出答案。每一步都要验证是否合理。</p>
<p style="color: #191b1f;" data-pid="gJMcW3sb">信息检索与验证：用户问一个需要多方印证的问题。Agent 从不同来源收集信息，交叉验证，排除矛盾，最终给出可靠的答案。比如&#8221;某个历史事件的真实经过&#8221;。</p>
<p style="color: #191b1f;" data-pid="B_JyxFMr">调试和故障排查：系统出问题了，Agent 需要逐步检查各个组件，收集日志，测试假设，最终定位问题原因。这个过程充满了试错和调整。</p>
<p style="color: #191b1f;" data-pid="twMnZfuf">研究和分析：对某个主题进行深入研究。Agent 先了解背景，然后深入特定方面，发现新的线索后调整研究方向，最终形成完整的分析报告。</p>
<h2 style="font-weight: 500; color: #191b1f;">3.5 实现要点</h2>
<p style="color: #191b1f;" data-pid="2ISbjc7z">推理链的质量：ReAct 模式的效果很大程度上取决于模型的推理能力。要选择推理能力强的模型，并通过提示词引导它进行结构化思考。</p>
<p style="color: #191b1f;" data-pid="hCen7-YE">终止条件设计：必须有明确的终止条件，否则可能陷入无限循环。常见的终止条件包括：找到满意答案、达到最大迭代次数、遇到无法处理的错误、用户主动终止。可以参考我上一篇文章《AI Agent 核心策略：如何判断 Agent 应该停止》</p>
<p style="color: #191b1f;" data-pid="ed-gwuHQ">上下文管理：随着循环次数增加，上下文会越来越长。需要策略性地管理上下文，比如总结之前的发现、删除无关信息、保留关键结论。</p>
<p style="color: #191b1f;" data-pid="i4AYNs0u">错误恢复：某一步出错不应该导致整个流程失败。要有恢复机制，比如重试、换一种方法、跳过这一步等。</p>
<h2 style="font-weight: 500; color: #191b1f;">3.6 优势与挑战</h2>
<p style="color: #191b1f;" data-pid="N2AU3FRG">优势：</p>
<ul style="color: #191b1f;">
<li data-pid="UEJqVKKc">可解释性强，每一步推理都有记录</li>
<li data-pid="TpxYG8Q_">灵活性高，可以动态调整策略</li>
<li data-pid="U0uun3Jk">准确性好，通过多步验证减少错误</li>
<li data-pid="CcQE98cr">适应性强，能处理预料之外的情况</li>
</ul>
<p style="color: #191b1f;" data-pid="NuQ89jv8">挑战：</p>
<ul style="color: #191b1f;">
<li data-pid="4A7fvDnV">延迟较高，多次循环导致响应时间长</li>
<li data-pid="Vwdqgpwa">成本增加，每次循环都要调用模型</li>
<li data-pid="dQ3PObN8">可能陷入循环，在某些问题上来回打转</li>
<li data-pid="lHcD0VFp">对模型能力要求高，弱模型效果差</li>
</ul>
<h2 style="font-weight: 500; color: #191b1f;">3.7 优化策略</h2>
<p style="color: #191b1f;" data-pid="Jscpg4EW">设置合理的最大循环次数：根据任务类型和复杂度，设置合适的上限。简单任务 3-5 次，复杂任务 10-15 次。</p>
<p style="color: #191b1f;" data-pid="BxHPGAuF">缓存中间结果：相同的查询不要重复执行，工具调用的结果要缓存起来。</p>
<p style="color: #191b1f;" data-pid="hqXUCRAI">并行化某些操作：如果多个信息获取操作互不依赖，可以并行执行，减少总体时间。</p>
<p style="color: #191b1f;" data-pid="a6Ong49S">使用更轻量的模型进行初步筛选：不是每个思考步骤都需要最强的模型，可以用小模型做初筛，大模型做关键决策。</p>
<p style="color: #191b1f;" data-pid="hJEVS-WB">提供思考模板：通过提示词工程，给 Agent 提供思考的框架，提高推理效率。</p>
<h2 style="font-weight: 500; color: #191b1f;">4. 多 Agent 协作模式</h2>
<h2 style="font-weight: 500; color: #191b1f;">4.1 模式定义</h2>
<p style="color: #191b1f;" data-pid="YRPPjTS3">多 Agent 协作模式是让多个专门化的 Agent 共同完成一个复杂任务。每个 Agent 负责自己擅长的领域，通过协调器（Coordinator）或预定义的工作流来协同工作。</p>
<p style="color: #191b1f;" data-pid="npXc0I5q">这个模式的核心理念是&#8221;专业分工&#8221;。就像一个团队，每个成员都有自己的专长，通过协作可以完成单个人无法完成的任务。协调可以是中心化的（有一个协调器），也可以是去中心化的（Agent 之间直接通信）。</p>
<h2 style="font-weight: 500; color: #191b1f;">4.2 解决的问题</h2>
<p style="color: #191b1f;" data-pid="plQ5QrS_">多 Agent 协作模式解决的是单个 Agent 难以处理的复杂问题：</p>
<ul style="color: #191b1f;">
<li data-pid="rMxeIEIS">任务涉及多个专业领域，单个 Agent 难以精通所有领域</li>
<li data-pid="o5Zsc0JM">需要并行处理多个子任务以提高效率</li>
<li data-pid="7VjQPdX7">任务太复杂，单个提示词难以覆盖所有情况</li>
<li data-pid="VKxu-SBA">需要不同视角的交叉验证来提高可靠性</li>
</ul>
<p style="color: #191b1f;" data-pid="4y3-rHUq">当你发现单个 Agent 的提示词越写越长、工具越加越多、错误率开始上升时，就该考虑多 Agent 协作了。</p>
<h2 style="font-weight: 500; color: #191b1f;">4.3 架构类型</h2>
<p style="color: #191b1f;" data-pid="2EGyUp-k">顺序协作：Agent 按照预定顺序依次工作，前一个的输出是后一个的输入。像流水线一样，每个 Agent 完成特定的加工步骤。适合步骤明确、顺序固定的任务。</p>
<p style="color: #191b1f;" data-pid="JY8oiENs">并行协作：多个 Agent 同时工作，各自处理任务的不同方面，最后汇总结果。像团队分工一样，每个人负责一部分，最后整合。适合可以分解的独立子任务。</p>
<p style="color: #191b1f;" data-pid="d_3yNHDG">层级协作：Agent 组织成树状结构，上层 Agent 负责任务分解和结果汇总，下层 Agent 负责具体执行。像公司组织架构，有管理层和执行层。适合需要多级分解的复杂任务。</p>
<p style="color: #191b1f;" data-pid="6U0mJ_S2">网状协作：Agent 之间可以自由通信，没有固定的上下级关系。像专家会诊，大家平等讨论，共同决策。适合需要充分讨论和创意的任务。</p>
<h2 style="font-weight: 500; color: #191b1f;">4.4 核心组件</h2>
<p style="color: #191b1f;" data-pid="o25_giE9">专业 Agent：每个 Agent 专注于特定领域或功能。比如数据分析 Agent、文案撰写 Agent、代码生成 Agent 等。专业化让每个 Agent 的提示词更精简、更有效。</p>
<p style="color: #191b1f;" data-pid="m958tjRE">协调器 Agent：负责任务分解、Agent 调度、结果汇总。协调器需要理解整体任务，知道每个 Agent 的能力，能做出合理的分配决策。</p>
<p style="color: #191b1f;" data-pid="RhYa1L72">通信机制：Agent 之间如何传递信息。可以是直接传递（点对点），也可以通过共享内存（如消息队列、数据库）。通信协议要明确，包括数据格式、错误处理等。一般是 json 格式。</p>
<p style="color: #191b1f;" data-pid="p6-J2OSh">上下文管理：如何在 Agent 之间共享和传递上下文。不是所有信息都需要传给所有 Agent，要有选择地传递相关信息，避免信息过载。</p>
<h2 style="font-weight: 500; color: #191b1f;">4.5 典型场景</h2>
<p style="color: #191b1f;" data-pid="II_UKxWZ">内容创作流水线：</p>
<ul style="color: #191b1f;">
<li data-pid="pdzuKIte">研究 Agent：收集资料、查证事实</li>
<li data-pid="BUT94YVM">写作 Agent：撰写初稿</li>
<li data-pid="Iw7LP4FN">编辑 Agent：优化文笔、检查逻辑</li>
<li data-pid="Bg565cA5">审核 Agent：确保符合规范、没有敏感内容</li>
</ul>
<p style="color: #191b1f;" data-pid="RfvTMjZ0">每个 Agent 专注自己的环节，整体产出高质量内容。</p>
<p style="color: #191b1f;" data-pid="N1YOTgh7">客户服务系统：</p>
<ul style="color: #191b1f;">
<li data-pid="LXDmUpjz">分类 Agent：理解客户问题类型</li>
<li data-pid="Rl41q2kR">查询 Agent：从数据库获取相关信息</li>
<li data-pid="aE3eXDKp">解决方案 Agent：生成解决方案</li>
<li data-pid="8muePPJD">回复 Agent：组织友好的回复话术</li>
</ul>
<p style="color: #191b1f;" data-pid="4WOyoI3D">根据问题类型，协调器可能跳过某些 Agent 或调整流程。</p>
<p style="color: #191b1f;" data-pid="evdApwcI">代码开发助手：</p>
<ul style="color: #191b1f;">
<li data-pid="5-HxKNQf">需求分析 Agent：理解用户需求</li>
<li data-pid="OFkM_--d">架构设计 Agent：设计系统架构</li>
<li data-pid="7JElNpwi">代码生成 Agent：编写具体代码</li>
<li data-pid="mSweGQUI">测试 Agent：生成测试用例并执行</li>
<li data-pid="AnbAPV9V">文档 Agent：生成代码文档</li>
</ul>
<p style="color: #191b1f;" data-pid="DWo7lHwX">可以迭代工作，测试发现问题后返回给代码生成 Agent 修改。</p>
<p style="color: #191b1f;" data-pid="RA61HVPB">数据分析系统：</p>
<ul style="color: #191b1f;">
<li data-pid="LkpI57qD">数据收集 Agent：从各个源获取数据</li>
<li data-pid="lFIsBRUL">清洗 Agent：处理缺失值、异常值</li>
<li data-pid="_XADchjm">分析 Agent：统计分析、模式识别</li>
<li data-pid="o7RwSLq0">可视化 Agent：生成图表</li>
<li data-pid="sCi6X9Qp">报告 Agent：撰写分析报告</li>
</ul>
<p style="color: #191b1f;" data-pid="81TwGKPI">可以并行处理多个数据源，提高效率。</p>
<h2 style="font-weight: 500; color: #191b1f;">4.6 协调策略</h2>
<p style="color: #191b1f;" data-pid="9tne3zOF">中心化协调：所有决策都由协调器做出。优点是逻辑清晰、易于控制；缺点是协调器可能成为瓶颈。</p>
<p style="color: #191b1f;" data-pid="MFJrzWGi">分布式协调：Agent 之间直接协商。优点是灵活、无单点故障；缺点是可能出现冲突、难以调试。</p>
<p style="color: #191b1f;" data-pid="atx2rsg7">混合协调：结合两者优点，重要决策由协调器做，细节由 Agent 之间协商。</p>
<p style="color: #191b1f;" data-pid="q0412j4J">动态协调：根据任务特点动态选择协调策略。简单任务用顺序协作，复杂任务用层级协作。</p>
<h2 style="font-weight: 500; color: #191b1f;">4.7 实施要点</h2>
<p style="color: #191b1f;" data-pid="UhPuXt_Y">明确分工：每个 Agent 的职责要清晰，避免重叠和空白。写清楚每个 Agent 负责什么、不负责什么。</p>
<p style="color: #191b1f;" data-pid="lh2aaOO8">接口标准化：Agent 之间的接口要标准化，包括输入输出格式、错误码、超时处理等。</p>
<p style="color: #191b1f;" data-pid="N47Wc6Yq">错误隔离：一个 Agent 出错不应该导致整个系统崩溃。要有错误隔离和恢复机制。</p>
<p style="color: #191b1f;" data-pid="ymv2WNhh">性能优化：识别瓶颈 Agent，考虑并行化、缓存、负载均衡等优化手段。</p>
<p style="color: #191b1f;" data-pid="svu7XLUs">版本管理：不同 Agent 可能有不同的更新频率，要有版本管理机制，确保兼容性。</p>
<h2 style="font-weight: 500; color: #191b1f;">4.8 优势与挑战</h2>
<p style="color: #191b1f;" data-pid="NouTf6jQ">优势：</p>
<ul style="color: #191b1f;">
<li data-pid="jLWbWpmJ">可扩展性好，可以随时添加新的专业 Agent</li>
<li data-pid="g-nQBgCs">复用性高，Agent 可以在不同任务中复用</li>
<li data-pid="NEyA8gIq">维护性好，每个 Agent 独立维护，互不影响</li>
<li data-pid="RDzAQ5Q6">可靠性高，通过冗余和交叉验证提高准确性</li>
</ul>
<p style="color: #191b1f;" data-pid="QPbvYgrr">挑战：</p>
<ul style="color: #191b1f;">
<li data-pid="OzNSnFzF">协调开销大，Agent 之间的通信和协调需要额外成本</li>
<li data-pid="gT_UjGgF">调试困难，问题可能出现在任何一个 Agent 或它们的交互中</li>
<li data-pid="2O5NnxFk">延迟增加，多个 Agent 串行或协调都会增加总体时间</li>
<li data-pid="A9YT2Dps">成本上升，每个 Agent 都需要模型调用，成本成倍增加</li>
</ul>
<h2 style="font-weight: 500; color: #191b1f;">5. 人机协同模式</h2>
<h2 style="font-weight: 500; color: #191b1f;">5.1 模式定义</h2>
<p style="color: #191b1f;" data-pid="GTacXAA6">人机协同模式是在 Agent 工作流程中嵌入人工干预点的设计模式。Agent 在关键决策点暂停执行，等待人类审核、提供额外信息或做出决策，然后继续执行。这不是简单的人工兜底，而是人类智慧和 AI 能力的有机结合。</p>
<p style="color: #191b1f;" data-pid="4orNrTpL">这个模式承认了一个现实：当前的 AI 还不能完全自主地处理所有情况，特别是涉及主观判断、伦理决策、高风险操作的场景。通过合理的人机协同，可以发挥各自优势。</p>
<p style="color: #191b1f;" data-pid="Glk-6qBG">在 AI 编程中通用有一个手动模式和一个自动模式。</p>
<h2 style="font-weight: 500; color: #191b1f;">5.2 解决的问题</h2>
<p style="color: #191b1f;" data-pid="vnbhO2h-">人机协同模式解决的是纯 AI 方案风险太高或能力不足的问题：</p>
<ul style="color: #191b1f;">
<li data-pid="pAfH8Di6">高风险决策需要人工确认，比如大额交易、医疗诊断</li>
<li data-pid="MLDpeofs">主观判断 AI 难以把握，比如创意评审、品牌调性</li>
<li data-pid="49-xdVzA">异常情况超出 AI 训练范围，需要人类经验</li>
<li data-pid="7AkLY48H">法律或合规要求必须有人参与决策</li>
<li data-pid="1c3J8Vvl">AI 不确定性太高，需要人工验证</li>
</ul>
<p style="color: #191b1f;" data-pid="1doTupmg">这个模式的关键是找到人机协同的最佳平衡点，既不能过度依赖人工（那就失去了自动化的意义），也不能完全放手给 AI（可能造成严重后果）。</p>
<h2 style="font-weight: 500; color: #191b1f;">5.3 协同机制</h2>
<p style="color: #191b1f;" data-pid="8KQDwxq0">审核点（Checkpoint）：在工作流的特定位置设置审核点，Agent 必须等待人工审核才能继续。审核点的位置很关键，太多会影响效率，太少可能错过关键决策。</p>
<p style="color: #191b1f;" data-pid="gvRZSPRQ">升级机制（Escalation）：当 Agent 遇到超出能力范围的情况时，自动升级到人工处理。需要定义清楚什么情况下升级，比如置信度低于阈值、遇到预定义的异常情况等。</p>
<p style="color: #191b1f;" data-pid="nlNK7phT">协作模式（Collaboration）：人类和 Agent 共同完成任务，各自负责擅长的部分。比如 Agent 做数据分析，人类做战略决策；Agent 生成初稿，人类做最终润色。</p>
<p style="color: #191b1f;" data-pid="tBidAWim">反馈循环（Feedback Loop）：人类的决策和修正会反馈给 Agent，用于改进后续的行为。这是一个持续学习的过程。</p>
<h2 style="font-weight: 500; color: #191b1f;">5.4 干预类型</h2>
<p style="color: #191b1f;" data-pid="8W0k8aBE">批准型干预：Agent 完成工作后，需要人工批准才能生效。比如 Agent 起草了一份合同，法务人员审核批准后才发送。这种干预主要是把关和确认。</p>
<p style="color: #191b1f;" data-pid="AL7CDgnU">选择型干预：Agent 提供多个选项，由人类选择。比如 Agent 生成了三个营销方案，市场总监选择最合适的。这种干预利用人类的判断力。</p>
<p style="color: #191b1f;" data-pid="dRupME1D">修正型干预：人类可以修改 Agent 的输出。比如 Agent 写了一篇文章，编辑可以直接修改其中的内容。这种干预是精细调整。</p>
<p style="color: #191b1f;" data-pid="HBUMrDxV">补充型干预：人类提供 Agent 缺少的信息。比如 Agent 在处理客户投诉时，遇到特殊情况，客服人员提供额外的背景信息。这种干预是信息补充。</p>
<p style="color: #191b1f;" data-pid="VkmTvNoo">接管型干预：在某些情况下，人类完全接管任务。比如 Agent 判断问题太复杂，直接转给人工处理。这种干预是兜底机制。</p>
<h2 style="font-weight: 500; color: #191b1f;">5.5 设计原则</h2>
<p style="color: #191b1f;" data-pid="Ebf65Qv8">最小干预原则：只在必要的地方设置人工干预，尽量让 Agent 自主完成任务。过多的干预会降低效率，失去自动化的意义。</p>
<p style="color: #191b1f;" data-pid="XuVj8cZR">透明度原则：人类要能理解 Agent 的决策依据。Agent 应该提供决策的理由、使用的数据、考虑的因素等，让人类能做出明智的判断。</p>
<p style="color: #191b1f;" data-pid="28kejkPg">可控性原则：人类要能随时介入、修改或停止 Agent 的行为。要有紧急停止按钮、回滚机制等。</p>
<p style="color: #191b1f;" data-pid="0lzD0Qj1">责任明确原则：明确人和 AI 各自的责任边界。特别是出现问题时，要清楚责任在谁。</p>
<p style="color: #191b1f;" data-pid="ZgJI8SA9">用户体验原则：人机交互界面要友好，信息呈现要清晰，操作要简便。不能因为加入人工环节就让流程变得复杂。</p>
<h2 style="font-weight: 500; color: #191b1f;">5.6 实施要点</h2>
<p style="color: #191b1f;" data-pid="BJorksOd">界面设计：人机交互界面是关键。要展示必要信息，但不能信息过载。要提供便捷的操作方式，减少人工负担。可以用可视化、摘要、高亮等技术。</p>
<p style="color: #191b1f;" data-pid="WAhUXJqT">通知机制：需要人工介入时，要有及时的通知机制。可以是应用内通知、邮件、短信等。要考虑优先级和紧急程度。</p>
<p style="color: #191b1f;" data-pid="utpp9CM0">超时处理：人工可能不能及时响应，要有超时机制。可以是自动采用保守方案、转给其他人、暂停任务等。</p>
<p style="color: #191b1f;" data-pid="_INnDWnd">权限管理：不同的人可能有不同的干预权限。要有完善的权限体系，确保只有合适的人才能做关键决策。</p>
<p style="color: #191b1f;" data-pid="7e5o5M39">审计追踪：所有的人工干预都要有记录。谁在什么时间做了什么决定，依据是什么。这对于问题追溯和合规审计都很重要。</p>
<h2 style="font-weight: 500; color: #191b1f;">5.7 优势与挑战</h2>
<p style="color: #191b1f;" data-pid="r_gtq5Mv">优势：</p>
<ul style="color: #191b1f;">
<li data-pid="AZ3scAB6">安全性高，关键决策有人把关</li>
<li data-pid="zKjEzFs1">灵活性好，能处理 AI 无法处理的特殊情况</li>
<li data-pid="AFxvju9G">可信度高，用户更信任有人参与的系统</li>
<li data-pid="oJSic7st">持续改进，人工反馈帮助系统不断优化</li>
</ul>
<p style="color: #191b1f;" data-pid="M1NHxDbZ">挑战：</p>
<ul style="color: #191b1f;">
<li data-pid="g-miyv9n">效率降低，人工环节会增加处理时间</li>
<li data-pid="qTVGb4Uw">成本增加，需要人力投入</li>
<li data-pid="Pa1C_d3P">一致性难保证，不同人可能有不同判断</li>
<li data-pid="UcsdWhkJ">扩展性受限，人工环节可能成为瓶颈</li>
</ul>
<h2 style="font-weight: 500; color: #191b1f;">6. 选择建议</h2>
<p style="color: #191b1f;" data-pid="gx2Blv5w">选择合适的设计模式需要综合考虑多个因素。这里提供一个决策框架：</p>
<h2 style="font-weight: 500; color: #191b1f;">6.1 从简单到复杂的演进路径</h2>
<p style="color: #191b1f;" data-pid="tLPpvwFb">第一阶段：单 Agent 模式</p>
<ul style="color: #191b1f;">
<li data-pid="_kwHgM1c">任务相对简单，领域单一</li>
<li data-pid="A0mZERoV">团队刚开始尝试 Agent</li>
<li data-pid="Mec_sljG">需要快速验证概念</li>
<li data-pid="V8KAY9cd">成本敏感</li>
</ul>
<p style="color: #191b1f;" data-pid="ov-GP8M1">第二阶段：ReAct 模式</p>
<ul style="color: #191b1f;">
<li data-pid="M_JVbauq">任务需要多步推理</li>
<li data-pid="c11zaOPS">结果需要可解释性</li>
<li data-pid="3kmzdTCW">有一定的复杂度但还能单 Agent 处理</li>
</ul>
<p style="color: #191b1f;" data-pid="UJ_L_f3_">第三阶段：多 Agent 协作</p>
<ul style="color: #191b1f;">
<li data-pid="27PgjGnL">任务跨越多个领域</li>
<li data-pid="DSgrgDam">需要专业分工</li>
<li data-pid="FJSMSXwq">单 Agent 已经力不从心</li>
</ul>
<p style="color: #191b1f;" data-pid="z2MJBPug">始终考虑：人机协同</p>
<ul style="color: #191b1f;">
<li data-pid="JSSPQNiJ">涉及高风险决策</li>
<li data-pid="rMZmOKnD">需要主观判断</li>
<li data-pid="IdqNL36w">法规要求人工参与</li>
</ul>
<h2 style="font-weight: 500; color: #191b1f;">6.2 关键决策因素</h2>
<p style="color: #191b1f;" data-pid="4g83YuGT">任务复杂度：</p>
<ul style="color: #191b1f;">
<li data-pid="zcFEfnSi">低：单 Agent</li>
<li data-pid="2MgCJcdU">中：ReAct 或简单的多 Agent</li>
<li data-pid="NDCyaahc">高：复杂的多 Agent</li>
</ul>
<p style="color: #191b1f;" data-pid="LQK8VKqA">响应时间要求：</p>
<ul style="color: #191b1f;">
<li data-pid="5xNPjVtX">实时（秒级）：单 Agent</li>
<li data-pid="DBCoZlka">近实时（分钟级）：ReAct 或并行多 Agent</li>
<li data-pid="p1ys5IN9">非实时（小时级）：任何模式都可以</li>
</ul>
<p style="color: #191b1f;" data-pid="I0DIQoyk">成本预算：</p>
<ul style="color: #191b1f;">
<li data-pid="8EX0eWe1">紧张：单 Agent</li>
<li data-pid="E2ACv727">适中：ReAct 或简单多 Agent</li>
<li data-pid="anasik7h">充足：复杂多 Agent</li>
</ul>
<p style="color: #191b1f;" data-pid="3wgZNQy_">可靠性要求：</p>
<ul style="color: #191b1f;">
<li data-pid="kPKu7c91">一般：单 Agent 或 ReAct</li>
<li data-pid="6FQ28HNb">高：多 Agent 协作（通过冗余提高可靠性）</li>
<li data-pid="huaOUTxM">关键：人机协同</li>
</ul>
<p style="color: #191b1f;" data-pid="H1J6y_Ia">团队能力：</p>
<ul style="color: #191b1f;">
<li data-pid="2KIzyUHA">初级：从单 Agent 开始</li>
<li data-pid="Ue8OyL_R">中级：可以尝试 ReAct 和简单多 Agent</li>
<li data-pid="uEIBJk_F">高级：可以驾驭任何模式</li>
</ul>
<h2 style="font-weight: 500; color: #191b1f;">7. 总结</h2>
<p style="color: #191b1f;" data-pid="D_6RkTz6">AI Agent 的设计模式不是银弹，每种模式都有自己的适用场景和权衡。单 Agent 模式简单直接，适合入门和简单任务。ReAct 模式增加了推理能力，适合需要探索的问题。多 Agent 协作通过分工提高能力，适合复杂的领域任务。层级规划通过递归分解处理高复杂度问题。人机协同则是当前 AI 能力限制下的必要补充。</p>
<p style="color: #191b1f;" data-pid="zZCQn7q0">选择模式时，要从实际需求出发，考虑任务特性、资源限制、团队能力等因素。不要过度设计，也不要畏手畏脚。从简单开始，逐步演进，在实践中找到最适合的方案。</p>
<p style="color: #191b1f;" data-pid="CWqbOYuI">技术最终是为业务服务的。不管用什么模式，最终目的是解决实际问题，创造价值。</p>
<p style="color: #191b1f;" data-pid="VvmDZBXX">以上。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2025/10/4-common-design-patterns-for-ai-agent-architecture/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Multi-Agent 系统的主从架构</title>
		<link>https://www.phppan.com/2025/08/multi-agent-master-slave/</link>
		<comments>https://www.phppan.com/2025/08/multi-agent-master-slave/#comments</comments>
		<pubDate>Sun, 24 Aug 2025 00:20:17 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[Agent]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">https://www.phppan.com/?p=2410</guid>
		<description><![CDATA[最近一年，Multi-Agent 系统持续发热发烫，融资不断，火了起来。 从 AutoGPT 到 MetaGP [&#8230;]]]></description>
				<content:encoded><![CDATA[<section style="color: #000000;" data-tool="mdnice编辑器" data-website="https://www.mdnice.com" data-pm-slice="0 0 []">
<p data-tool="mdnice编辑器">最近一年，Multi-Agent 系统持续发热发烫，融资不断，火了起来。</p>
<p data-tool="mdnice编辑器">从 AutoGPT 到 MetaGPT，从 CrewAI 到 LangGraph，各种多代理框架层出不穷。国内现象级的 Manus，以及当天由 MetaGPT 的同学开源的 OpenManus。OpenAI 的 Swarm、微软的 AutoGen，还有 Anthropic 的 Claude Code，每个大厂都在探索自己的 Multi-Agent 方案。GitHub 上相关项目的 Star 数动辄上万，社区讨论热度持续攀升。</p>
<p data-tool="mdnice编辑器">从这股热潮，我们可以看出 AI 应用的一个重要趋势：从单一模型调用走向多智能体协作。就像软件开发从单体应用演进到微服务架构，AI 系统也在探索如何通过多个专门化的 Agent 协同工作，完成更复杂的任务。</p>
<p data-tool="mdnice编辑器">当我们仔细观察这些 Multi-Agent 系统的架构时，会发现一个规律：</p>
<p data-tool="mdnice编辑器">MetaGPT 里有个产品经理角色，负责协调其他工程师角色；AutoGen 支持 Manager-Worker 模式；Claude Code 更是明确采用了<strong style="color: #0e88eb;">主循环引擎加子任务代理</strong>的设计。在 OpenAI Swarm 中，也能看到 Orchestrator Agent 的影子。</p>
<p data-tool="mdnice编辑器">这些系统都采用了某种形式的「主从」架构——有一个 Agent 负责全局协调，其他 Agent 提供专门化支持。</p>
<p data-tool="mdnice编辑器">为什么？巧合吗？</p>
<p data-tool="mdnice编辑器">今天我们就聊聊 Multi-Agent 系统的主从架构。从大模型的底层原理开始。</p>
<h1 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">1 从大模型的原理说起</span></h1>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">1.1 大模型的「注意力」机制</span></h2>
<p data-tool="mdnice编辑器">要理解为什么需要主从架构，得先理解大模型是怎么「思考」的。</p>
<p data-tool="mdnice编辑器">大模型的核心是 Transformer 架构，而 Transformer 的灵魂是注意力机制（Attention）。简单来说，模型在生成每个 token 时，会「注意」到输入中的所有相关信息（上下文窗口内），然后综合这些信息做出决策。</p>
<p data-tool="mdnice编辑器">这里有个关键点：<strong style="color: #0e88eb;">大模型的每次决策都是基于它能「看到&#8221;」的全部上下文</strong>。</p>
<p data-tool="mdnice编辑器">这就像你在做一道数学题。如果题目是&#8221;小明有 5 个苹果，给了小红 2 个&#8221;，你要回答&#8221;小明还剩几个&#8221;，你必须同时看到&#8221;5 个&#8221;和&#8221;给了 2 个&#8221;这两个信息。如果你只看到其中一部分，就无法得出正确答案。</p>
<p data-tool="mdnice编辑器">大模型也是如此。它的智能来源于对上下文的完整理解（其智能还来源于预训练时学到的知识，模式识别、知识迁移等能力）。一旦上下文缺失或者矛盾，模型的输出质量就会急剧下降。</p>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">1.2 多个模型协作的挑战</span></h2>
<p data-tool="mdnice编辑器">当多个大模型（Agent）需要协作时，如何保证它们都拥有必要的上下文？</p>
<p data-tool="mdnice编辑器">假设我们有三个 Agent 并行进行开发部署工作：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">Agent A：负责前端开发</section>
</li>
<li>
<section style="color: #010101;">Agent B：负责后端开发</section>
</li>
<li>
<section style="color: #010101;">Agent C：负责部署运维</section>
</li>
</ul>
<p data-tool="mdnice编辑器">理想情况下，它们应该像一个经验丰富的全栈工程师一样，时刻知道其他部分的设计决策。但实际上，每个 Agent 都是独立的大模型实例，它们各自维护着自己的上下文。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">这就产生了第一个问题：上下文分裂</strong>。</p>
<p data-tool="mdnice编辑器">Agent A 决定使用 React，Agent B 决定用 Python Flask，这本来没问题。但当 Agent A 后续生成代码时假设后端返回 GraphQL，而 Agent B 实际提供的是 REST API，最终代码就无法正常工作。</p>
<p data-tool="mdnice编辑器">并且大模型有个特性叫「自回归生成」——每个新的输出都依赖于之前的所有输出。这意味着一旦某个 Agent 做出了错误假设，这个错误会在后续生成中不断放大。</p>
<h1 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2 主从架构的设计哲学</span></h1>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2.1 为什么主从架构有效</span></h2>
<p data-tool="mdnice编辑器">主从架构的核心思想很简单：<strong style="color: #0e88eb;">一个指挥，多个执行。一个主 Agent 掌控全局，其他从 Agent 提供子领域专业化的支持</strong>。</p>
<p data-tool="mdnice编辑器">这个设计直接解决了上下文分裂的问题。主 Agent 始终维护着完整的任务上下文，它知道：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">整体目标是什么</section>
</li>
<li>
<section style="color: #010101;">已经做了哪些决策</section>
</li>
<li>
<section style="color: #010101;">各个部分如何配合</section>
</li>
<li>
<section style="color: #010101;">当前的优先级是什么</section>
</li>
</ul>
<p data-tool="mdnice编辑器">从 Agent 则像是主 Agent 的「外脑」——当主 Agent 需要专门知识时，会调用相应的从 Agent，但最终的决策和执行都由主 Agent 完成。</p>
<p data-tool="mdnice编辑器">在我们做具体实现的时候，每个不同的从 Agent 都有自己的角色和系统 Prompt。</p>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2.2 Claude Code 的实践印证</span></h2>
<p data-tool="mdnice编辑器">Claude Code 的设计诠释了主从的理念。根据 Github 上逆向工程的分析，它的架构中：</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">nO 主循环引擎</strong>（主 Agent）负责：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">维护完整的代码上下文</section>
</li>
<li>
<section style="color: #010101;">协调所有子任务</section>
</li>
<li>
<section style="color: #010101;">做最终决策</section>
</li>
<li>
<section style="color: #010101;">生成实际代码</section>
</li>
</ul>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">I2A 子任务代理</strong>（从 Agent）负责：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">回答特定问题</section>
</li>
<li>
<section style="color: #010101;">提供专业建议</section>
</li>
<li>
<section style="color: #010101;">探索可能的解决方案</section>
</li>
</ul>
<p data-tool="mdnice编辑器">Claude Code 刻意避免了子 Agent 的并行修改。当需要调查多个方向时，主 Agent 会有限范围内并行地咨询不同的子 Agent，确保每个决策都基于最新的完整上下文。</p>
<p data-tool="mdnice编辑器">这种设计看起来「低效」，但实际上避免了大量的错误和重做，总体效率反而更高。</p>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2.3 生物学的启发</span></h2>
<p data-tool="mdnice编辑器">并且，主从架构在生物界也是有比较多例子的。</p>
<p data-tool="mdnice编辑器">人脑就是一个典型的例子。前额叶皮质充当「主 Agent」，负责高级决策和规划。而各个专门脑区（视觉皮层、听觉皮层、运动皮层等）就像「从 Agent」，处理特定类型的信息。</p>
<p data-tool="mdnice编辑器">所有的感官输入最终都会汇聚到前额叶皮质，由它整合信息并做出决策。即使是反射动作，大脑也会在事后「知晓」并可能调整后续行为。</p>
<p data-tool="mdnice编辑器">这种中心化的架构经过了数亿年的进化验证。</p>
<h1 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3 主从架构的技术实现</span></h1>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3.1 上下文管理</span></h2>
<p data-tool="mdnice编辑器">实现主从架构，最核心的是上下文管理。主 Agent 需要：</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">1. 维护完整但精简的上下文</strong></p>
<p data-tool="mdnice编辑器">并不是所有信息都同等重要。主 Agent 需要智能地压缩和总结历史信息。Claude Code 使用了一个策略：</p>
<p data-tool="mdnice编辑器">当 token 使用量达到阈值的 92% 时，触发压缩机制。关键决策被保留，而从 Agent 的中间探索过程被压缩或丢弃。这样既保持了决策的连贯性，又避免了上下文爆炸。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">2. 构建结构化的决策记录</strong></p>
<p data-tool="mdnice编辑器">不要只是简单地拼接所有的对话历史。需要结构化地记录：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">任务目标和约束</section>
</li>
<li>
<section style="color: #010101;">已做出的关键决策</section>
</li>
<li>
<section style="color: #010101;">各决策之间的依赖关系</section>
</li>
<li>
<section style="color: #010101;">待解决的问题队列</section>
</li>
</ul>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">3. 动态调整上下文窗口</strong></p>
<p data-tool="mdnice编辑器">根据任务的复杂度和当前阶段，动态调整传递给从 Agent 的上下文量。初期探索阶段可以更开放，后期执行阶段需要更精确。</p>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3.2 Agent 的设计原则</span></h2>
<p data-tool="mdnice编辑器">Agent 不是越智能越好，而是要<strong style="color: #0e88eb;">专注</strong>和<strong style="color: #0e88eb;">可控</strong>：</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">1. 明确的能力边界</strong></p>
<p data-tool="mdnice编辑器">每个从 Agent 应该有清晰定义的能力范围。比如：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">代码审查 Agent：只负责发现潜在问题</section>
</li>
<li>
<section style="color: #010101;">重构 Agent：只负责改进代码结构</section>
</li>
<li>
<section style="color: #010101;">测试 Agent：只负责生成测试用例</section>
</li>
</ul>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">2. 标准化的输入输出</strong></p>
<p data-tool="mdnice编辑器">从 Agent 的接口要标准化，这样主 Agent 可以用统一的方式调用它们。输出格式也要规范，便于主 Agent 解析和整合。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">3. 无状态设计</strong></p>
<p data-tool="mdnice编辑器">从 Agent 最好是无状态的，每次调用都是独立的。这样可以避免状态管理的复杂性，也便于并行化（当任务确实独立时）。</p>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3.3 协调机制的关键点</span></h2>
<p data-tool="mdnice编辑器">主 Agent 的协调能力决定了整个系统的表现：</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">1. 任务分解策略</strong></p>
<p data-tool="mdnice编辑器">并不是所有任务都要分解。主 Agent 需要学会判断：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">简单任务直接处理</section>
</li>
<li>
<section style="color: #010101;">复杂任务分解但保持上下文</section>
</li>
<li>
<section style="color: #010101;">探索性任务可以并行但结果需要串行整合</section>
</li>
</ul>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">2. 冲突检测与解决</strong></p>
<p data-tool="mdnice编辑器">即使在主从架构下，从 Agent 的建议也可能相互矛盾。主 Agent 需要：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">检测潜在的冲突</section>
</li>
<li>
<section style="color: #010101;">评估不同方案的优劣</section>
</li>
<li>
<section style="color: #010101;">做出最终决策并保持一致性</section>
</li>
</ul>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">3. 优雅降级</strong></p>
<p data-tool="mdnice编辑器">当从 Agent 失败或不可用时，主 Agent 应该能够：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">尝试从其它从 Agent 获取</section>
</li>
<li>
<section style="color: #010101;">降级到自己处理</section>
</li>
<li>
<section style="color: #010101;">调整任务策略</section>
</li>
</ul>
<h1 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4 主从架构的优势与局限</span></h1>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.1 主从架构的核心优势</span></h2>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">1. 全局一致性保证</strong>主 Agent 作为唯一的决策中心，天然保证了架构决策的一致性。不只是技术栈的选择（比如统一使用 REST 还是 GraphQL），更重要的是接口约定、错误处理策略、命名规范等细节都能保持统一。这种一致性在复杂项目中价值巨大。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">2. 清晰的决策链路</strong>每个决策都有明确的来源和依据。你可以在主 Agent 的对话历史中追踪每个架构决定是如何做出的，为什么选择某个方案。这种可追溯性在调试问题或向他人解释系统设计时非常有价值。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">3. 优雅的错误处理</strong>主 Agent 掌握全局状态，当某个子任务失败时，它可以准确判断影响范围并制定恢复策略。比如，如果数据库设计出错，主 Agent 知道哪些 API 设计需要相应调整。而在去中心化系统中，这种级联影响很难追踪和修复。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">4. 上下文利用最大化</strong>看似串行的决策流程，实际上优化了整体效率：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">避免了重复劳动（多个 Agent 不会各自生成相似的代码）</section>
</li>
<li>
<section style="color: #010101;">减少了协调开销（不需要 Agent 间的大量通信）</section>
</li>
<li>
<section style="color: #010101;">上下文复用充分（主 Agent 的决策历史可以直接传递给从 Agent）</section>
</li>
</ul>
<p data-tool="mdnice编辑器">在 Claude Code 的实践中，这种设计让系统能在有限的 token 预算内完成相当复杂的编程任务。</p>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.2 主从架构的局限性</span></h2>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">1. 主 Agent 成为性能瓶颈</strong>所有决策都要经过主 Agent，当需要并行处理多个复杂子任务时，主 Agent 的串行决策会限制整体效率。就像一个项目经理同时管理太多团队，协调成本会急剧上升。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">2. 对主 Agent 能力的高度依赖</strong>系统的智能上限取决于主 Agent 的能力。如果主 Agent 对某个领域理解不深，即使有专业的从 Agent，整体表现也会受限。这就像一个不懂技术的经理，很难充分发挥技术团队的潜力。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">3. 缺乏真正的协作智能</strong>主从架构本质上是&#8221;分解-执行-组合&#8221;的模式，缺少 Agent 之间的平等协商和创造性互动。在需要头脑风暴或多视角探索的任务中，这种层级结构可能限制了解决方案的多样性。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">4. 任务分解的粒度难题</strong>主 Agent 需要准确判断任务分解的粒度。分得太细，协调成本高；分得太粗，从 Agent 可能无法胜任。而且随着任务复杂度增加，找到合适的分解方式越来越难。</p>
<h2 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.3 适用场景分析</span></h2>
<p data-tool="mdnice编辑器">主从架构特别适合：</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">1. 工程化任务</strong></p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">代码生成</section>
</li>
<li>
<section style="color: #010101;">系统设计</section>
</li>
<li>
<section style="color: #010101;">文档编写</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这些任务需要高度的一致性和结构化。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">2. 有明确目标的任务</strong></p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">问题诊断</section>
</li>
<li>
<section style="color: #010101;">数据分析</section>
</li>
<li>
<section style="color: #010101;">流程自动化</section>
</li>
</ul>
<p data-tool="mdnice编辑器">目标明确时，中心化协调更高效。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">3. 需要可控性的场景</strong></p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">金融交易</section>
</li>
<li>
<section style="color: #010101;">医疗诊断</section>
</li>
<li>
<section style="color: #010101;">法律咨询</section>
</li>
</ul>
<p data-tool="mdnice编辑器">这些领域不能接受不可预测的行为。</p>
<p data-tool="mdnice编辑器">不太适合：</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">1. 创意生成</strong></p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">头脑风暴</section>
</li>
<li>
<section style="color: #010101;">艺术创作</section>
</li>
<li>
<section style="color: #010101;">探索性研究</section>
</li>
</ul>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">2. 大规模并行处理</strong></p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">日志分析</section>
</li>
<li>
<section style="color: #010101;">图像批处理</section>
</li>
<li>
<section style="color: #010101;">分布式爬虫</section>
</li>
</ul>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">3. 对等协作</strong></p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">多人游戏 AI</section>
</li>
<li>
<section style="color: #010101;">群体仿真</section>
</li>
<li>
<section style="color: #010101;">去中心化系统</section>
</li>
</ul>
<h1 data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">5 小结</span></h1>
<p data-tool="mdnice编辑器">随着大模型能力的提升，主从架构也在演进：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">更长的上下文窗口</strong>：GPT-4 已经支持 128K 的上下文，Claude 3 甚至到了 200K。这意味着主 Agent 可以维护更完整的历史，减少信息损失。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">更好的指令跟随</strong>：新一代模型在指令跟随上有显著提升，从 Agent 可以更准确地理解和执行主 Agent 的指令。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">原生的工具调用</strong>：模型开始原生支持函数调用，这让主从 Agent 之间的接口更加标准化和可靠。</section>
</li>
</ul>
<p data-tool="mdnice编辑器">如果你要实现一个主从架构的 Multi-Agent 系统，以下是一些建议：</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">1. 设计清晰的 Agent 角色</strong>：不要让从 Agent 职责过于宽泛。每个从 Agent 应该像 Unix 工具一样——做一件事，并做好。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">2. 实现鲁棒的错误处理</strong></p>
<p data-tool="mdnice编辑器">从 Agent 失败是常态，不是异常。主 Agent 需要：</p>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">超时机制</section>
</li>
<li>
<section style="color: #010101;">重试策略</section>
</li>
<li>
<section style="color: #010101;">降级方案</section>
</li>
<li>
<section style="color: #010101;">错误隔离</section>
</li>
</ul>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">3. 优化上下文传递</strong>：控制上下文的边界，并不是所有上下文都需要传递给给到 Agent。根据任务类型，精心设计上下文的内容和格式。</p>
<p data-tool="mdnice编辑器"><strong style="color: #0e88eb;">4. 监控和可观测性</strong>：记录所有的决策点和 Agent 交互，后面调试和优化用得上。</p>
<p data-tool="mdnice编辑器">Multi-Agent 的主从架构，本质上是在解决一个古老的问题：<strong style="color: #0e88eb;">如何组织多个智能体高效地完成复杂任务</strong>。</p>
<p data-tool="mdnice编辑器">从生物进化到人类社会，从计算机架构到分布式系统，我们一次次地发现：在需要一致性和可控性的场景下，某种形式的<strong style="color: #0e88eb;">中心化协调</strong>是必要的。</p>
<p data-tool="mdnice编辑器">大模型的出现并没有改变这个规律。相反，由于大模型对上下文的强依赖，主从架构变得更加重要。</p>
<p data-tool="mdnice编辑器">随着大模型能力的提升和 Agent 技术的成熟，我们会看到更多创新的架构出现。但无论如何演进，那些基本的原则——<strong style="color: #0e88eb;">上下文一致性、决策可控性、错误可恢复性</strong>——都是我们在实践中需要谨慎考虑的。</p>
<p data-tool="mdnice编辑器">以上。</p>
<p>&nbsp;</p>
</section>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2025/08/multi-agent-master-slave/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>分页的秘密：OFFSET 性能问题与游标分页</title>
		<link>https://www.phppan.com/2024/12/efficient-pagination-mysql-offset-keyset-optimization/</link>
		<comments>https://www.phppan.com/2024/12/efficient-pagination-mysql-offset-keyset-optimization/#comments</comments>
		<pubDate>Sat, 21 Dec 2024 03:05:18 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[分页]]></category>
		<category><![CDATA[性能]]></category>
		<category><![CDATA[性能优化]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=2309</guid>
		<description><![CDATA[在我们日常使用的网站或应用中，无论是浏览电商商品列表、滚动社交媒体动态，还是搜索引擎上一页一页查找结果，分页无 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="color: #000000;" data-tool="mdnice编辑器">在我们日常使用的网站或应用中，无论是浏览电商商品列表、滚动社交媒体动态，还是搜索引擎上一页一页查找结果，分页无处不在。它看似简单，一页接着一页展示数据，但在背后，却隐藏着不少技术的「秘密」。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">分页处理得好，用户只会觉得流畅自然；但如果处理不好，页面加载迟缓、数据重复、甚至直接超时，崩溃，都会让用户体验大打折扣。而在应用架构过程中，分页更是一个绕不开的话题，尤其当涉及到<strong style="color: #0e88eb;">海量数据</strong> 时，分页的实现方式会直接影响到系统的性能和效率。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">OFFSET 性能问题</strong> 就是分页中最常见的「瓶颈」。它的核心问题在于，当数据规模变大时，传统分页方式的查询速度会急剧下降，甚至拖垮整个数据库。幸运的是，我们有解决方案：<strong style="color: #0e88eb;">游标分页</strong>。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">那么，为什么 OFFSET 性能会变差？游标分页又是如何解决这些问题的？今天，我们从分页开始，聊一下分页逻辑。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">1. 分页是什么</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">分页是一个很常见的逻辑，也是大部分程序员入门的时候首先会掌握的一个通用的实现逻辑。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">分页是一种将大量数据分成多个小部分（页面）进行逐步加载和显示的技术方法。它是一种数据分割和展示的策略，常用于需要显示大量数据的场景，既能提升用户体验，又能改善系统性能。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">分页通常通过将数据按照固定的条目数分隔成多个页面，用户可以通过分页导航（如“上一页”、“下一页”、“跳转到第 N 页”等）浏览数据的不同部分。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2. 分页的作用</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">分页的主要作用包括以下几点：</p>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">提升用户体验</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">避免让用户一次性加载和浏览大量数据，从而减少信息过载。</section>
</li>
<li>
<section style="color: #010101;">通过分页导航（如页码按钮、上一页/下一页），让用户能够快速定位到感兴趣的数据。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">优化页面性能</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">限制页面加载的数据量，减少服务器和浏览器的资源消耗。</section>
</li>
<li>
<section style="color: #010101;">减少前端页面渲染的压力，提高页面加载速度和响应速度。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">降低后端和数据库压力</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">分页可以限制一次性查询的数据量，避免对数据库产生过高的查询负载。</section>
</li>
<li>
<section style="color: #010101;">避免将所有数据发送到前端，减少网络的传输压力。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">便于数据管理</strong>：</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">在管理系统中，分页能够让管理员方便地查看、筛选和操作特定范围内的数据。</section>
</li>
</ul>
</li>
</ol>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3. 分页的实现方式</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">分页的实现方式常见的是两种，传统分页和游标分页，根据应用场景和需求，选择合适的方案可以有效提升系统性能和用户体验。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3.1 OFFSET 分页（传统分页）</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">传统分页，也称为基于 OFFSET 的分页，是最常见的一种分页方式。其核心思想是通过页码和偏移量（OFFSET）来定位查询结果的起始记录，并限定每次查询的记录数量（LIMIT）。这种方式通常与 SQL 的 LIMIT 和 OFFSET 关键字结合使用。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">传统分页的主要逻辑是根据用户请求的页码计算出需要跳过的记录数（OFFSET = (page &#8211; 1) * pageSize），然后查询从偏移量开始的指定数量的记录。</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">原理</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">OFFSET 分页是最常见也是最简单的分页方式。它通过指定查询的起始位置和每页记录数，从数据库中获取相应的数据。例如，在 SQL 中可以通过<code style="color: #0e8aeb;">LIMIT</code> 和<code style="color: #0e8aeb;">OFFSET</code> 实现：</p>
<pre style="color: #000000;" data-tool="mdnice编辑器"><code style="color: #abb2bf;"><span style="color: #c678dd;">SELECT</span> * 
<span style="color: #c678dd;">FROM</span> table_name
<span style="color: #c678dd;">ORDER</span> <span style="color: #c678dd;">BY</span> <span style="color: #c678dd;">id</span>
<span style="color: #c678dd;">LIMIT</span> <span style="color: #d19a66;">10</span> <span style="color: #c678dd;">OFFSET</span> <span style="color: #d19a66;">20</span>;
</code></pre>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">LIMIT 10</code>：表示每页显示 10 条记录。</section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">OFFSET 20</code>：表示跳过前 20 条记录（即从第 21 条开始）。</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">优点</span></h3>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">实现简单</strong></p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">逻辑清晰直观，基于<code style="color: #0e8aeb;">LIMIT</code> 和<code style="color: #0e8aeb;">OFFSET</code> 的 SQL 查询几乎所有数据库都支持。</section>
</li>
<li>
<section style="color: #010101;">开发和维护成本低，适合快速实现分页功能。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">支持随机跳页</strong></p>
<pre><code style="color: #0e8aeb;"> <span style="color: #c678dd;">SELECT</span> * 
<span style="color: #c678dd;">FROM</span><span style="color: #c678dd;">users</span>
<span style="color: #c678dd;">ORDER</span><span style="color: #c678dd;">BY</span><span style="color: #c678dd;">id</span><span style="color: #c678dd;">ASC</span>
<span style="color: #c678dd;">LIMIT</span><span style="color: #d19a66;">10</span><span style="color: #c678dd;">OFFSET</span><span style="color: #d19a66;">990</span>;
</code></pre>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">用户可以通过指定页码直接跳转到任意页，而无需逐页加载。例如，直接查询第 100 页的数据：</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">适用范围广</strong></p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">适合小规模或中等规模的数据分页场景，尤其是在数据集较小且性能要求不高时。</section>
</li>
</ul>
</li>
</ol>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">缺点</span></h3>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">性能问题</strong></p>
<pre><code style="color: #0e8aeb;"> <span style="color: #c678dd;">SELECT</span> * 
<span style="color: #c678dd;">FROM</span><span style="color: #c678dd;">users</span>
<span style="color: #c678dd;">ORDER</span><span style="color: #c678dd;">BY</span><span style="color: #c678dd;">id</span><span style="color: #c678dd;">ASC</span>
<span style="color: #c678dd;">LIMIT</span><span style="color: #d19a66;">10</span><span style="color: #c678dd;">OFFSET</span><span style="color: #d19a66;">100000</span>;
</code></pre>
<p style="color: #000000;">在这种情况下，数据库需要先扫描 100,000 条记录后，才能返回第 100,001 条到第 100,010 条记录。扫描的记录越多，查询耗时越长。</p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">当数据量很大时，<code style="color: #0e8aeb;">OFFSET</code> 会导致查询性能下降，因为数据库需要扫描并跳过<code style="color: #0e8aeb;">OFFSET</code> 指定的记录，即使这些记录不会返回。<br />
例如：</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">数据一致性问题</strong></p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">重复记录</strong>：如果在第一页和第二页之间插入了一条新记录，第二页可能会重复显示第一页的最后一条记录。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">记录丢失</strong>：如果在分页过程中删除了某些记录，可能会导致某些记录被跳过。</section>
</li>
</ul>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">如果在分页过程中数据发生变化（如插入或删除记录），可能会导致分页结果出现重复记录或跳过记录的情况。例如：</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">不适合实时更新的场景</strong></p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">当数据集频繁增删时，传统分页难以保证结果的准确性。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">消耗资源</strong></p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">每次分页查询都需要数据库执行完整的排序和偏移操作，对资源消耗较大，尤其在大数据集或深分页（偏移量很大）时问题更加明显。这种我们一般称之为<strong style="color: #0e88eb;">深分页</strong></section>
</li>
</ul>
</li>
</ol>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">适用场景</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">适合小规模数据分页，或者数据更新不频繁的场景，如展示固定的商品列表或博客文章。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3.2 Keyset 分页（游标分页）</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">Keyset Pagination，也称为基于键的分页或游标分页，是一种高效的分页技术，用于解决传统分页方法（基于 OFFSET 和 LIMIT）在处理大数据集时的性能瓶颈问题。相较于传统分页，Keyset Pagination 不依赖页码或偏移量，而是通过上一页的最后一条记录的标识符（通常是主键或唯一索引）来标记分页的起始点，从而实现更高效、更稳定的分页。</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">原理</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">游标分页是一种基于游标的分页方式，通过使用上一页的最后一条记录的标识（如主键或时间戳）来确定下一页的数据，而不是依赖 OFFSET。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">示例查询：</p>
<pre style="color: #000000;" data-tool="mdnice编辑器"><code style="color: #abb2bf;"><span style="color: #c678dd;">SELECT</span> * 
<span style="color: #c678dd;">FROM</span> table_name
<span style="color: #c678dd;">WHERE</span> <span style="color: #c678dd;">id</span> &gt; <span style="color: #d19a66;">100</span>
<span style="color: #c678dd;">ORDER</span> <span style="color: #c678dd;">BY</span> <span style="color: #c678dd;">id</span>
<span style="color: #c678dd;">LIMIT</span> <span style="color: #d19a66;">10</span>;
</code></pre>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">id &gt; 100</code>：表示从上一页最后一条记录的主键（<code style="color: #0e8aeb;">id=100</code>）之后开始查询。</section>
</li>
<li>
<section style="color: #010101;"><code style="color: #0e8aeb;">LIMIT 10</code>：每次获取 10 条记录。</section>
</li>
</ul>
<h4 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;"><strong style="color: #0e88eb;">优点</strong></span></h4>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">性能优越</strong>：避免了 OFFSET 扫描的性能问题，查询直接从指定游标位置开始。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">数据一致性</strong>：即使数据在分页过程中发生变化，也能保证数据不会重复或丢失。</section>
</li>
</ul>
<h4 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;"><strong style="color: #0e88eb;">缺点</strong></span></h4>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">跳页困难</strong>：无法直接跳转到第 N 页，需要依赖前置页的上下文。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">依赖排序字段</strong>：通常需要全局唯一且连续的排序字段（如主键或时间戳）。</section>
</li>
</ul>
<h4 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;"><strong style="color: #0e88eb;">适用场景</strong></span></h4>
<p style="color: #000000;" data-tool="mdnice编辑器">适合处理海量数据或数据频繁更新的场景，如社交媒体动态流、消息列表、AIGC 的推荐图片流等。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">聊完了常见的两种分页，再聊一下 OFFSET 为什么会慢。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4. OFFSET 为什么会慢</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">以 MySQL 为例。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><code style="color: #0e8aeb;">LIMIT ... OFFSET ...</code> 是一种常用的分页查询方式，但随着<code style="color: #0e8aeb;">OFFSET</code> 值的增大，这种方式会带来严重的性能问题。其核心原因在于<strong style="color: #0e88eb;">MySQL 的查询执行机制</strong> 和<strong style="color: #0e88eb;">数据的存储与读取方式</strong>。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">在执行<code style="color: #0e8aeb;">LIMIT ... OFFSET ...</code> 查询时，MySQL 的行为是<strong style="color: #0e88eb;">扫描并跳过 OFFSET 指定的记录</strong>，即使这些记录不会返回到客户端，但是数据库仍然需要从磁盘读取记录，排序……</p>
<p style="color: #000000;" data-tool="mdnice编辑器">这不是执行问题，而是 OFFSET 设计方式：</p>
<pre style="color: #000000;" data-tool="mdnice编辑器"><code style="color: #abb2bf;">…the rows are first sorted according to the &lt;order by clause&gt; and <span style="color: #c678dd;">then</span> limited by dropping the number of rows specified <span style="color: #c678dd;">in</span> the &lt;result offset clause&gt; from the beginning…

SQL:2016, Part 2, §4.15.3 Derived tables

翻译过来：……记录会首先根据 ORDER BY 子句 进行排序，然后通过丢弃从开头开始的 OFFSET 子句指定数量的行来限制结果……

</code></pre>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.1 OFFSET 执行过程</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">比如下面的例子：</p>
<pre style="color: #000000;" data-tool="mdnice编辑器"><code style="color: #abb2bf;"><span style="color: #c678dd;">SELECT</span> * 
<span style="color: #c678dd;">FROM</span> t1 
<span style="color: #c678dd;">ORDER</span> <span style="color: #c678dd;">BY</span> <span style="color: #c678dd;">id</span> <span style="color: #c678dd;">ASC</span> 
<span style="color: #c678dd;">LIMIT</span> <span style="color: #d19a66;">1000000</span>, <span style="color: #d19a66;">20</span>;
</code></pre>
<p style="color: #000000;" data-tool="mdnice编辑器">其执行过程如下：</p>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">全表扫描或索引扫描：</strong></p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">MySQL 根据<code style="color: #0e8aeb;">ORDER BY id</code> 对记录进行排序。即使只需要第 1000001 条到第 1000020 条记录，也必须先按查询条件读出前 100 万条记录。</section>
</li>
<li>
<section style="color: #010101;">如果有索引（如主键索引<code style="color: #0e8aeb;">id</code>），MySQL 会利用索引扫描；如果没有索引，则会进行全表扫描。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">跳过 OFFSET 记录：</strong></p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">MySQL 遍历查询结果集，并逐条丢弃前 100 万条记录（<code style="color: #0e8aeb;">OFFSET 1000000</code>）。</section>
</li>
<li>
<section style="color: #010101;">这种「丢弃」并不是直接跳过，而是逐行读取，然后丢弃，直到到达第 1000001 条记录。</section>
</li>
</ul>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">读取目标记录：</strong></p>
</section>
<ul class="list-paddingleft-1">
<li>
<section style="color: #010101;">到达第 1000001 条记录后，MySQL 开始读取接下来的 20 条数据（<code style="color: #0e8aeb;">LIMIT 20</code>），作为最终结果返回。</section>
</li>
</ul>
</li>
</ol>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.2 OFFSET 性能问题的根本原因</span></h2>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;"><strong>（1）扫描和跳过造成资源浪费</strong></span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">即使客户端只需要一小部分数据（例如 20 条），MySQL 在执行查询时，仍然需要扫描和处理大量的记录（前 100 万条）。这会带来以下问题：</p>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">耗费磁盘 I/O：</strong><br />
MySQL 需要从磁盘读取未返回的记录，即使这些记录最终会被丢弃。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">浪费内存和 CPU：</strong><br />
MySQL 扫描的所有记录会被加载到内存中，排序和过滤操作会消耗 CPU 资源。对于深分页（<code style="color: #0e8aeb;">OFFSET</code> 值很大）的查询，这种浪费会随着页码的增加而成倍增长。</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;"><strong>（2）无法直接利用索引跳过记录</strong></span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">即使排序字段有索引（如主键索引<code style="color: #0e8aeb;">id</code>），MySQL 仍然需要逐条扫描记录，跳过 OFFSET 指定的记录。原因是：</p>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">索引扫描的局限性：</strong> MySQL 的索引只能用来快速定位起始记录（例如<code style="color: #0e8aeb;">id &gt; 1000000</code> 的情况），但在 OFFSET 查询中，MySQL 并不知道目标记录的具体位置，只能通过逐条遍历的方式来跳过。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">无指针跳转机制：</strong> MySQL 的存储引擎（如 InnoDB）在处理 OFFSET 查询时，不会直接跳过指定数量的记录，而是逐行读取和计数，直到到达目标记录。</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;"><strong>（3）排序带来的额外开销</strong></span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">在使用<code style="color: #0e8aeb;">ORDER BY</code> 的情况下，MySQL 必须先对所有数据进行排序，然后再从中挑选目标记录：</p>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">如果排序字段没有索引，MySQL 会将数据加载到内存或临时表中，并在内存中完成排序（可能会涉及磁盘写入）。</section>
</li>
<li>
<section style="color: #010101;">如果排序字段有索引，MySQL 会利用索引加速排序，但仍需遍历和丢弃 OFFSET 指定的记录，资源浪费依然存在。</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;"><strong>（4）深分页数据量巨大</strong></span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">当<code style="color: #0e8aeb;">OFFSET</code> 值较小时，MySQL 需要跳过的记录量较少，性能影响不明显。但随着<code style="color: #0e8aeb;">OFFSET</code> 值的增大，MySQL 需要扫描和丢弃的记录数呈线性增长，最终导致性能急剧下降。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.3 OFFSET 性能问题的典型场景</span></h2>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;"><strong>（1）数据量庞大时的深分页</strong></span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">当表中的数据量达到百万级别时，深分页（如<code style="color: #0e8aeb;">OFFSET 1000000</code>）会导致查询性能显著下降。原因是 MySQL 在扫描前 100 万条记录时，消耗了大量的磁盘 I/O 和 CPU 资源。</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;"><strong>（2）查询结果动态变化</strong></span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">分页查询的同时，数据可能在不断更新（如新增或删除记录）。这种情况下：</p>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">MySQL 仍然会按照 OFFSET 值从头扫描，导致性能下降。</section>
</li>
<li>
<section style="color: #010101;">数据的插入或删除可能导致分页结果重复或遗漏。</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;"><strong>（3）排序字段没有索引</strong></span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">如果<code style="color: #0e8aeb;">ORDER BY</code> 的字段没有索引，MySQL 需要对全表数据进行排序，并将排序结果存储在临时表中。排序操作会进一步加剧性能问题。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.4 如何解决 OFFSET 性能问题？</span></h2>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">使用游标分页（Keyset Pagination）</strong><br />
通过记录上一页的最后一条记录的唯一标识符（如主键<code style="color: #0e8aeb;">id</code>）来定位下一页的起点，避免扫描和跳过无关记录：</section>
</li>
</ol>
<pre style="color: #000000;" data-tool="mdnice编辑器"><code style="color: #abb2bf;">   <span style="color: #c678dd;">SELECT</span> * 
   <span style="color: #c678dd;">FROM</span> t1 
   <span style="color: #c678dd;">WHERE</span> <span style="color: #c678dd;">id</span> &gt; <span style="font-style: italic; color: #5c6370;">#{last_id} </span>
   <span style="color: #c678dd;">ORDER</span> <span style="color: #c678dd;">BY</span> <span style="color: #c678dd;">id</span> <span style="color: #c678dd;">ASC</span> 
   <span style="color: #c678dd;">LIMIT</span> <span style="color: #d19a66;">20</span>;
</code></pre>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">优势</strong>：直接定位目标记录，性能与<code style="color: #0e8aeb;">OFFSET</code> 无关。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">适用场景</strong>：连续分页（如滑动加载）。</section>
</li>
</ul>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">限制深分页范围</strong><br />
限制用户只能跳转到前后一段范围内的页码，避免深分页。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">子查询优化</strong><br />
使用子查询提取主键范围，然后通过主键关联查询：</p>
</section>
</li>
</ol>
<pre style="color: #000000;" data-tool="mdnice编辑器"><code style="color: #abb2bf;">   <span style="color: #c678dd;">SELECT</span> * 
   <span style="color: #c678dd;">FROM</span> t1 
   <span style="color: #c678dd;">JOIN</span> (
       <span style="color: #c678dd;">SELECT</span> <span style="color: #c678dd;">id</span> 
       <span style="color: #c678dd;">FROM</span> t1 
       <span style="color: #c678dd;">ORDER</span> <span style="color: #c678dd;">BY</span> <span style="color: #c678dd;">id</span> <span style="color: #c678dd;">ASC</span> 
       <span style="color: #c678dd;">LIMIT</span> <span style="color: #d19a66;">1000000</span>, <span style="color: #d19a66;">20</span>
   ) x <span style="color: #c678dd;">USING</span> (<span style="color: #c678dd;">id</span>);
</code></pre>
<ul class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">优势</strong>：减少排序和回表操作的开销。</section>
</li>
</ul>
<ol class="list-paddingleft-1" style="color: #000000;">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">合理设计索引</strong><br />
对常用的查询字段和排序字段添加索引，最大化利用 MySQL 的索引能力。</section>
</li>
</ol>
<p style="color: #000000;" data-tool="mdnice编辑器">除以上的 4 种以外，还可以考虑倒序分页，延迟关联、分区表优化或业务逻辑分流等方案。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">OFFSET 的性能问题，归根结底是因为 MySQL 的查询执行机制无法直接跳过指定数量的记录，只能通过逐条扫描和丢弃的方式实现。这种机制在深分页时会导致严重的资源浪费。通过优化查询方式（如游标分页或子查询），可以显著减少无关记录的扫描量，从而提高查询性能。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">5. 小结</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">分页是日常开发中非常常见的功能，但在数据量上来后，分页可能成为隐藏的性能杀手。传统的 OFFSET 分页尽管实现简单，但却无法避免扫描和跳过大量无用记录的性能瓶颈，尤其在处理海量数据时。这种情况下，优化分页逻辑显得尤为重要。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">通过引入游标分页、子查询优化、分区表设计等技术手段，并结合业务逻辑上的调整，几乎可以解决大部分分页场景的性能问题。在实际开发中，应根据业务特点和数据规模选择合适的优化方案，实现性能和用户体验的平衡。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">分页的优化，不仅是一项技术能力，更是对业务场景理解的体现。希望通过本文的分析和总结，能帮助开发者更好地应对深分页的挑战，写出高效、稳健的分页逻辑！</p>
<p style="color: #000000;" data-tool="mdnice编辑器">以上。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2024/12/efficient-pagination-mysql-offset-keyset-optimization/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>研发效能之规模管理：工程化与系统化的思考</title>
		<link>https://www.phppan.com/2024/10/scale-management-in-software-development-engineering-and-systematic-approach/</link>
		<comments>https://www.phppan.com/2024/10/scale-management-in-software-development-engineering-and-systematic-approach/#comments</comments>
		<pubDate>Sat, 26 Oct 2024 13:15:54 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[架构]]></category>
		<category><![CDATA[研发效能]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=2287</guid>
		<description><![CDATA[随着业务的发展，研发团队和系统架构往往面临一个共同的难题：如何在规模不断扩大的情况下，保持高效、稳定的输出。  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="color: #353535;" data-tool="mdnice编辑器">随着业务的发展，研发团队和系统架构往往面临一个共同的难题：<strong style="color: #f83929;">如何在规模不断扩大的情况下，保持高效、稳定的输出</strong>。</p>
<p style="color: #353535;" data-tool="mdnice编辑器">你是否曾经历过这样的困境：系统运行环境中的负载不断攀升，不得不频繁进行性能优化；团队规模扩充后，开发协作开始变得混乱，沟通成本直线上升；技术债务不断积累，系统的开发和维护变得艰难？</p>
<p style="color: #353535;" data-tool="mdnice编辑器">这些问题的本质在于<strong style="color: #f83929;">规模管理</strong>的缺失或不足。<strong style="color: #f83929;">规模</strong>不仅仅体现在系统需要处理越来越多的用户和数据层面，还包括团队管理、开发流程和技术栈的复杂性增长。如果缺乏系统化和工程化的管理方法，规模的扩大往往会拖慢研发效率，甚至导致项目失控。</p>
<p style="color: #353535;" data-tool="mdnice编辑器">那么，<strong style="color: #f83929;">如何通过系统化、工程化的手段，来解决规模扩展带来的复杂性和挑战</strong>呢？</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="color: #ffffff;">1 研发中的规模</span></h1>
<p style="color: #353535;" data-tool="mdnice编辑器">在软件研发中，规模主要可以分为<strong style="color: #f83929;">生产规模</strong>和<strong style="color: #f83929;">开发规模</strong>两大类。具体来说，研发中的规模主要包括以下几个方面：</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #222222;">1.1 生产规模</span></h2>
<p style="color: #353535;" data-tool="mdnice编辑器">生产规模指的是系统在实际运行环境中所需处理的负载、并发能力和扩展性。它关注的是一个系统在面对业务增长时，是否能够高效处理不断增加的数据量、用户请求、并发任务等。包括：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">并发处理能力</strong>：系统可以同时处理多少用户请求或任务。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">数据处理能力</strong>：系统能够处理的数据量级别如何，是否支持大数据量的存储、查询和分析。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">网络流量承受能力</strong>：系统在面对大规模用户访问时，是否能够保持稳定的响应时间，并在流量高峰期依然能够正常工作。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">弹性扩展能力</strong>：系统是否可以根据流量的变化自动扩展资源，避免高负载时的性能瓶颈和低负载时的资源浪费。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">容错与高可用性</strong>：系统在面对硬件或软件故障时是否具备自我恢复能力，确保业务的连续性。</section>
</li>
</ul>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #222222;">1.2 开发规模</span></h2>
<p style="color: #353535;" data-tool="mdnice编辑器">开发规模指的是随着项目和团队的扩展，如何有效管理代码库、开发流程和团队协作。随着开发人数、代码库复杂度的增长，团队需要更加系统化的管理手段，以保持高效的开发效率和高质量的代码输出。</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">代码库规模</strong>：项目的代码量逐渐增加，模块和功能变得更加复杂。如何确保代码库的可维护性、可测试性和可扩展性是关键。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">团队规模</strong>：参与开发的工程师人数增多，如何确保团队成员高效协作、避免冲突和重复工作是管理的重点。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">协作复杂度</strong>：随着团队规模扩大，沟通和协作的难度也会增加。如何通过协作工具、流程规范和文档化手段确保团队高效运转。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">开发流程的复杂度</strong>：团队规模和项目复杂度增加，开发流程自然也会变得更复杂。如何通过流程优化和工具化手段（如CI/CD、自动化测试等）简化开发、测试、发布流程。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">知识管理</strong>：随着项目复杂度增加，技术债务和知识流失的风险也随之增加。如何通过文档化、知识共享平台等手段，确保团队成员（尤其是新人）快速上手和理解项目。</section>
</li>
</ul>
<p style="color: #353535;" data-tool="mdnice编辑器">除了上面的 5 点，还有一些技术规模相关的点：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">技术栈的扩展性</strong>：技术选型是否具备支撑未来业务增长的能力，是否容易扩展、维护和升级。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">基础设施的扩展性</strong>：从服务器、数据库到网络架构，是否能够支持高并发、大数据量、快速响应等需求。</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">技术债务管理</strong>：随着项目的发展，技术债务的积累不可避免。如何在技术规模扩展的同时进行技术债务的管理和偿还。</section>
</li>
</ul>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="color: #ffffff;">2 如何管理规模</span></h1>
<p style="color: #353535;" data-tool="mdnice编辑器">作为研发管理者，面对系统和团队规模的不断扩大，如何确保研发效能的持续提升，是一个复杂且多维度的挑战。规模管理的核心在于通过<strong style="color: #f83929;">技术手段与管理方法</strong>的结合，保证系统和团队能够适应业务增长，同时避免因规模扩大而带来的效率损失和质量问题。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #222222;">2.1 管理生产规模</span></h2>
<p style="color: #353535;" data-tool="mdnice编辑器">生产规模通常指的是系统在实际运行环境中所能处理的负载、并发能力和扩展性。然而，生产规模的扩展实际上离不开架构、基础设施、自动化手段等，即通过技术手段来保证系统能处理不断增长的业务需求。</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">2.1.1 架构设计与扩展性</span></h3>
<p style="color: #353535;" data-tool="mdnice编辑器">生产规模的扩展依赖于架构设计的弹性和扩展性。<strong style="color: #f83929;">架构设计</strong>是生产系统能否承载更大负载、更高并发的根本。</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">微服务架构</strong>：在面对大规模扩展时，单体架构往往难以承受较大负载和频繁的变更。微服务架构通过将系统拆分为多个独立的服务，每个服务可以独立扩展、部署和维护。这种架构设计允许生产系统根据业务需求水平扩展，避免单点瓶颈。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">事件驱动架构</strong>：在高并发环境下，事件驱动架构可以通过异步消息处理来解耦系统中的模块，从而提高弹性和扩展性。这种架构设计允许系统通过消息队列（如Kafka、RabbitMQ）来处理大量并发请求，并减少同步通信带来的延迟和性能瓶颈。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">分布式架构</strong>：对于需要处理海量数据和高并发请求的生产系统，分布式架构是必不可少的。通过水平扩展（如分布式数据库、分布式缓存、分布式存储等），系统可以在生产环境中扩展以应对更高的负载。</p>
</section>
</li>
</ul>
<p style="color: #353535;" data-tool="mdnice编辑器">架构设计决定了生产规模的技术上限。架构设计是生产系统能否在负载增加时保持高效运行的关键。</p>
<p style="color: #353535;" data-tool="mdnice编辑器">在管理生产规模时，需要着重考虑当前架构的合理性和前瞻性。</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">2.1.2 基础设施扩展和性能优化</span></h3>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">自动化扩展</strong>：利用云计算平台的弹性伸缩功能，根据流量动态增加或减少资源。为了实现更灵活的资源管理和扩展，容器化技术（如 Docker ）和容器编排系统（如 Kubernetes ）成为生产规模扩展的基础。通过容器化，生产环境中的服务可以快速部署、扩展和迁移，从而应对瞬时的流量峰值。同时，Kubernetes 的自动扩展功能可以根据资源的使用情况自动调整服务的实例数量，确保系统在负载变化时能够灵活响应。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">缓存与 CDN</strong>：在高并发访问场景下，合理使用缓存（如Redis、Memcached）和 CDN 可以显著减轻后端的压力，提升系统的响应速度。缓存机制不仅加快了数据的读写，还减少了数据库的压力。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">技术栈的性能和扩展性</strong>：技术选型中的语言、框架和数据库等技术栈的扩展性直接决定了生产系统的性能瓶颈。例如，选择支持大规模并发请求的技术栈（如 Node.js、Go、Java 中的 Netty 框架等）可以显著提升系统在高负载下的表现。同时，选择可扩展的数据库技术（如 NoSQL 数据库、分布式数据库）可以确保系统在面对海量数据时依然能够快速响应。当确实存在性能问题时，换一种技术栈可能是一种比较彻底的解决问题的思路。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">性能监控与优化</strong>：生产规模的管理离不开实时性能监控。通过监控工具（如Prometheus、Grafana）监控系统的关键性能指标（如CPU、内存、带宽、响应时间等），并通过自动化告警机制及时发现并解决瓶颈问题，确保系统的稳定性和高效性。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">云计算与弹性扩展</strong>：云平台提供的弹性扩展能力是生产规模扩展的重要技术基础。通过云服务（如阿里云、腾讯云、AWS、Azure、Google Cloud）提供的按需扩展资源，生产系统可以根据流量动态调整计算资源、存储资源和网络带宽，确保系统在高并发和高负载下保持稳定。</p>
</section>
</li>
</ul>
<p style="color: #353535;" data-tool="mdnice编辑器">基础设施扩展能力和性能优化及监控直接影响生产系统的弹性和可扩展性。合理的选型能够为生产系统提供未来业务增长所需的技术保障。</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">2.1.3 自动化与运维能力</span></h3>
<p style="color: #353535;" data-tool="mdnice编辑器">生产规模的扩展离不开自动化运维能力的支持。<strong style="color: #f83929;">自动化工具链</strong>（如 CI/CD、自动化测试、基础设施即代码）是保障生产系统在扩展过程中保持高效运作的重要手段。</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">持续集成与持续交付 (CI/CD)</strong> ：在生产环境中，频繁的更新和部署可能会带来较高的风险。通过CI/CD工具链，生产系统的更新、测试和部署可以自动化完成，从而减少人工操作带来的错误和延迟。CI/CD工具确保在生产规模扩展的过程中，系统的更新频率不会影响其稳定运行。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">自动化测试与监控</strong>：在生产规模扩展时，系统的复杂性和负载增加会带来更多的不确定性。通过自动化测试，生产系统可以在每次更新前进行回归测试和性能测试，确保系统在发布新功能时不会出现性能瓶颈或不可预见的错误。同时，通过监控工具（如Prometheus、Grafana），可以实时监控生产系统的性能指标，提前发现并解决潜在的性能问题。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">自动化扩展与容灾能力</strong>：通过基础设施自动化（如 Terraform、Ansible），生产系统在面对突发流量时可以自动扩展资源，并在发生故障时进行自动化恢复。这种技术规模中的自动化能力，是生产系统在高负载或故障环境下能够保持高可用性的关键。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">蓝绿部署和金丝雀发布</strong>：在大规模生产环境下，通过蓝绿部署和金丝雀发布，可以减小新功能或修复补丁上线时的风险，确保在问题发生时能够快速回滚。其实就是灰度发布，或者说要严格地执行灰度发布。</p>
</section>
</li>
</ul>
<p style="color: #353535;" data-tool="mdnice编辑器">自动化能力不仅提高了生产系统的运维效率，还在生产规模扩展时提供了韧性和容错能力。</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">2.1.4 技术债务管理与可维护性</span></h3>
<p style="color: #353535;" data-tool="mdnice编辑器">随着生产规模的扩展，技术债务的管理变得尤为重要。技术债务的管理不当会直接影响生产系统的性能和稳定性。技术规模中的<strong style="color: #f83929;">技术债务管理</strong>策略需要融入生产规模的规划中，以确保系统在扩展过程中不会因为技术债务的积累而出现故障或性能下降。</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">定期重构与优化</strong>：随着系统的不断扩展，代码复杂度和技术债务不可避免地会增加。通过定期的代码重构和性能优化，可以减少技术债务的积累，确保系统在生产环境中的稳定性。例如，定期优化数据库查询或重构基础代码模块，可以避免随着业务增长而出现的性能瓶颈。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">技术债务的监控与清理</strong>：通过技术债务监控工具，团队可以定期评估系统中的技术债务，并规划技术债务的偿还时间。特别是在生产系统扩展时，及时清理技术债务能够大幅减少系统的不可预测性，确保生产系统的可维护性。</p>
</section>
</li>
</ul>
<p style="color: #353535;" data-tool="mdnice编辑器">更多技术债务的内容可以参考之前写的这篇文章：<a style="color: var(--weui-link);" href="http://mp.weixin.qq.com/s?__biz=MzIzNDU2NDA0NA==&amp;mid=2247484160&amp;idx=1&amp;sn=c58c50e6463118afbce6eaaaffb3b836&amp;chksm=e8f533a3df82bab594fac77ca586438dd25146796e4ef7688b276f2d902c8292065eea518428&amp;scene=21#wechat_redirect" target="_blank" data-itemshowtype="0" data-linktype="2"><strong>架构师必备：技术债务的识别、管理与解决之道</strong></a></p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #222222;">2.2 管理开发规模</span></h2>
<p style="color: #353535;" data-tool="mdnice编辑器">开发规模指的是随着项目复杂度、代码库、开发团队人数的增加，如何有效管理开发流程、代码库和团队协作。包括以下几个部分：</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">2.2.1 代码库与模块化管理</span></h3>
<p style="color: #353535;" data-tool="mdnice编辑器">随着项目的规模扩大，代码库的复杂度也随之增加。为了保持代码库的可维护性和可扩展性，合理的技术架构设计和技术栈选型至关重要。</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">模块化与组件化</strong>：模块化设计（例如微服务架构）能帮助团队将系统拆分为多个独立的模块或服务，减少耦合性，并允许团队并行开发。合理的模块化设计不仅可以简化代码管理，还能减少不同团队之间的依赖，提升开发效率。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">技术栈的扩展性</strong>：技术栈的选择对开发规模的扩展至关重要。选用成熟、可扩展的技术栈（如Kubernetes、容器化、云原生技术）可以帮助团队更好地应对复杂的开发需求。技术栈选型不仅影响系统的运行能力，还影响团队的学习曲线、代码质量和开发速度。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">接口设计与抽象</strong>：合理的接口抽象能够减少模块之间的依赖。通过面向接口编程，团队可以在不破坏项目整体架构的情况下，灵活地扩展或替换某些模块。这种设计使得开发团队在面对复杂业务时，能够保持系统的灵活性和可维护性。</p>
</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">2.2.2 开发流程与自动化</span></h3>
<p style="color: #353535;" data-tool="mdnice编辑器">随着团队人数的增加和代码库的扩展，开发流程的复杂性也随之增加。为了提升开发效率，技术规模中的基础设施扩展性和自动化能力是开发流程中的重要组成部分。</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">持续集成与持续交付 (CI/CD)</strong> ：自动化工具链是开发规模扩展中的关键要素。通过自动化测试、构建、部署流程，开发团队能够更频繁地发布代码，减少人为操作的风险。技术规模中的自动化工具（如Jenkins、GitLab CI、CircleCI，各公有云的云效产品）对开发效率的提升至关重要。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">代码评审与规范</strong>：制定统一的代码规范，确保团队成员的代码风格一致，避免“代码腐化”为难以维护的“意大利面条式代码”。通过代码评审（Code Review），团队可以发现潜在问题，提升代码的整体质量和可维护性。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">自动化测试</strong>：技术规模扩展中的自动化程度直接影响开发团队的效率。通过引入单元测试、集成测试、端到端测试，团队可以在不断扩展的代码库中保持代码质量，并快速识别回归错误。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">技术债务管理与重构计划</strong>：随着开发规模的扩大，技术债务的管理变得尤为重要。技术债务的积累会降低开发效率，增加维护成本。因此，定期的技术债务清理和代码重构计划是开发流程管理中的必要步骤。通过技术规模中的架构优化和代码重构，团队可以确保系统在业务增长时依然保持可维护性。</p>
</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">2.2.3 团队协作与知识管理</span></h3>
<p style="color: #353535;" data-tool="mdnice编辑器">开发规模不仅仅依赖于技术架构和工具链的管理，还需要通过良好的协作机制和知识管理确保团队的高效运作。技术规模中的技术栈选型和架构设计也会影响团队的协作方式。</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">知识共享与文档化</strong>：在开发规模扩展的过程中，技术栈的复杂性增加，团队成员需要通过高效的知识管理平台（如Confluence、Notion）来共享与管理技术文档。特别是当团队采用复杂的技术架构时（如微服务或分布式架构），通过文档化来规范开发流程和技术决策，可以减少沟通成本，提升协作效率。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">技术栈选择对协作的影响</strong>：选择合适的技术栈不仅影响系统的技术规模，也会影响团队的协作方式。例如，采用微服务架构可以让不同团队独立开发、部署自己的服务，减少团队之间的依赖。而采用更紧耦合的单体架构则需要更多的沟通与协调。因此，技术栈的选择在开发规模扩展中起到至关重要的作用。</p>
</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">2.2.4 选择合适的开发模型</span></h3>
<p style="color: #353535;" data-tool="mdnice编辑器">开发模型是帮助团队组织开发流程、管理代码质量和发布节奏的框架。在不同的开发规模下，开发模型需要根据技术规模中涉及的技术栈、架构设计和自动化能力进行调整。</p>
<p style="color: #353535;" data-tool="mdnice编辑器">在开发规模扩展的过程中，技术栈和架构设计往往决定了开发模型的选择。例如：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #353535;"><strong style="color: #f83929;">微服务架构与敏捷开发模型</strong>：微服务架构鼓励独立发布和独立开发，因此更适合敏捷开发模式。在这种模式下，技术团队可以迭代地发布小的功能模块，并通过自动化测试和持续集成工具确保代码质量。微服务架构的技术规模管理要求开发模型灵活且高效，以适应快速变化的业务需求。</p>
</section>
</li>
<li>
<section style="color: #353535;"><strong style="color: #f83929;">单体架构与瀑布模型</strong>：对于采用单体架构的系统，开发模型往往倾向于传统的瀑布模型或迭代开发模型。由于单体架构的耦合性较强，系统的发布和开发需要更为慎重，开发模型在这种情况下会更注重前期设计、集成测试和代码审核。</p>
</section>
</li>
</ul>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="color: #ffffff;">3 小结</span></h1>
<p style="color: #353535;" data-tool="mdnice编辑器"><strong style="color: #f83929;">管理规模的扩展不仅仅是对技术的挑战，更是对一个企业工程化与系统化能力的考验</strong>。通过清晰的架构设计、自动化工具的引入、规范化的流程和有效的团队协作机制，企业可以在规模扩张的同时保持研发效能和系统的稳定性。</p>
<p style="color: #353535;" data-tool="mdnice编辑器">这不仅要求架构师从技术角度进行弹性设计，还需要研发管理者从整体角度系统化地规划团队协作和流程优化。<strong style="color: #f83929;">规模扩展的成功，依赖于工具、流程、架构和团队的有机结合与协同运作</strong>。只有通过持续的工程化改进和系统化的管理方法，企业才能在面对规模扩展时从容应对，并建立起长久的竞争优势。</p>
<p style="color: #353535;" data-tool="mdnice编辑器">规模的扩展并不可怕，真正的挑战在于能否通过合理的手段，保证系统和团队在快速变化的环境中依然具备强大而灵活的应对能力。</p>
<p style="color: #353535;" data-tool="mdnice编辑器">正如一座高楼，<strong style="color: #f83929;">只有在扎实的地基之上，才能随风而屹立不倒</strong>。在研发管理的世界里，规模的管理就是那座高楼的地基。通过科学的规模管理，企业不仅能够应对当前的增长，更能够为未来的持续创新打下坚实的基础。</p>
<p style="color: #353535;" data-tool="mdnice编辑器"><strong style="color: #f83929;">最后再次推荐一下 cursor 编辑器，写起来代码来真的很 6。</strong></p>
<p style="color: #353535;" data-tool="mdnice编辑器">以上。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2024/10/scale-management-in-software-development-engineering-and-systematic-approach/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>架构劣化，系统复杂度飙升，如何应对？</title>
		<link>https://www.phppan.com/2024/10/how-to-prevent-architecture-degradation/</link>
		<comments>https://www.phppan.com/2024/10/how-to-prevent-architecture-degradation/#comments</comments>
		<pubDate>Sat, 19 Oct 2024 02:59:40 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[架构]]></category>
		<category><![CDATA[架构师]]></category>
		<category><![CDATA[研发效能]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=2284</guid>
		<description><![CDATA[在构建和演进复杂企业级系统时，架构师常常面临一个令人头痛的现象：架构劣化。 当系统初始设计时一切都井然有序，但 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="color: #000000;" data-tool="mdnice编辑器">在构建和演进复杂企业级系统时，架构师常常面临一个令人头痛的现象：<strong style="color: #0e88eb;">架构劣化</strong>。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">当系统初始设计时一切都井然有序，但随着业务需求的不断增多、新功能的迭代、技术栈的多样化引入，系统开始逐渐变得复杂，模块间的耦合度不断上升，开发者在维护和扩展时难免感到力不从心。系统的可预测性降低，Bug 频发，技术债务迅速累积，甚至每一次小的改动都可能引发意想不到的问题。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">为什么曾经清晰的架构会走向失控？<strong style="color: #0e88eb;">如何在长期的系统演化中，保证架构的灵活性与可维护性，而不让其逐渐腐化？</strong></p>
<p style="color: #000000;" data-tool="mdnice编辑器">这一切都指向了一个关键问题：<strong style="color: #0e88eb;">架构设计中的一致性</strong>。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">正如 Fred Brooks 在《设计原本（The Design of Design）》中所言：「<strong style="color: #0e88eb;">一致性应该是所有质量原则的根基。</strong>」</p>
<p style="color: #000000;" data-tool="mdnice编辑器">今天我们将从<strong style="color: #0e88eb;">风格一致性</strong>、<strong style="color: #0e88eb;">解决方案一致性</strong>、以及<strong style="color: #0e88eb;">形式一致性</strong>三个方面，聊下架构设计中如何实现一致性。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">1 风格一致性：统一的架构模式</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">何谓风格？</strong></p>
<p style="color: #000000;" data-tool="mdnice编辑器">架构风格是构建系统时遵循的一套原则和模式，它为系统的设计提供了抽象框架。风格可以看作是架构中一系列可重复的<strong style="color: #0e88eb;">微观决策</strong>，这些决策在不同上下文中应用，旨在最小化开发者的脑力负担。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">风格具有其属性：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">妥适性</strong>：根据奥卡姆剃刀原理，风格应避免引入不必要的复杂性，满足基本功能即可。这意味着架构设计中应当聚焦于最核心的需求，避免过度设计。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #0e88eb;">普遍性</strong>：风格应该具备广泛适用性，能够通过有限的功能支持多种结果。这种普遍性有助于减少架构中的冗余，提升系统的灵活性。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器">架构风格的一个经典例子是「管道-过滤器」模式。在数据处理系统中，通过一系列过滤器对数据流进行处理，开发者只需理解这种模式的核心思想，即可快速理解系统的其他部分。这种风格的一致性使得系统更加可预测，减少了开发和维护中的复杂性。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">风格的一致性的落地会从架构到系统设计。</strong></p>
<p style="color: #000000;" data-tool="mdnice编辑器">风格一致性要求在设计系统时，所有模块都遵循相同的架构模式。例如，在一个复杂的企业应用中，如果我们选择了领域模型来处理业务逻辑，那么整个系统的其他部分也应遵循这一模式，而不应在某些模块中使用事务脚本。这种不一致会导致开发者陷入不同模式的转换中，增加理解和维护的成本。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">风格一致性的核心在于<strong style="color: #0e88eb;">正交性原则</strong>，即各个模块应独立处理自己的职责，减少彼此间的耦合。通过保持架构风格的一致性，系统可以更好地实现模块化和松耦合，这不仅有助于当前的开发，还为未来的扩展打下了基础。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">需要注意的是，架构风格并非一成不变。随着技术的发展和业务需求的变化，架构风格也会不断演化。因此，架构师应当通过<strong style="color: #0e88eb;">文档化</strong>的方式，确保风格的一致性能够在团队内传播和延续。文档不仅是风格的记录，更是团队成员在开发过程中保持一致的指南。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2 解决方案一致性：统一的实现方式</span></h1>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2.1 为什么解决方案需要一致？</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">风格一致性更多体现在宏观的架构层面，而<strong style="color: #0e88eb;">解决方案一致性</strong>则体现在系统具体实现的细节中。解决方案的一致性要求在同一系统中，开发者应使用相同的技术栈、设计模式和实现方式，以避免由于不同方案混用而导致的系统复杂性。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">举例来说，假设在一个大型系统中，某些模块使用了<strong style="color: #0e88eb;">Node.js</strong>和<strong style="color: #0e88eb;">Express</strong>作为后端技术栈，而其他模块则使用了<strong style="color: #0e88eb;">Java</strong>和<strong style="color: #0e88eb;">Spring Boot</strong>。这种不一致的解决方案会导致以下问题：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">开发效率低下</strong>：Node.js 和 Java 的编程范式截然不同，前者是 JavaScript 的异步、事件驱动模型，后者则是 Java 的多线程模型。开发者在不同模块之间切换时，需要调整思维方式和适应不同的编程风格。这种上下文切换会降低开发效率，尤其是在跨模块协作时。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">技术债务增加</strong>：两种技术栈在依赖管理、错误处理、性能调优等方面有着不同的最佳实践。团队需要为每个技术栈制定不同的管理策略，这可能导致技术债务的积累。例如，Node.js 的异步编程需要处理回调或 Promise 链，而 Java 则更多依赖传统的 try-catch 机制。如果开发团队未能统一错误处理方式，后续的维护工作将变得更加复杂。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">测试和部署复杂化</strong>：不同技术栈会导致不同的测试和部署工具链。例如，Node.js 项目可能使用 <strong style="color: #0e88eb;">Jest</strong> 或 <strong style="color: #0e88eb;">Mocha</strong> 进行测试，而 Java 项目则依赖 <strong style="color: #0e88eb;">JUnit</strong> 或 <strong style="color: #0e88eb;">TestNG</strong>。在部署阶段，Node.js 通常使用 <strong style="color: #0e88eb;">npm</strong> 来管理依赖并构建项目，而 Java 则依赖 <strong style="color: #0e88eb;">Maven</strong> 或 <strong style="color: #0e88eb;">Gradle</strong>。这意味着，CI/CD 流水线需要针对不同的模块配置不同的工具链，增加了自动化部署的复杂性。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">团队协作障碍</strong>：团队中的开发者可能对某一种技术栈更加熟悉。如果团队成员分工不明确，或者需要在不同技术栈的模块间协作时，可能会遇到技能鸿沟。例如，擅长 Java 的开发者在接手 Node.js 代码时可能不熟悉 JavaScript 的异步处理方式，导致 Bug 频发或进度延迟。反之亦然。</p>
</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器">相反，通过保持解决方案的一致性——例如，统一选择使用<strong style="color: #0e88eb;">Java + Spring Boot</strong>或<strong style="color: #0e88eb;">Node.js + Express</strong>作为后端技术栈——可以确保团队在开发、测试和部署的各个阶段都能使用一致的工具和框架。这样不仅降低了学习成本和上下文切换的负担，还使得团队在协作时更具一致性。测试和部署流程也可以标准化，开发者能够更加专注于核心业务逻辑的实现，从而提高整体开发效率和系统的可维护性。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2.2 如何实现解决方案一致性？</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">为了实现<strong style="color: #0e88eb;">解决方案一致性</strong>，我们需要采取一系列技术和管理上的措施，确保团队在开发过程中能够遵循统一的标准和原则。以下是我们在实际工作中常用的一些的策略和实践：</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">2.2.1 建立统一的架构原则和技术规范</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">在项目启动或架构设计的早期，架构师或技术负责人需要制定明确的<strong style="color: #0e88eb;">架构原则</strong>和<strong style="color: #0e88eb;">技术规范</strong>，并确保团队中的所有成员都理解并遵守这些规范。具体措施包括：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">制定技术选型指南</strong>：明确系统中使用的核心技术栈（如数据库访问技术、缓存管理、消息传递机制等）。例如，团队可以决定在整个项目中统一使用Spring Data JPA作为ORM解决方案，而不允许直接使用原生SQL或其他ORM框架。这种技术选型需要根据系统的需求和团队的技能水平做出合理的决策。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">定义设计模式的应用场景</strong>：对于常见的问题，架构师应当指定适当的设计模式。例如，规定在服务层使用策略模式（Strategy Pattern）来处理不同的业务逻辑，而不是让开发者随意选择不同的模式或技术实现。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">确定编程规范与代码风格</strong>：统一的代码风格不仅能提高代码的可读性，还能增强代码的一致性。通过制定编码规范（如命名规则、注释风格、格式化规则等），并在代码中使用一致的编程风格，可以避免因风格差异导致的困惑和误解。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">文档化架构决策</strong>：对于每一个重要的架构和技术决策，都要形成文档。这份文档不仅是为了当前的团队成员，也是为了以后加入的开发者能够快速了解并遵循既定的架构规范。</p>
</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">2.2.2 使用代码模板和生成工具</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">代码模板和生成工具可以帮助团队在技术实现上保持一致性。通过提供预先定义好的代码模板，开发者可以快速生成符合架构规范的代码，避免了手动编写过程中出现的风格不一致问题。具体措施包括：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">使用框架提供的代码生成工具</strong>：如 beego 框架的  bee generate 。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">创建内部代码模板</strong>：团队可以根据项目的实际需求，创建一系列内部的代码模板。这些模板可能包括控制器、服务层、数据访问层的标准实现，确保每个模块的代码结构一致。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">自动化配置管理</strong>：对于基础设施的配置（如数据库连接、日志管理、安全配置等），可以使用框架中的自动化工具或约定优于配置原则，减少开发者手动调整配置的需求，从而保证一致性。</p>
</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">2.2.3 落实 Code Review</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">Code Review 是确保解决方案一致性的有效手段之一。通过固定的代码审查机制，以及定期的代码评审，团队可以及时发现并纠正不一致的实现方式，确保整个系统遵循统一的设计和技术规范。具体措施包括：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">建立严格的代码审查流程</strong>：每个开发者在提交代码前，必须经过团队的代码审查。审查的重点除了代码质量之外，还应包括检查代码是否符合项目的架构规范、是否使用了统一的技术栈和设计模式。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">引入静态代码分析工具</strong>：使用静态代码分析工具（如SonarQube、Checkstyle等）可以自动检测代码中的不一致问题，包括代码风格、架构违规、潜在的错误等。这种工具能够根据预先定义的规则对代码进行检查，并在问题出现时发出警告，帮助开发者在早期修复问题。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">定期的架构评审</strong>：架构评审是对整个系统架构设计及实现进行统一检查的活动。在架构评审中，团队可以讨论当前的架构是否依然适用，是否有新的技术或模式需要引入，以及现有的解决方案是否一致。通过架构评审，还可以确保整个系统的技术决策继续符合既定的架构原则。</p>
</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">2.2.4 保持团队的沟通与协作</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">解决方案一致性不仅仅依赖于技术选型和工具，它也需要团队成员之间的高效沟通和协作。团队中的每个人都应该理解和认同一致性原则，并遵循这些原则进行开发。具体措施包括：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">定期技术分享与培训</strong>：为了确保所有开发人员对系统的架构和技术栈有深入理解，团队可以定期组织技术分享会或培训，帮助开发者熟悉统一的解决方案和设计模式。例如，可以安排关于如何正确使用Spring Data JPA的培训，确保每个开发者都能使用该技术栈的一致实现方式。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">建立架构讨论机制</strong>：在遇到复杂的技术问题或不确定的实现方式时，开发者应及时与架构师或其他团队成员进行讨论，而不应各自为战。这种持续的沟通有助于避免不一致的解决方案和技术决策。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">跨团队协作</strong>：在大型项目中，可能会有多个团队同时开发不同模块。在这种情况下，跨团队的技术交流和协作至关重要。团队间的定期同步会议、共享架构文档和技术决策，都有助于确保各个团队在技术实现上的一致性。</p>
</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">2.2.5 标准化的工具链与 CI/CD 流程</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">工具链和自动化流程的标准化是实现解决方案一致性的另一个关键因素。通过使用相同的开发工具、CI/CD 流程和部署工具，团队可以在从开发到发布的各个环节保持一致性。具体措施包括：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">统一的开发环境</strong>：为所有开发者提供标准化的开发环境。例如，通过 Docker 容器提供统一的开发环境，确保每个开发者在本地的开发环境与生产环境一致，从而避免由于不同环境配置导致的实现差异。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">标准化的CI/CD流程</strong>：在 CI 和 CD 中，使用统一的流水线和自动化测试，确保每次代码提交都经过相同的测试和质量检查流程。例如，可以在 CI 管道中集成代码质量检查、单元测试和集成测试工具，确保每个模块都通过相同的验证过程，避免出现质量参差不齐的代码。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">统一的发布和部署策略</strong>：通过标准化的部署工具（如Kubernetes、Docker Compose等）和配置管理工具（如Ansible、Terraform等），确保系统在不同环境中的部署过程一致，这样可以避免因不同的部署方式导致的运行时错误和不兼容问题。</p>
</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e88eb;">2.2.6 逐步消除遗留系统中的不一致</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器">在大型项目中，遗留系统中往往会存在解决方案不一致的情况。为了实现解决方案一致性，团队需要有计划地逐步消除这些不一致的问题。具体措施包括：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">逐步替换不一致的技术栈</strong>：对于遗留的模块，如果存在与当前技术栈不一致的实现方式，可以通过重构或替换的方式，将不一致的部分替换掉。例如，将原先使用的手写 SQL 查询逐步替换为统一的ORM框架。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">分阶段的技术债务清理</strong>：技术债务的积累往往是导致解决方案不一致的主要原因之一。团队应定期对系统中的技术债务进行评估，并分阶段清理那些导致解决方案不一致的部分。通过持续的技术债务清理，确保系统在长期演进中保持一致性和可维护性。</p>
</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">解决方案一致性</strong>是软件系统成功的关键之一，它不仅可以降低系统的复杂性，还能提升团队的协作效率和系统的可维护性。通过制定明确的架构原则、使用统一的技术栈、引入代码审查机制、保持团队的沟通协作，以及标准化工具链和 CI/CD 流程，团队可以有效地实现解决方案的一致性。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">在一个长期演进的系统中，解决方案的一致性有助于减少技术债务，避免「架构腐化」，让系统在面对不断变化的需求时依然保持灵活性和可扩展性。通过这些实践，团队能够构建出更加可靠、易于维护的系统，并为未来的扩展提供坚实的基础。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3 形式一致性</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">形式一致性</strong>是指系统设计中各个部分的结构、风格、和实现方式在形式上保持统一和协调。它不仅仅体现在代码的外观和风格上，还包括系统在设计原则、接口定义、组件交互方式等方面的统一性。形式一致性确保了系统的各个模块之间能够无缝协作，减少了理解和维护的困难，并使得系统更加易于扩展和演进。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">形式一致性要求设计者在系统的各个层次上都遵循同样的简约和清晰原则，确保每个模块的设计具有相同的模式和风格。例如，系统中所有 API 的命名规则、参数传递方式和返回结构都应保持一致，这样开发者只需学习一次，便能理解和使用所有接口。在前端设计时，所有的用户界面组件应遵循统一的界面规范和交互逻辑，以确保用户在不同模块之间切换时能够获得相同的用户体验。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3.1 简约</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">在形式一致性中，<strong style="color: #0e88eb;">简约</strong>意味着设计需要尽可能地去除冗余，确保每个组件都是必要的、功能明确的。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">简约不仅意味着少量的代码或元素，还意味着减少不必要的复杂性。通过使用更少的元素来完成更多的功能，简约的设计不仅减少了开发和维护的成本，还提升了系统的可预测性和稳定性。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">在简约的系统中，开发者能够快速理解每个模块的设计意图，并能够在不增加复杂性的前提下对系统进行扩展。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3.2 结构清晰</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">结构清晰</strong>是形式一致性的重要组成部分。它要求系统的设计逻辑应该是直截了当的，模块的职责和功能应该易于理解。每个模块都应具备独立的功能，且模块间的依赖关系应当保持最小化。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">结构清晰的系统不仅让开发者能够快速掌握系统的整体架构，还能轻松推测出其他模块的设计方式。在一个结构清晰的系统中，开发者不必反复查阅文档或进行复杂的调试，因为模块的设计和交互逻辑都是一致且直观的。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">如在一个微服务架构中，假设我们有一个用户管理服务和订单服务。为了保持结构清晰，这两个服务应该各自负责单一的职责：用户管理服务处理用户注册、登录、个人信息管理等，订单服务则负责订单的创建、支付以及状态管理。这两个服务之间通过 API 进行通信，并且彼此独立，避免了不必要的耦合。如果将用户信息直接嵌入到订单服务中，会导致结构复杂化，增加了理解和维护的难度。通过保持清晰的模块划分，开发者可以很容易地理解每个服务的职责，并在系统发生变化时轻松进行调整。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3.3 隐喻</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">隐喻</strong>是系统设计中提升可理解性的重要工具。通过使用简单易懂、与现实世界或常见概念相类比的隐喻，开发者能够更快速地理解系统的设计意图。隐喻的使用不仅让系统的架构更具亲和力，还减少了开发者的认知负担。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">在形式一致性中，隐喻的应用应当贯穿整个系统——无论是从命名到设计模式，还是从接口定义到用户交互，都应当遵循同样的隐喻理念。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">如在构建文件系统时，使用「文件和文件夹」的隐喻可以帮助开发者和用户更好地理解系统的组织结构。现实生活中，人们处理物理文件和文件夹的经验非常直观——文件夹用于存放文件，文件可以被打开、编辑、删除或移动。将这种现实生活中的概念引入到计算机系统中，使用户和开发者能够迅速理解系统的操作模型。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">通过这种隐喻，用户不需要理解系统背后的复杂实现逻辑，就能够基于现实世界中的经验快速掌握系统的使用方式。同时，开发者在设计时也能够遵循这一隐喻，确保系统结构和操作符合人们的认知习惯，提升了系统的可用性和可维护性。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4 小结</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">系统架构设计的本质在于持续演进，而一致性则是这种演进过程中不可或缺的基石。</strong></p>
<p style="color: #000000;" data-tool="mdnice编辑器">风格、解决方案、形式上的一致性不仅能够<strong style="color: #0e88eb;">减少开发者的认知负担</strong>，还能为系统的扩展和维护提供有力的支持。一个具有一致性的系统，往往更具可预测性、更易于理解，并且能够在面对复杂的业务需求和技术变革时保持灵活性与稳健性。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">正如 Fred Brooks 所言，一致性不仅是质量的根基，也是系统能够在复杂环境中持续演进的保证。通过在架构设计中贯彻一致性原则，我们不仅在解决当前的问题，更是在为未来的变革与创新铺平道路。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">
<p style="color: #000000;" data-tool="mdnice编辑器">以上。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2024/10/how-to-prevent-architecture-degradation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>聊下 SaaS 初创企业的安全策略</title>
		<link>https://www.phppan.com/2024/08/talk-about-security-strategies-for-saas-startups/</link>
		<comments>https://www.phppan.com/2024/08/talk-about-security-strategies-for-saas-startups/#comments</comments>
		<pubDate>Fri, 30 Aug 2024 23:52:54 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[SaaS]]></category>
		<category><![CDATA[创业]]></category>
		<category><![CDATA[安全]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=2271</guid>
		<description><![CDATA[在这个数字化高度依赖的时代，安全不仅仅是一种防御手段，更是一种核心竞争力。对于 SaaS 初创企业而言，安全策 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="color: #000000;" data-tool="mdnice编辑器">在这个数字化高度依赖的时代，安全不仅仅是一种防御手段，更是一种核心竞争力。对于 SaaS 初创企业而言，安全策略的构建如同奠定企业发展的基石，决定着未来的稳定与可持续性。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">在开始构建基于云服务的 SaaS 平台时，如何在前期制定全面而有效的安全策略，将直接影响公司能否在激烈的市场竞争中立于不败之地。任何忽视安全的行为，都会为企业未来的成长埋下隐患。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">今天我们要聊的安全仅仅是狭义上的安全，包括外部的攻击，以及企业内部管理不规范或误操作导致的安全问题等。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">SaaS 初创业企业的安全策略包括外部安全和内部安全两大方面。每个方面都是针对特定的安全问题而梳理的，都会有对应的解法。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">1 外部安全</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">外部安全主要涉及防范来自外部的威胁，如网络攻击、中间人攻击、数据泄露等。以下是关键领域及其应对策略：</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #ffffff;">1.1 网络安全</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>安全问题</strong>：网络安全是外部安全的核心，涉及防护企业网络免受各种外部威胁的攻击。常见的网络威胁包括 DDoS 攻击、SQL 注入、中间人攻击等。这些攻击可能导致服务中断、数据泄露，甚至系统被完全控制。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>解决方案</strong>：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">防火墙与 DDoS 防护</strong>：部署多层防火墙，包括应用层和网络层防火墙，以过滤恶意流量。通过云服务提供商（如阿里云、腾讯云、AWS）的 DDoS 防护服务，可以自动检测并缓解大规模流量攻击。<strong style="color: #000000;">早期考虑先上一波动态 CDN</strong>。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">加密通信</strong>：强制使用 HTTPS（TLS/SSL） 来加密数据在传输过程中的安全性。确保所有的 API 接口和 Web 应用都使用强加密协议，防止数据在传输过程中的窃听和篡改。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">入侵检测与防御</strong>：部署入侵检测系统（IDS）和入侵防御系统（IPS），实时监控网络流量，识别并阻止可疑活动。IDS/IPS可以帮助发现并响应攻击者的尝试，避免其进一步渗透。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>注意事项</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">定期审查防火墙规则和策略，确保其适应最新的安全需求。</section>
</li>
<li>
<section style="color: #010101;">确保TLS/SSL证书的有效性，并及时更新证书，防止过期导致的安全风险。</section>
</li>
<li>
<section style="color: #010101;">入侵检测系统的规则库需要定期更新，以应对新出现的攻击手段。</section>
</li>
</ul>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #ffffff;">1.2 应用安全</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>安全问题</strong>：SaaS 应用程序是客户与服务的直接交互层，应用层的安全问题（如 SQL 注入、跨站脚本攻击 XSS ）可能被利用来进行未授权的操作或数据泄露。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>解决方案</strong>：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">定期代码审计</strong>：使用静态代码分析工具（如SonarQube）和动态应用安全测试（DAST）工具，定期对代码进行审查，发现并修复潜在的安全漏洞。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">安全编码实践</strong>：遵循 OWASP 提供的安全编码标准，防止常见的应用层攻击，如 SQL 注入、XSS、CSRF 等。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">Web 应用防火墙（WAF）</strong>：部署 WAF 来检测并阻止恶意的 HTTP 流量。<strong style="color: #000000;">常见的应用攻击以及一些爬虫的防御策略都可以在 WAF 中落地</strong>，在云服务产品中有点小贵。</section>
</li>
</ul>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #ffffff;">1.3 数据安全</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器">数据安全是 SaaS 初创企业保护其核心资产的关键领域之一。无论是存储、传输、处理还是备份，数据安全问题都可能导致严重的业务中断、数据泄露，以及客户信任的丧失。</p>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">1.3.1 数据存储与访问控制</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>安全问题</strong>： 数据存储和访问控制是数据安全的基础。如果存储的数据未加密或访问控制不当，攻击者可能通过各种方式获取敏感数据。<strong>未授权的访问、数据泄露、或越权操作</strong>可能导致严重的安全和合规性问题。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>解决方案</strong>：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">数据加密</strong>：在存储数据时，使用强加密算法（如AES-256）对<strong style="color: #000000;">敏感数据</strong>进行加密。无论是数据库、文件存储还是备份数据，都应确保其在静态状态下（即存储时）是加密的。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">访问控制</strong>：实施基于角色的访问控制（RBAC），确保只有授权用户可以访问特定的数据。使用最小权限原则，限制用户对数据的访问权限，防止越权操作。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">多因素认证（MFA）</strong>：在访问敏感数据时，强制使用多因素认证，增加额外的安全层，防止因凭证泄露导致的数据泄露。在各家云服务厂商 MFA 已经在普遍应用了。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">数据隔离</strong>：根据用户或应用的不同需求，实施数据隔离策略，确保不同的数据集之间没有不必要的访问路径，防止数据被滥用或误用。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>注意事项</strong>：</p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">定期审查权限</strong>：定期审查和更新用户权限，<strong style="color: #000000;">尤其是在员工角色变更或离职时</strong>，确保权限及时调整或撤销，防止滥用。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">加密密钥管理</strong>：妥善管理加密密钥，防止其泄露或丢失。采用 KMS 来管理密钥生命周期。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志审计</strong>：启用详细的访问日志，审计所有的数据访问和操作记录，并定期分析日志以发现潜在的安全问题。</section>
</li>
</ul>
<h3 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">1.3.2 数据备份与恢复</span></h3>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>安全问题</strong>：数据备份是确保在数据丢失或损坏时能够恢复的关键措施。然而，如果备份策略不完善或备份存储位置不安全，备份数据本身可能成为攻击者的目标，导致数据泄露或业务中断。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>解决方案</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">备份策略</strong>：制定合理的备份策略，确保关键数据定期备份。使用增量备份和全量备份相结合的方式，平衡存储空间和恢复时间。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">多重备份存储</strong>：将备份数据存储在多个物理位置或云服务中，防止单点故障。可以使用云端备份解决方案（如阿里云、腾讯云的备份服务）结合本地存储进行多重备份。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">备份恢复演练</strong>：定期进行数据恢复演练，确保备份数据在紧急情况下能够快速恢复，验证备份的可用性和恢复时间。上次语雀故障恢复时长超出预期的一个核心原因就是备份恢复的数据问题。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>注意事项</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">备份保留策略</strong>：合理设置备份保留时间，确保数据的历史版本可以在特定时间内恢复，但不至于占用过多存储空间。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">备份访问控制</strong>：加强对备份存储位置的访问控制，防止未经授权的访问或下载。确保只有必要的人员和系统能够访问备份数据。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">备份日志审计</strong>：记录备份和恢复操作日志，定期审查日志以确保备份操作的合规性和安全性，发现并处理任何异常行为。</section>
</li>
</ul>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">2 内部安全</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">内部安全主要关注内部人员或系统的安全问题，包括账号被盗用、权限管理不当，越权访问、删库跑路等等。这些问题如果处理不当，可能导致敏感数据泄露、业务中断，甚至让公司关门。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">在内部安全中，主机安全、数据安全、代码安全、日志安全和第三方系统安全是保护企业内部系统和数据的关键领域。每个领域都有其独特的安全挑战，需要通过制定和实施有效的策略来应对。</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #ffffff;">2.1 主机安全</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>安全问题</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">未授权访问</strong>：如果对主机的访问控制不严，内部用户或攻击者可能获得未授权的访问权限，导致系统被滥用或破坏。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">操作系统漏洞</strong>：主机上的操作系统和服务可能存在未修补的漏洞，这些漏洞可能被攻击者利用来获取控制权或窃取数据。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">缺乏监控和审计</strong>：如果缺乏对主机操作的实时监控和日志审计，恶意活动可能无法被及时发现和阻止。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>解决方案</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">统一账号管理</strong>：使用集中式的身份和访问管理（IAM）系统，统一管理主机的访问权限，确保只有授权用户能够访问关键主机。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">定期更新与补丁管理</strong>：确保操作系统和应用程序定期更新，及时应用所有安全补丁以修复已知漏洞。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">使用堡垒机</strong>：通过堡垒机来集中管理对所有主机的访问，所有操作通过堡垒机进行，并记录详细日志，确保操作的可追溯性。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志审计</strong>：启用并配置详细的操作日志审计系统，定期审查日志，发现并响应异常行为。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>注意事项</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">权限最小化</strong>：严格遵循最小权限原则，确保用户只能访问他们完成工作所需的资源。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">监控与报警</strong>：配置实时监控和报警系统，及时通知管理员任何异常活动，如未经授权的登录尝试或关键服务的异常行为。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志保护</strong>：确保日志文件的完整性，防止日志记录被篡改或删除，以维护操作活动的可追溯性。</section>
</li>
</ul>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #ffffff;">2.2 数据安全</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>安全问题</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">越权访问</strong>：后台管理系统如果权限控制不严，可能导致用户访问到不应有的数据或功能，引发数据泄露或误操作。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">数据泄露</strong>：如果后台系统处理的数据未经加密或脱敏，敏感信息可能被内部人员或攻击者窃取。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">操作审计不足</strong>：缺乏对后台管理系统操作的审计和监控，可能导致恶意或错误操作未被及时发现。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>解决方案</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">基于角色的访问控制</strong>：在后台管理系统中实施 RBAC，确保不同角色只能访问与其职责相关的数据和功能，防止越权操作。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">数据脱敏与加密</strong>：对后台系统中处理的敏感数据进行加密，并在展示或导出时进行脱敏处理，确保敏感信息不被泄露。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">操作日志记录</strong>：记录所有后台管理系统的操作日志，特别是涉及数据访问、修改和删除的操作，确保所有活动可追溯。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>注意事项</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">定期权限审查</strong>：定期审查和更新后台系统的用户权限，防止权限滥用或遗留的过期权限。这在实际工作中经常会遇到，因为开放了权限了后面基本就不管了，至少在权限管理上增加一个时间的限制。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">异常操作监控</strong>：配置实时监控，识别和报警异常操作，如大规模数据导出或频繁的权限变更。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志保护与分析</strong>：确保操作日志的完整性和安全性，定期分析日志以发现潜在的安全威胁。</section>
</li>
</ul>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #ffffff;">2.3 代码安全</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>安全问题</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">代码漏洞</strong>：不安全的编码实践可能导致代码中存在安全漏洞，如 SQL 注入、XSS、CSRF 等，攻击者可以利用这些漏洞入侵系统或窃取数据。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">代码泄露</strong>：如果代码管理不当，源代码可能泄露，攻击者可以分析代码并发现潜在的安全漏洞。甚至整个代码被竞争对手拿走分析。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">代码变更未经审核</strong>：未经审核的代码变更可能引入新的漏洞或破坏现有的安全控制，增加系统的安全风险。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>解决方案</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">安全编码规范</strong>：制定并强制执行安全编码规范，确保开发人员遵循最佳安全实践，如输入验证、输出编码等。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">代码审查与静态分析</strong>：在代码提交前进行代码审查，并使用静态代码分析工具（如 SonarQube ）自动检测潜在的安全漏洞。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">版本控制与权限管理</strong>：使用版本控制系统（如Git）管理代码，并严格控制代码库的访问权限，确保只有授权人员能够查看和修改代码。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">持续集成与安全测试</strong>：在持续集成（CI）过程中引入安全测试，自动化发现和修复代码中的安全问题。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>注意事项</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">定期安全培训</strong>：定期对开发人员进行安全培训，提升其安全意识和能力，防止常见的编码错误。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">敏感信息保护</strong>：确保代码库中不包含敏感信息，如硬编码的密码或API密钥，使用安全的方式管理这些信息。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">变更管理</strong>：所有代码变更必须经过严格的审核流程，确保新代码不会引入安全问题，并记录变更日志以备审计。</section>
</li>
</ul>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #ffffff;">2.4 日志安全</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>安全问题</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志数据泄露</strong>：如果日志包含未脱敏的敏感信息，攻击者可能通过获取日志文件来窃取这些信息。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志篡改</strong>：攻击者可能篡改或删除日志记录，掩盖其恶意行为，使得调查和取证变得困难。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志存储不足</strong>：日志存储不当或容量不足可能导致日志丢失，影响问题的追溯和分析。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>解决方案</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志脱敏与加密</strong>：在生成日志时对包含敏感信息的字段进行脱敏处理，并对日志文件进行加密存储，防止信息泄露。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">集中化日志管理</strong>：使用集中化的日志管理工具（如ELK Stack）来统一收集、存储和分析日志，确保日志的完整性和可用性。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志完整性校验</strong>：使用哈希校验或数字签名保护日志文件，防止日志被篡改，确保日志记录的真实性和完整性。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>注意事项</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志保留策略</strong>：制定合理的日志保留策略，确保重要日志能够长期存储，以满足合规和审计要求。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">访问控制</strong>：严格限制对日志文件的访问权限，确保只有授权人员能够查看和分析日志。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">日志监控与报警</strong>：实时监控日志中的异常行为，设置自动报警机制，及时发现并响应潜在的安全事件。</section>
</li>
</ul>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #ffffff;">2.5 第三方系统安全</span></h2>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>安全问题</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">第三方系统漏洞</strong>：如果企业依赖的第三方系统存在安全漏洞，这些漏洞可能被攻击者利用，危及企业的整体安全。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">第三方系统配置不当</strong>：错误的配置或使用默认配置可能导致第三方系统暴露在外部攻击者面前。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">集成安全风险</strong>：与第三方系统的集成可能引入新的安全风险，尤其是在数据共享和权限管理方面。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>解决方案</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">定期安全评估</strong>：定期对第三方系统进行安全评估，识别并修复潜在的安全漏洞。确保所有第三方系统保持最新版本，及时应用安全补丁。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">安全配置管理</strong>：根据最佳实践配置第三方系统，禁用默认账户和配置，使用强密码和加密通信，确保系统的安全性。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">集成安全控制</strong>：在与第三方系统集成时，实施严格的安全控制措施，如API访问控制、数据加密和请求验证，防止集成过程中出现安全问题。</section>
</li>
</ul>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>注意事项</strong></p>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;"><strong style="color: #000000;">供应商管理</strong>：选择信誉良好的第三方供应商，并定期审查其安全实践，确保其符合企业的安全要求。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">合同与责任划分</strong>：在与第三方签订合同时，明确各方的安全责任和应对措施，确保在出现安全问题时能够明确责任。</section>
</li>
<li>
<section style="color: #010101;"><strong style="color: #000000;">持续监控</strong>：对第三方系统的运行状态和安全日志进行持续监控，及时发现和响应潜在的安全事件。</section>
</li>
</ul>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold;">小结</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">通过从外部安全和内部安全两个视角来审视 SaaS 类初创企业的安全策略，可以更全面地识别和应对各类安全风险。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong>外部安全侧重于防范来自外部攻击者的威胁</strong>，如网络攻击、应用漏洞利用等；<strong>内部安全则关注内部用户、流程和系统可能引发的安全问题</strong>，如权限管理、员工安全意识等。只有同时重视外部安全和内部安全，并采取相应的防护措施，才能为 SaaS 企业构建一个全方位的安全防御体系。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">安全并非一蹴而就，而是一个持续演进的过程。无论是外部威胁的防范还是内部安全的管理，都需要保持高度的敏感性和前瞻性。SaaS 企业的成功不仅仅依赖于技术创新，更依赖于对安全的承诺与执行力。唯有将安全视作企业文化的一部分，融入到每一步的决策与行动中，才能在风云变幻的市场中行稳致远，真正建立起客户信任的堡垒。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2024/08/talk-about-security-strategies-for-saas-startups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>初创企业的前后端分离架构落地策略</title>
		<link>https://www.phppan.com/2024/08/implementation-strategy-of-front-end-and-back-end-separation-architecture-for-startups/</link>
		<comments>https://www.phppan.com/2024/08/implementation-strategy-of-front-end-and-back-end-separation-architecture-for-startups/#comments</comments>
		<pubDate>Sat, 10 Aug 2024 05:15:11 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[前后端分离架构]]></category>
		<category><![CDATA[技术架构]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=2264</guid>
		<description><![CDATA[前后端分离架构是一种现代Web应用程序的架构模式，其核心逻辑是将应用程序的前端(用户界面)和后端(业务逻辑和数 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p style="color: #000000;" data-tool="mdnice编辑器">前后端分离架构是一种现代Web应用程序的架构模式，其核心逻辑是将应用程序的前端(用户界面)和后端(业务逻辑和数据访问)分离开来，使它们成为独立的部分。前端和后端通过API进行通信，彼此独立开发、测试和部署。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">前端负责用户界面的呈现和交互，通过 HTML、CSS和 JavaScript 等实现。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">后端负责业务逻辑的处理、数据的存储和检索，提供 API 接口供前端调用。前端和后端通过 HTTP 协议进行通信，传输数据通常使用 JSON 格式。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">1 前后端架构的演化过程</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">前后端分离架构并不是直接出现的，它是随着技术的发展慢慢演化而来的，大概分为如下几个阶段。</p>
<ol class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">早期的 Web 应用( 20 世纪 90 年代)</strong> ：在 Web 应用程序的早期阶段，前后端是紧密耦合的。服务器端使用模板引擎(如 PHP、JS P)生成完整的 HTML 页面，前端主要使用 HTML、CSS 和少量的 JavaScript，与后端混合在一起。这种架构模式简单直接，但灵活性和可维护性较差。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">Ajax 的出现( 2005 年)</strong> ：Ajax(Asynchronous JavaScript and XML)的出现，标志着前后端分离的开始。通过 Ajax，前端可以在不刷新页面的情况下与服务器进行异步通信，实现局部内容的更新。这种技术使得前端能够更加动态和交互，但前后端的耦合度仍然较高。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">RESTful API 的兴起( 2000 年代中期)</strong> ：随着 Roy Fielding 提出REST(Representational State Transfer)架构风格，RESTful API 开始流行起来。RESTful API 使用HTTP方法(GET、POST、PUT、DELETE)对应 CRUD 操作，提供了一种标准化的前后端通信方式。前端通过 Ajax 请求访问后端提供的 RESTful API，实现数据的读写。这种架构模式使得前后端的职责更加清晰，提高了可扩展性和可维护性。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">单页应用(SPA)的崛起( 2010 年前后)</strong> ：伴随着 JavaScript 框架(如 Backbone.js、AngularJS)的出现，单页应用(SPA)开始流行。SPA 将应用程序的逻辑和路由转移到前端，通过 Ajax 与后端 API 进行数据交互。这种架构模式使得前端能够提供更加流畅的用户体验，但也对前端开发提出了更高的要求。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">现代前端框架的兴起( 2013 年至今)</strong> ：React、Vue、Angular 等现代前端框架的出现，进一步推动了前后端分离架构的发展。这些框架提供了组件化开发、声明式UI、虚拟DOM等特性，使得前端开发更加高效和可维护。前端框架与后端API的紧密配合，成为构建现代Web应用程序的主流方式。</p>
</section>
</li>
</ol>
<p style="color: #000000;" data-tool="mdnice编辑器">除了以上的 5 个关键的技术发展外，还有一些技术也促进了前后端分离架构的演化：</p>
<ol class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">Node.js 的崛起和全栈 JavaScript(2009年至今)</strong> ：Node.js 的出现使得 JavaScript 可以在服务器端运行，催生了全栈 JavaScript 的开发模式。使用 Node.js 构建后端服务，与前端的 JavaScript 框架无缝衔接，形成了完整的 JavaScript 技术栈。这种前后端都使用 JavaScript 的开发模式，进一步促进了前后端分离和全栈开发。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">GraphQL 的兴起( 2015 年至今)</strong> ：Facebook 推出了 GraphQL 作为一种新的 API 查询语言和规范。GraphQL 提供了更灵活、高效的数据查询和聚合能力，成为 RESTful API 的有力补充。前端可以使用 GraphQL 精确地请求所需的数据，减少了数据的冗余和请求次数，提高了开发效率和性能。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">Serverless 和 BaaS 的兴起( 2015 年至今)</strong> ：Serverless(无服务器)架构和 Backend as a Service(BaaS) 的兴起，进一步推动了前后端分离的发展。前端可以直接调用云服务提供的 API 和功能，无需关心服务器和基础设施的管理。这种架构模式使得前端开发更加专注于用户界面和交互，后端服务由云平台提供，提高了开发效率和可扩展性。</p>
</section>
</li>
</ol>
<p style="color: #000000;" data-tool="mdnice编辑器">前后端分离架构的演变是 Web 技术不断发展的结果。从早期的前后端混合，到 Ajax 的出现，再到 RESTful API、现代前端框架和 Serverless 架构，每一次技术的突破都推动了前后端分离的发展。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">如今，前后端分离已成为构建现代 Web 应用程序的主流架构模式，为开发者提供了更大的灵活性、可维护性和可扩展性。</p>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">2 前后端分离架构的优势和劣势</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">前后端分离架构的优势</p>
<ol class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">开发效率提高</strong>：前后端分离允许前端和后端团队并行开发，互不干扰，大大提高了开发效率。<strong style="color: #0e88eb;">前端团队可以专注于用户界面和交互的实现</strong>，<strong style="color: #0e88eb;">后端团队可以专注于业务逻辑和数据处理</strong>。这种分工明确，各自独立，减少了沟通和协调的成本，加快了开发进度。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">技术选型灵活</strong>：<strong style="color: #0e88eb;">前后端分离使得前端和后端可以根据各自的需求选择适合的技术栈</strong>，不受彼此的限制。前端可以使用最新的 JavaScript 框架和工具，如 React、Vue 等，充分发挥前端技术的优势。后端可以选择适合的编程语言和框架，如Java、Python、Node.js 等，根据业务需求和团队技能进行决策。这种技术选型的灵活性，使得团队可以根据项目特点和团队实力，选择最佳的技术组合。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">可扩展性好</strong>：前后端分离的架构使得应用程序的扩展更加容易。当需要扩展前端功能时，可以独立对前端进行改进和升级，而不影响后端的稳定性。同样，当需要扩展后端服务时，可以对后端进行水平扩展或性能优化，而不影响前端的运行。这种前后端的解耦，使得系统的可扩展性大大提高，能够更好地应对业务增长和用户量的变化。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">可维护性强</strong>：前后端分离的架构使得代码结构更加清晰，模块化程度高，易于维护和修改。前端代码和后端代码分别维护，各自的逻辑和责任边界明确。当需要修改或优化某个部分时，可以针对性地进行修改，而不会影响其他部分的正常运行。这种解耦的架构，降低了系统的复杂度，提高了代码的可读性和可维护性。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">重用性高</strong>：前后端分离的架构使得后端提供的 API 可以被多个前端应用程序重用。无论是 Web 端、移动端还是其他客户端，都可以通过相同的 API 接口访问后端服务。这种 API 的复用性，避免了重复开发的问题，提高了开发效率。同时，对于不同的客户端，可以根据其特点和需求，提供定制化的 API，满足不同场景下的数据需求。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">性能优化</strong>：前后端分离的架构为性能优化提供了更多的可能性。前端可以使用缓存机制、懒加载、代码压缩等技术，优化页面加载速度和用户体验。通过合理的缓存策略，可以减少不必要的网络请求，提高页面的响应速度。后端可以专注于业务逻辑和数据处理，通过数据库优化、缓存策略、负载均衡等手段，提高 API 的响应速度和吞吐量。前后端分别优化，可以更好地发挥各自的优势，提供更好的性能体验。</p>
</section>
</li>
</ol>
<p style="color: #000000;" data-tool="mdnice编辑器">前后端分离虽然有如上的优点，但是也并不是没有缺点，有如下的问题在技术选型的时候是需要重点考虑的：</p>
<ol class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">开发复杂度增加</strong>：前后端分离的架构虽然提高了开发效率和灵活性，但也增加了开发的复杂度。<strong style="color: #0e88eb;">前后端团队需要进行更多的沟通和协调</strong>，确保前后端的接口设计和数据格式的一致性。由于前后端是独立开发的，需要制定清晰的API文档和约定，避免出现理解偏差和集成问题。同时，前后端分离也对开发人员提出了更高的要求，需要前端开发人员具备一定的后端知识，后端开发人员也需要了解前端的需求和限制。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">前后端的版本兼容性</strong>：前后端分离的架构中，前端和后端是独立开发和部署的，它们之间通过 API 进行通信。这就要求前后端的版本必须保持兼容，否则可能会出现功能异常或数据错误。当后端 API 发生变更时，需要及时通知前端团队，并进行相应的调整。同样，当前端需要新的 API 支持时，也需要与后端团队沟通和协调。管理前后端的版本兼容性，需要制定严格的版本控制策略和发布流程，确保平稳过渡和升级。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">数据传输量增大</strong>：前后端分离的架构中，前端和后端之间通过 API 进行数据传输，这可能导致数据传输量的增大。由于前端需要通过 API 获取所需的数据，如果 API 设计不合理或前端请求过于频繁，会增加网络负载和延迟。为了减少数据传输量，需要合理设计 API，提供必要的数据过滤和分页机制。同时，也可以采用缓存策略，减少重复的数据请求。在某些场景下，还可以考虑使用 GraphQL 等技术，通过查询语言的方式精确获取所需数据，减少数据的冗余。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">安全性考虑</strong>：前后端分离的架构中，由于前端和后端是独立的，因此需要更加关注 API 的安全性。前端通过 API 访问后端服务，如果 API 没有进行适当的身份验证和授权，就可能存在安全风险。恶意用户可能会通过伪造或篡改 API 请求，获取敏感数据或执行未授权的操作。为了确保 API 的安全性，<strong style="color: #0e88eb;">需要实现完善的身份认证和授权机制</strong>，如<strong style="color: #0e88eb;">使用 OAuth、JWT 等标准化的认证协议</strong>。同时，还需要对 API 进行安全审计和测试，及时发现和修复潜在的安全漏洞。</p>
</section>
</li>
</ol>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">3 构建前后端分离架构的注意事项</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">基于前后的优势和劣势，我们在构建前后端分离架构的时候有以下的注意事项：</p>
<ol class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">明确前后端职责</strong>：在构建前后端分离架构时，首先需要明确前后端的职责边界。<strong style="color: #0e88eb;">前端负责用户界面的呈现和交互，而后端负责业务逻辑的处理和数据的存储</strong>。要避免前后端职责的混淆，确保各自的代码逻辑清晰和独立。<strong style="color: #0e88eb;">前端不应该包含过多的业务逻辑</strong>，而后端也不应该过多地干预前端的界面展示。通过合理的职责划分，可以提高系统的可维护性和可扩展性。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">设计良好的 API</strong>：<strong style="color: #0e88eb;">前后端分离的关键在于设计良好的 API</strong>。API 是前后端之间的通信契约，需要符合 RESTful 或 GraphQL 等标准化的设计原则。API 应该具有清晰的语义，合理的资源命名，以及标准的 HTTP 方法和状态码。同时，API还需要提供完整的文档说明，包括请求参数、响应格式、错误处理等。良好的 API 设计可以提高开发效率，减少沟通成本，并为未来的扩展提供便利。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">统一数据格式</strong>：前后端通信过程中，数据格式的统一是非常重要的。前后端应该约定统一的数据交换格式，如 JSON 。在设计 API 时，需要明确定义请求和响应的数据结构，避免出现数据格式不一致的问题。统一的数据格式可以减少数据解析和转换的开销，提高数据传输的效率。同时，也需要考虑数据的验证和错误处理，确保数据的完整性和正确性。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">处理跨域问题</strong>：前后端分离架构中，前端和后端通常部署在不同的域名下，因此会涉及到跨域访问的问题。为了允许前端访问后端的 API，需要正确配置跨域资源共享(CORS)。后端需要在响应头中添加适当的 CORS 头部，如Access-Control-Allow-Origin，以允许指定域名的跨域请求。同时，也<strong style="color: #0e88eb;">需要注意 CORS 的安全性，避免过于宽松的配置导致安全漏洞</strong>。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">身份认证和授权</strong>：在前后端分离架构中，<strong style="color: #0e88eb;">需要实现安全可靠的身份认证和授权机制</strong>。常见的方式是使用基于 token 的身份验证，如JSON Web Token(JWT)。后端在用户登录成功后，生成一个加密的 token，并将其返回给前端。前端在后续的 API 请求中，将 token 作为请求头发送给后端，用于验证用户身份。后端需要对 token 进行解密和验证，确保请求的合法性。同时，还需要根据用户的角色和权限，对API进行适当的授权控制。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">错误处理和日志记录</strong>：在前后端分离架构中，由于前端和后端是独立的，因此需要合理地处理错误情况。后端应该提供明确的错误信息和状态码，前端需要根据错误信息进行适当的处理和显示。同时，还需要记录日志，包括请求日志、错误日志等，以便问题定位和调试。日志记录应该包含关键的信息，如请求参数、响应结果、异常堆栈等，并采用合适的日志级别和格式。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">性能优化</strong>：前后端分离架构为性能优化提供了更多的可能性。<strong style="color: #0e88eb;">前端可以采用懒加载、代码拆分、缓存</strong>等技术，优化页面加载速度和用户体验。通过<strong style="color: #0e88eb;">合理的缓存策略</strong>，减少不必要的网络请求，提高页面的响应速度。使用 CDN 加速静态资源的加载，减少网络延迟。后端方面，<strong style="color: #0e88eb;">优化数据库查询</strong>，使用索引和查询优化技术，提高查询性能。<strong style="color: #0e88eb;">合理设计和使用缓存</strong>(如 Redis)，减少对数据库的直接访问，提高数据的读取速度。采用异步处理和消息队列机制，将耗时的任务异步执行，提高系统的并发处理能力等等。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">监控和运维</strong>：建立完善的监控和运维体系，对系统的性能、错误、安全等进行实时监测和管理。<strong style="color: #0e88eb;">前端可以使用错误监控工具</strong>(如 Sentry、Bugsnag)来捕获和报告前端的运行时错误，及时发现和修复问题。<strong style="color: #0e88eb;">后端使用 APM(应用性能监控)工具</strong>(如 New Relic、AppDynamics)对应用程序的性能指标进行监测，包括请求响应时间、数据库查询性能、资源利用率等，及时发现性能瓶颈和异常情况。<strong style="color: #0e88eb;">使用日志聚合和分析工具</strong>(如 ELK 栈)对应用程序的日志进行收集、存储和分析，便于问题的定位和追踪。建立告警机制，根据预设的阈值和规则，及时通知运维人员处理异常情况。<strong style="color: #0e88eb;">制定完善的运维流程和应急预案</strong>，包括部署流程、回滚机制、故障处理流程等，确保系统的稳定性和可用性。定期进行系统的备份和恢复演练，做好数据的备份和容灾措施。</p>
</section>
</li>
</ol>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4 在初创企业落地实施</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">初创企业在前后端分离架构落地时，需要从组织分工、技术栈选择、基础设施搭建等多个方面进行全面考虑和规划。以下是一些关键策略：</p>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.1 组织分工</span></h2>
<ol class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">成立专门的前后端团队</strong>：</p>
<p style="color: #000000;">根据团队规模和业务需求，成立专门的前端团队和后端团队。</p>
<p style="color: #000000;">前端团队负责用户界面的开发和交互，后端团队负责业务逻辑的实现和数据处理。每个团队都有明确的职责和目标，并建立有效的沟通机制，确保协作顺畅。</p>
<p style="color: #000000;">在项目早期可能没有完全分开，在一个研发组里面有各个工种，但是内部的分工和权责也要明确出来，算是虚线的逻辑吧。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">设置技术负责人</strong>：</p>
<p style="color: #000000;">在前后端团队中，分别设置技术负责人或架构师，负责制定技术路线、架构设计和技术决策。技术负责人需要深入了解业务需求，平衡技术选型和团队能力，确保技术方案的可行性和合理性。</p>
<p style="color: #000000;">最好是有一个全栈一些的技术负责人，能明确边界和原则，同时兼顾对于安全、效率、架构的梳理和管控。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">建立跨部门协作机制</strong>：</p>
<p style="color: #000000;">前后端分离架构需要前后端团队的紧密协作，同时也需要与产品、设计、测试等其他部门保持良好的沟通。建立定期的跨部门会议，讨论需求、进度、问题等，确保各个部门的工作协调一致。</p>
<p style="color: #000000;">在特别早期的初创企业，可能没有这么复杂，就一个研发组，一个产品组，大家坐一起完成工作，有事吼一声就行，但是做的节奏和逻辑需要明确，如双周的版本，一方面是有节奏，另一方面是有阶段性的成果交付，对于大家有一些正向的激励作用，同时也让整个项目组感受到事情在有节奏的推进中，有章法。</p>
</section>
</li>
</ol>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.2 技术栈选择</span></h2>
<ol class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">前端技术栈</strong>：</p>
<p style="color: #000000;">根据项目需求和团队技能，选择合适的前端技术栈。常见的选择包括 React、Vue 等现代化的 JavaScript 框架，以及配套的状态管理库(如Redux、Vuex)和构建工具(如Webpack、Babel)。同时，考虑使用 UI 组件库(如Ant Design、Element UI)和 CSS 预处理器(如Sass、Less)来提高开发效率。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">后端技术栈</strong>：后端技术栈的选择需要考虑性能、可扩展性、生态系统等因素。常见的选择包括 Node.js、Java、Golang 等，以及相应的 Web 框架(如Express、Spring Boot、Beego)。选择合适的数据库(如MySQL、MongoDB、Redis)来存储和管理数据。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">API 设计和文档</strong>：前后端通过 API 进行通信，因此需要制定清晰、规范的 API 设计原则。采用 RESTful 或 GraphQL 等标准化的 API 设计风格，提供易于理解和使用的 API 接口。同时，编写详细的 API 文档，包括请求参数、响应格式、错误码等，方便前后端开发人员的协作和集成。</p>
</section>
</li>
</ol>
<h2 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">4.3 基础设施搭建</span></h2>
<ol class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">开发环境搭建</strong>：为前后端团队提供统一的开发环境，包括操作系统、开发工具、依赖管理等。使用版本控制系统(如Git)来管理代码，并建立代码审查和合并的流程。搭建本地开发环境，提供必要的模拟数据和服务，方便开发和调试。以腾讯云为例，可以考虑使用其 Coding 平台，实现代码的版本控制和协作开发。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">CI/CD</strong>：CI/CD 是基础设施，自动化构建、测试和部署流程，从代码到制品库，再到线上环境部署。</p>
<p style="color: #000000;">可以使用 Jenkins、GitLab CI、Travis CI 等工具，实现代码的自动化构建、单元测试、集成测试和部署。建立自动化部署流程，将应用程序快速、可靠地部署到测试环境和生产环境。以腾讯云为例，可以考虑使用其 Coding 平台的 CI/CD 能力。</p>
<p style="color: #000000;">前端的构建产物可以使用类似于腾讯云的 COS 结合 CDN 访问，在访问速度和可用性方面都不错。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">生产环境搭建</strong>：选择合适的服务器和云平台来托管应用程序。根据业务需求和预期流量，合理配置服务器的规格和数量。考虑使用云服务提供商(如AWS、阿里云、腾讯云)提供的基础设施服务，如虚拟机、容器服务、数据库服务等，以便快速扩展和管理，减少运维相关的工作和人力投入。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">网络策略和安全策略</strong>：</p>
</section>
<ol class="list-paddingleft-1">
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">网络隔离和安全组</strong> ：使用虚拟私有云(Virtual Private Cloud， VPC)对线上环境进行网络隔离，确保不同环境之间的网络隔离性。将不同的服务组件(如 Web 服务器、应用服务器、数据库)放置在不同的子网中，通过网络 ACL 和安全组规则控制子网之间的访问。配置安全组规则，只允许必要的端口和协议通过，禁止不必要的入站和出站流量，减少攻击面。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">负载均衡和高可用</strong>：使用负载均衡服务(如腾讯云的 CLB)对线上环境的流量进行分发，实现服务的高可用和横向扩展。配置多个服务实例，通过负载均衡将流量分发到不同的实例，提高服务的容错能力和性能。开启会话保持(Session Persistence)功能，确保来自同一客户端的请求能够被路由到同一个服务实例，保持会话的一致性。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">HTTPS 加密传输</strong> ：为线上环境的服务配置 SSL/TLS 证书，启用 HTTPS 加密传输，保护数据的机密性和完整性。使用可信的证书颁发机构(CA)签发的证书，确保证书的可信性和安全性。定期检查和更新证书，避免证书过期导致的安全风险。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">Web 应用防火墙(WAF)</strong> ：部署 Web 应用防火墙(如腾讯云的 WAF)来保护线上环境的 Web 应用和 API 接口。配置 WAF 规则，防御常见的 Web 攻击，如 SQL 注入、跨站脚本攻击(XSS)、远程文件包含等。启用 WAF 的 CC 攻击防护功能，防止恶意的流量攻击和请求洪水。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">DDoS 防护</strong>：为线上环境启用 DDoS 防护服务(如腾讯云的 Anti-DDoS)，防御大流量的 DDoS 攻击。前期可以考虑使用 CDN 作为 DDoS 的一道防线。配置合适的防护阈值和清洗策略，根据业务需求和流量特征进行调整。定期监控 DDoS 攻击的情况，及时调整防护策略和扩容带宽。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">访问控制和身份认证</strong>：对敏感的管理后台和 API 接口实施严格的访问控制和身份认证机制。启用多因素认证(Multi-Factor Authentication， MFA)，如短信验证码、动态口令等，提高账号的安全性。对 API 接口进行身份认证和授权，如使用 OAuth、JWT 等机制，确保只有授权的客户端才能访问。</p>
</section>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">网络监控和日志</strong>：对线上环境的网络流量进行实时监控，包括流量状况、异常行为等。配置网络流量分析和可视化工具，如腾讯云的云监控，实时了解网络的健康状况。开启网络日志记录，包括访问日志、错误日志等，便于事后分析和问题排查。对网络日志进行集中收集和分析，使用日志分析平台(如 ELK)进行实时监控和告警。</p>
</section>
</li>
</ol>
</li>
<li>
<section style="color: #010101;">
<p style="color: #000000;"><strong style="color: #0e88eb;">一些辅助系统</strong></p>
</section>
</li>
</ol>
<ul class="list-paddingleft-1" style="color: #000000;" data-tool="mdnice编辑器">
<li>
<section style="color: #010101;">API 的管理系统：提供 API 文档，方便前后端开发同学了解和使用 API。</section>
</li>
<li>
<section style="color: #010101;">配置中心：集中管理应用程序的配置信息，将配置信息与代码分离，实现配置的动态更新和热加载，无需重新部署应用。</section>
</li>
<li>
<section style="color: #010101;">定时任务管理系统：提供任务的依赖管理和失败重试机制，处理任务之间的依赖关系和异常情况，记录任务的执行日志和统计信息，方便问题追踪和性能优化。</section>
</li>
<li>
<section style="color: #010101;">数据模型管理系统：管理模型的变更，也可以不用，直接一个 sql 文件做版本管理。</section>
</li>
</ul>
<h1 style="color: #000000;" data-tool="mdnice编辑器"><span style="font-weight: bold; color: #0e8aeb;">5 小结</span></h1>
<p style="color: #000000;" data-tool="mdnice编辑器">初创企业在落地前后端分离架构时，需要全面考虑技术选型、开发流程、基础设施、性能优化、监控运维等多个方面。合理的技术选型和开发流程是高效协作的基石，完善的基础设施和辅助系统是稳定运行的保障，而持续的性能优化和监控运维则是不断迭代和创新的动力。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">前后端分离不仅仅是一种技术架构，更是一种思维方式和工作方式的转变。</strong>它要求前后端开发人员从各自的舒适区走出来，以开放和协作的心态，通过接口契约和文档驱动的方式，建立起高效、灵活、可扩展的应用架构。分层是架构的本质，分治是架构的灵魂。</p>
<p style="color: #000000;" data-tool="mdnice编辑器">初创企业在追求快速迭代和业务增长的同时，也要重视架构的长期演进和技术债务的管理。一个好的前后端分离架构，不仅能够支撑当前的业务需求，更能够为未来的发展提供可扩展性和灵活性。</p>
<p style="color: #000000;" data-tool="mdnice编辑器"><strong style="color: #0e88eb;">架构不是一蹴而就的，而是一个不断迭代和优化的过程。关键是要有长远的视角，同时也要脚踏实地，一步一个脚印地前进。</strong></p>
<p style="color: #000000;" data-tool="mdnice编辑器">以上</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2024/08/implementation-strategy-of-front-end-and-back-end-separation-architecture-for-startups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>浅谈创业早期技术实现思路</title>
		<link>https://www.phppan.com/2016/09/startup-technology/</link>
		<comments>https://www.phppan.com/2016/09/startup-technology/#comments</comments>
		<pubDate>Wed, 28 Sep 2016 04:44:07 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[架构和远方]]></category>
		<category><![CDATA[创业]]></category>
		<category><![CDATA[架构]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1957</guid>
		<description><![CDATA[浅谈创业早期技术实现思路 创业最开始的时候，是最难的时候，此时，从0到1，从无到有，做的是自己不曾做过的事情， [&#8230;]]]></description>
				<content:encoded><![CDATA[<p class="p1"><a href="http://www.phppan.com/wp-content/uploads/2016/09/20130108093351_79502-1068x784.jpg"><img class="size-large wp-image-1958 aligncenter" src="http://www.phppan.com/wp-content/uploads/2016/09/20130108093351_79502-1068x784-1024x751.jpg" alt="20130108093351_79502-1068x784" width="625" height="458" /></a></p>
<h1 id="浅谈创业早期技术实现思路" style="color: #333333;">浅谈创业早期技术实现思路</h1>
<p class="comments-section" style="color: #333333;">创业最开始的时候，是最难的时候，此时，从0到1，从无到有，做的是自己不曾做过的事情，所以，我们称之为创业。</p>
<p class="comments-section" style="color: #333333;">对于早期的技术而言，不要大而全，不用高精尖，先按需求实现，活下来再说。我们需要考虑的是哪些可以用云服务，哪些可以直接用现成的开源方案或技术，哪些需要自己开发； 我们可以粗旷一些，要的是快速出活，让产品活下来。</p>
<p class="comments-section" style="color: #333333;">前期那么几杆枪，就技术而行，要用团队成员最熟悉的，要有人能全盘掌控所有的技术栈。虽然我们用的是最熟悉的东西，但是在整个技术选型和开发过程中，需要有以下几个基本的思路：</p>
<h3 id="1-原则和规范" style="color: #333333;">1. 原则和规范</h3>
<ul style="color: #333333;">
<li>注意解耦，分层，动静分离、轻重分离的原则；</li>
<li>开发的规范，代码及代码分支管理规范、发布流程；</li>
<li>在开发过程中，对于公共的操作要抽象成组件，即我们常说的职责单一，如缓存操作，数据库操作等等都封装成组件，一边开发一边封装；</li>
</ul>
<h3 id="2-保留水平扩展的能力" style="color: #333333;">2. 保留水平扩展的能力</h3>
<ul style="color: #333333;">
<li>业务服务端无状态，会话通过 memcache 等来管理；</li>
<li>数据库设计考虑到一定时间内的容量，做好必要的分库分表，如1到2年的容量规划；</li>
<li>热点数据缓存起来，将大量请求打到缓存而不是数据库；</li>
</ul>
<h3 id="3-业务隔离" style="color: #333333;">3. 业务隔离</h3>
<ul style="color: #333333;">
<li>隔离关键业务和非关键业务；</li>
<li>隔离主业务系统与旁路上报、日志上报等周边系统；如果是 HTTP 服务，至少要在域名级别保证其隔离；</li>
<li>不同端业务的隔离； 如 PC 侧的业务和 H5 的页面可以是同一套代码，但是域名不同，接入点不同，后端机器相同；</li>
</ul>
<h3 id="4-用好开源的轮子" style="color: #333333;">4. 用好开源的轮子</h3>
<ul style="color: #333333;">
<li>在满足现有业务需求的情况下，对业界开源的轮子做技术选型，在能驾驭的前提下尽量使用已有的，成熟的，经过了大量公司实践的开源组件，如nginx，redis，elk等等。</li>
</ul>
<h3 id="5-必要的安全策略" style="color: #333333;">5. 必要的安全策略</h3>
<ul style="color: #333333;">
<li>安全是互联网应用无法回避的问题，我们需要在框架或基础组件层面引入常见的 XSS 、CSRF 和 SQL注入等安全问题的过滤；</li>
<li>对于静态的能放到CDN的内容尽量放到CDN，一是就近接入，提高访问速度，二是减少后台的服务压力；</li>
<li>保留快速切到云服务防 DDoS 的能力；</li>
<li>在业务层面实现一定的规则以及联合 WEB 容器实现一定程度上的防 CC 攻击能力；</li>
</ul>
<h3 id="6-备份、备份、备份" style="color: #333333;">6. 备份、备份、备份</h3>
<ul style="color: #333333;">
<li>宕机、不同城市的机房同时起火、光缆被挖断、数据错乱等等各种神奇的事情都有可能出现，此时备份就显示出其价值。我们不仅仅是要备份业务数据库，还要备份代码，备份部署脚本等等；</li>
<li>当所有的不幸都发生的时候，我们所有的东西都不见的时候，我们能够很快的将应用恢复到上一个可预见的备份版本，即我们有灾备方案，最好是能够提前演练过；</li>
</ul>
<h3 id="7-监控可能出现的异常" style="color: #333333;">7. 监控可能出现的异常</h3>
<ul style="color: #333333;">
<li>使用第三方的监控服务监控网站的访问可用性，服务的可用性等；</li>
<li>对业务的数据和关键的节点进行监控，比如做金融的需要确认每个用户的进出钱要对得上账，在这里至少要有一个监控；</li>
</ul>
<h3 id="8-灰度发布" style="color: #333333;">8. 灰度发布</h3>
<ul style="color: #333333;">
<li>前期按机器做灰度发布，一个简单的脚本就可以搞定，后期可以实现按用户灰度等，以此提高业务的连续性，保证业务的可用性；</li>
</ul>
<p class="comments-section" style="color: #333333;">从 0 到 1，不管是技术还是业务都是不成熟的，大家都是摸着石头过河，所以我们需要快速的试错，需要快速的反馈。</p>
<p class="comments-section" style="color: #333333;">在技术层面，在保证以上一些原则的同时，快速迭代，实现产品需求，对于一些出错统计类的东西直接交给第三方来实现；在业务层面，如果是网站，一些流量分析直接也是直接交给第三方，比如百度统计，Google Analytics等，对于具体的业务，一个脚本每天早上跑出报表以邮件的形式发到指定邮件组，将相关人加入邮件组列表接以能接收到报表邮件。</p>
<p class="comments-section" style="color: #333333;">以上是最开始需要注意的原则和必须要实现的东西，在此之外，还有很重要的需要搭建的内容需要持续搭建和实现，包括但不限于以下一些：</p>
<ol style="color: #333333;">
<li>降级服务能力：在遇到正常或不正常的大流量时，可以在一定范围内将业务降级，业务降级可以前期提供手动降级能力，后续实现自动降级；</li>
<li>第三方服务可替换：花钱能解决问题，但花钱一般不能真正的解决问题，因为花钱买来的可能是一个坑，还是一个需要自己填的坑。在使用第三方服务时，需要多家备用可替换，如短信服务，多接两家，平时两家均衡分发，或者按业务分发，当某一家出问题时，直接切到正常的那家；</li>
<li>日志中心：日志是定位问题的必备工具，当后台服务有多台机器时，就不能一台一台的用 grep 搜索了，需要有一个集中存储的地方，直接上一个 elk 也许能解决大部分的问题；</li>
</ol>
<p class="comments-section" style="color: #333333;">创业要的是活下来，技术要的是产生价值。 架构会随着业务的发展而不断的演化。</p>
<hr />
<p class="p2"><span class="s1">除了眼前的苟且,还有架构与远方。</span></p>
<p class="p2"><span class="s1">介绍创业路上的技术选型和架构、大型网站架构、高性能高可用可扩展架构实现，技术管理等相关话题，紧跟业界主流步伐。</span></p>
<p class="p2"><a href="http://www.phppan.com/wp-content/uploads/2016/09/qrcode_for_gh_5d3f534e15fe_344-1.jpg"><img class="aligncenter size-full wp-image-1959" src="http://www.phppan.com/wp-content/uploads/2016/09/qrcode_for_gh_5d3f534e15fe_344-1.jpg" alt="qrcode_for_gh_5d3f534e15fe_344 (1)" width="344" height="344" /></a></p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2016/09/startup-technology/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>数据集合类系统如何架构</title>
		<link>https://www.phppan.com/2015/05/data-collections-systems-architecture/</link>
		<comments>https://www.phppan.com/2015/05/data-collections-systems-architecture/#comments</comments>
		<pubDate>Sat, 09 May 2015 17:00:11 +0000</pubDate>
		<dc:creator><![CDATA[admin]]></dc:creator>
				<category><![CDATA[程序相关]]></category>
		<category><![CDATA[数据集合]]></category>
		<category><![CDATA[架构]]></category>
		<category><![CDATA[系统架构]]></category>
		<category><![CDATA[高可用]]></category>

		<guid isPermaLink="false">http://www.phppan.com/?p=1926</guid>
		<description><![CDATA[数据集合类系统如何架构 以下内容来源于QCon某高可用架构群聊天记录整理 如果携程网想把旅游信息展示到另一平台 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>数据集合类系统如何架构</p>
<p>以下内容来源于QCon某高可用架构群聊天记录整理</p>
<p>如果携程网想把旅游信息展示到另一平台上 平台和他们的系统数据对接，pull好一些还是post好一些？或者说一个系统只是把好多其他商家的数据集合展示到统一的系统上，这样的系统一般如何架构？</p>
<p>先回答第一个问题：数据对接是pull好一些还是post好一些，这里需要根据实际业务做权衡，如果平台系统很大部分是通过聚合第三方数据再展示，那么比较推荐让第三方post数据，自己设计统一数据规则接口。这种情况，需要考虑自身服务的稳定性了，预防第三方误调用，击垮自身系统。如果只有小部分内容聚合第三方，那就pull，比较好保证自己系统稳定性，不过最终还得把所有的数据转换成自己格式，需要自己开发团队做这块工作。</p>
<p>相比较而言，post时效性高，数据交互少，如果系统会需要各个源的信息，最终也不会只是展示那么简单。如果使用post方案，则需要在接入，数据，读取等方面做隔离，在接入使用mq可以提高吞吐，在读的时候用Cache抗。并且在前期需要考虑好数据存储和数据的量级，因为是第三方的数据，在存储的扩展性方面要有比较好的方案。</p>
<p>最终落地的方案可能是：</p>
<p>按业务隔离，不同的业务相互不影响，拆分子系统；<br />
使用redis和kafka保障高性能，kafka主要一方面用到日志上 一方面用到缓解数据库并发上；<br />
使用nginx和lvs保障高可用；<br />
在后期所有数据进hbase然后用storm做数据流处理和分析</p>
<p>以上这些并不需要一次性做到位，不要过早优化，只需要有一些大的原则，比如隔离，扩展等。小系统会随着业务慢慢演变，最终会变成大系统。在演变的过程中，可能会需要读写分离、业务分布式，分服务，架构就是在这样演变的路上成长起来的。</p>
]]></content:encoded>
			<wfw:commentRss>https://www.phppan.com/2015/05/data-collections-systems-architecture/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
