<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>测试分层 on Dorkytiger 的小屋</title>
    <link>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/</link>
    <description>Recent content in 测试分层 on Dorkytiger 的小屋</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <atom:link href="https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>六层金字塔总览</title>
      <link>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/01-pyramid-overview/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/01-pyramid-overview/</guid>
      <description>&lt;h1 id=&#34;31-六层金字塔总览&#34;&gt;3.1 六层金字塔总览&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;上一节：无　|　下一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/02-component-benchmark/&#34;&gt;3.2 组件基准&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一句话结论&#34;&gt;一句话结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;性能测试分六层，每层回答不同的问题。&lt;/strong&gt; 记住一条法则：&lt;strong&gt;要回答「为什么慢」，越往下层（越隔离）越好；要回答「能扛多少」，必须往上走（越接近真实）。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一用汽车研发理解六层测试&#34;&gt;一、用汽车研发理解六层测试&lt;/h2&gt;
&lt;p&gt;汽车厂商研发一款新车，不会直接让试车员开上高速测。它会经历一整套逐级放大的测试：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;汽车研发阶段&lt;/th&gt;
					&lt;th&gt;对应的性能测试&lt;/th&gt;
					&lt;th&gt;干什么&lt;/th&gt;
					&lt;th&gt;成本&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;零件台架试验&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;微基准&lt;/td&gt;
					&lt;td&gt;一个轴承在试验台上转到坏，测寿命&lt;/td&gt;
					&lt;td&gt;极低&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;总成试验&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;组件基准&lt;/td&gt;
					&lt;td&gt;发动机装在台架上跑，测功率油耗&lt;/td&gt;
					&lt;td&gt;低&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;整车转鼓试验&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;集成基准&lt;/td&gt;
					&lt;td&gt;整车在实验室里模拟行驶&lt;/td&gt;
					&lt;td&gt;中&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;真实道路测试&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;全链路负载&lt;/td&gt;
					&lt;td&gt;开上真实道路、真实天气、真实交通&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;碰撞试验&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;破坏性测试&lt;/td&gt;
					&lt;td&gt;故意撞毁，看怎么坏、能不能保命&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;耐久路试&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;浸泡测试&lt;/td&gt;
					&lt;td&gt;跑 10 万公里，看哪里先磨坏&lt;/td&gt;
					&lt;td&gt;很高&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;量产决策&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;容量测试&lt;/td&gt;
					&lt;td&gt;决定生产多少台、什么配置&lt;/td&gt;
					&lt;td&gt;很高&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;从这张表能读出三件事&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;越往上越接近真实，也越贵。&lt;/strong&gt; 台架试验一小时几百块，风洞试验按小时上万。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;越往下越容易定位。&lt;/strong&gt; 台架上的轴承坏了，你立刻知道是轴承的问题；整车上异响，你要查几十个可能。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;每一层都有它才能发现的盲区。&lt;/strong&gt; 台架测不出风噪，路测才能；路测测不出 10 万公里后的磨损，耐久才能。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;性能测试完全一样。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二六层详解&#34;&gt;二、六层详解&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;层级&lt;/th&gt;
					&lt;th&gt;测什么&lt;/th&gt;
					&lt;th&gt;时间尺度&lt;/th&gt;
					&lt;th&gt;单次耗时&lt;/th&gt;
					&lt;th&gt;能发现&lt;/th&gt;
					&lt;th&gt;盲区&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;① 微基准&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;单个方法/算法&lt;/td&gt;
					&lt;td&gt;纳秒–微秒&lt;/td&gt;
					&lt;td&gt;秒级&lt;/td&gt;
					&lt;td&gt;算法与常数优化、分配热点&lt;/td&gt;
					&lt;td&gt;看不到 IO、锁、GC 的真实交互&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;② 组件基准&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;Repository、序列化、缓存&lt;/td&gt;
					&lt;td&gt;微秒–毫秒&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;几十秒&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;SQL 慢、N+1、序列化开销、索引缺失&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;无网络、无网关、无真实并发&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;③ 集成基准&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;单服务完整启动 + 真实依赖&lt;/td&gt;
					&lt;td&gt;毫秒&lt;/td&gt;
					&lt;td&gt;分钟级&lt;/td&gt;
					&lt;td&gt;连接池、事务、启动预热、AOP 开销&lt;/td&gt;
					&lt;td&gt;无多服务放大效应&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;④ 全链路负载&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;多服务 + 网关 + 真实网络&lt;/td&gt;
					&lt;td&gt;毫秒–秒&lt;/td&gt;
					&lt;td&gt;十分钟级&lt;/td&gt;
					&lt;td&gt;排队、级联、限流、超时配合&lt;/td&gt;
					&lt;td&gt;成本高、定位难、噪声大&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;⑤ 专项测试&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;压力 / 尖峰 / 浸泡&lt;/td&gt;
					&lt;td&gt;分钟–小时&lt;/td&gt;
					&lt;td&gt;小时级&lt;/td&gt;
					&lt;td&gt;拐点、崩溃形态、&lt;strong&gt;资源泄漏&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;不回答「为什么」&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;⑥ 容量测试&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;多副本 + 负载分配&lt;/td&gt;
					&lt;td&gt;小时&lt;/td&gt;
					&lt;td&gt;小时级&lt;/td&gt;
					&lt;td&gt;副本数与规格决策&lt;/td&gt;
					&lt;td&gt;需要接近生产的拓扑&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三核心判断法则&#34;&gt;三、核心判断法则&lt;/h2&gt;
&lt;h3 id=&#34;法则一诊断往下容量往上&#34;&gt;法则一：诊断往下，容量往上&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;「这个接口为什么慢？」 → 往下走：组件基准 / 微基准 / 剖析
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;「这个服务能扛多少？」 → 往上走：全链路负载 / 容量测试
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;混用会怎样&lt;/strong&gt;：&lt;/p&gt;</description>
    </item>
    <item>
      <title>组件基准：性价比最高的一层</title>
      <link>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/02-component-benchmark/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/02-component-benchmark/</guid>
      <description>&lt;h1 id=&#34;32-组件基准性价比最高的一层&#34;&gt;3.2 组件基准：性价比最高的一层&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;上一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/01-pyramid-overview/&#34;&gt;3.1 六层金字塔总览&lt;/a&gt;　|　下一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/03-integration-and-e2e/&#34;&gt;3.3 集成基准与全链路&lt;/a&gt;
配套代码：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/code/03-test-pyramid/02-component-benchmark/&#34;&gt;03-test-pyramid/02-component-benchmark&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一句话结论&#34;&gt;一句话结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;后端 80% 的性能问题（慢 SQL、N+1、序列化开销、索引缺失、锁竞争）都能在组件基准里被发现，而它的迭代成本只有几十秒。&lt;/strong&gt; 这是投入产出比最高的一层，也是大多数团队&lt;strong&gt;完全缺失&lt;/strong&gt;的一层。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一用台架试验理解组件基准&#34;&gt;一、用「台架试验」理解组件基准&lt;/h2&gt;
&lt;p&gt;汽车厂商测发动机，会把它装在&lt;strong&gt;台架&lt;/strong&gt;上：接上真实的油路、水路、排气，但不装在整车上。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么？&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;台架的好处&lt;/th&gt;
					&lt;th&gt;对应组件基准&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;环境可控、可重复&lt;/td&gt;
					&lt;td&gt;固定数据集、固定随机种子&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;出问题立刻知道是发动机的&lt;/td&gt;
					&lt;td&gt;慢就是这条 SQL 慢，不会怪到网络上&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;一次试验几分钟，一天能试几十轮&lt;/td&gt;
					&lt;td&gt;一次基准几十秒，快速迭代&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;能测到极限工况（红线转速）&lt;/td&gt;
					&lt;td&gt;能测到极端数据（1 亿行、热点 key）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;关键：台架用的是真发动机&lt;/strong&gt;，不是模型。同理，&lt;strong&gt;组件基准必须用真实数据库&lt;/strong&gt;（Testcontainers 起的 PostgreSQL），不能用 H2 之类替代品——因为索引行为、执行计划、锁机制完全不同。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;用 H2 做基准的后果&lt;/strong&gt;：在 H2 上很快的查询，在 PostgreSQL 上可能因为执行计划不同而慢 100 倍。&lt;strong&gt;你会得到「测试通过、上线爆炸」的经典结局。&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二组件基准测什么四件事分开测&#34;&gt;二、组件基准测什么：四件事分开测&lt;/h2&gt;
&lt;p&gt;一个接口的真实成本 = &lt;strong&gt;SQL 执行 + 驱动/ORM 映射 + 业务逻辑 + 序列化&lt;/strong&gt;。&lt;strong&gt;必须分开测&lt;/strong&gt;，否则你只知道总数，不知道哪块贵。&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;测什么&lt;/th&gt;
					&lt;th&gt;怎么测&lt;/th&gt;
					&lt;th&gt;常见发现&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;① 纯 SQL 执行&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;直接用 JDBC 执行，不含映射&lt;/td&gt;
					&lt;td&gt;缺索引、全表扫描、锁等待&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;② 驱动/ORM 映射&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;对比「JDBC 结果集 → 对象」与①的差值&lt;/td&gt;
					&lt;td&gt;ORM 的反射开销、N+1&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;③ 业务逻辑&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;用固定输入调用 service 方法，mock 掉 IO&lt;/td&gt;
					&lt;td&gt;算法问题、重复计算&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;④ 序列化&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;单独测 JSON 编解码&lt;/td&gt;
					&lt;td&gt;反射型序列化器、大对象&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;为什么必须分开&lt;/strong&gt;：假设你测出「接口总耗时 60 ms」，你无法判断该优化哪个。分开之后：&lt;/p&gt;</description>
    </item>
    <item>
      <title>集成基准与全链路：什么时候值得</title>
      <link>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/03-integration-and-e2e/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/03-integration-and-e2e/</guid>
      <description>&lt;h1 id=&#34;33-集成基准与全链路什么时候值得&#34;&gt;3.3 集成基准与全链路：什么时候值得&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;上一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/02-component-benchmark/&#34;&gt;3.2 组件基准&lt;/a&gt;　|　下一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/04-load-profiles/&#34;&gt;3.4 负载曲线&lt;/a&gt;
配套代码：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/code/03-test-pyramid/03-integration-and-e2e/&#34;&gt;03-test-pyramid/03-integration-and-e2e&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一句话结论&#34;&gt;一句话结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;集成基准补的是「单服务完整启动」这一层；全链路压测补的是「排队与跨服务放大」。&lt;/strong&gt; 全链路很贵，只该用在&lt;strong&gt;验收 SLO、测容量、验证级联行为&lt;/strong&gt;这三件事上——&lt;strong&gt;绝不能用来定位瓶颈。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一用转鼓试验和真实路试理解这两层&#34;&gt;一、用「转鼓试验」和「真实路试」理解这两层&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th&gt;转鼓试验（集成基准）&lt;/th&gt;
					&lt;th&gt;真实路试（全链路）&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;在哪跑&lt;/td&gt;
					&lt;td&gt;实验室，整车在转鼓上&lt;/td&gt;
					&lt;td&gt;真实道路&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;有什么&lt;/td&gt;
					&lt;td&gt;真车、真发动机、真轮胎&lt;/td&gt;
					&lt;td&gt;加上真实天气、交通、坡度、油品&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;能发现&lt;/td&gt;
					&lt;td&gt;整车级别的匹配问题（变速箱逻辑、散热）&lt;/td&gt;
					&lt;td&gt;高速风噪、长上坡过热、堵车时的油耗&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;成本&lt;/td&gt;
					&lt;td&gt;中&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;可重复性&lt;/td&gt;
					&lt;td&gt;高（环境可控）&lt;/td&gt;
					&lt;td&gt;低（天气、交通不可控）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;对应到后端&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;&lt;/th&gt;
					&lt;th&gt;集成基准&lt;/th&gt;
					&lt;th&gt;全链路负载&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;范围&lt;/td&gt;
					&lt;td&gt;单服务完整启动 + 真实依赖&lt;/td&gt;
					&lt;td&gt;多服务 + 网关 + 真实网络&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;能发现&lt;/td&gt;
					&lt;td&gt;连接池、事务边界、AOP/拦截器开销、启动预热、序列化链路&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;排队、级联超时、限流配置、跨服务放大&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;成本&lt;/td&gt;
					&lt;td&gt;分钟级&lt;/td&gt;
					&lt;td&gt;十分钟到小时级&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;可重复性&lt;/td&gt;
					&lt;td&gt;高&lt;/td&gt;
					&lt;td&gt;中（受环境噪声影响大）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二集成基准填补单服务完整的空白&#34;&gt;二、集成基准：填补「单服务完整」的空白&lt;/h2&gt;
&lt;p&gt;组件基准只测一个 Repository 或一个方法。&lt;strong&gt;但真实请求还会经过：&lt;/strong&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;HTTP 层 → 拦截器/中间件 → 鉴权 → 参数校验 → 业务逻辑 → 事务 → 多个 Repository → 序列化 → 响应
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这些环节的成本（拦截器链、事务开启/提交、日志、指标埋点）&lt;strong&gt;只有把服务完整启动起来才能测到&lt;/strong&gt;。&lt;/p&gt;</description>
    </item>
    <item>
      <title>负载曲线：阶梯、恒定、尖峰</title>
      <link>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/04-load-profiles/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/04-load-profiles/</guid>
      <description>&lt;h1 id=&#34;34-负载曲线阶梯恒定尖峰&#34;&gt;3.4 负载曲线：阶梯、恒定、尖峰&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;上一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/03-integration-and-e2e/&#34;&gt;3.3 集成基准与全链路&lt;/a&gt;　|　下一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/05-soak-testing/&#34;&gt;3.5 浸泡测试&lt;/a&gt;
配套代码：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/code/03-test-pyramid/04-load-profiles/&#34;&gt;03-test-pyramid/04-load-profiles&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一句话结论&#34;&gt;一句话结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;三种负载曲线用来发现三种不同的问题&lt;/strong&gt;：阶梯加压找&lt;strong&gt;拐点&lt;/strong&gt;，恒定压测验证&lt;strong&gt;稳态 SLO&lt;/strong&gt;，尖峰测试验证&lt;strong&gt;弹性与恢复&lt;/strong&gt;。用错曲线，就会测不出你关心的问题。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一用汽车测试理解三种路况&#34;&gt;一、用汽车测试理解三种路况&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;路况&lt;/th&gt;
					&lt;th&gt;负载曲线&lt;/th&gt;
					&lt;th&gt;测什么&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;匀速巡航&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;恒定到达率&lt;/td&gt;
					&lt;td&gt;稳定工况下的油耗与舒适度&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;逐步加速到极限&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;阶梯加压&lt;/td&gt;
					&lt;td&gt;最高能跑多快、什么时候开始抖动&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;急加速 + 急刹车&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;尖峰测试&lt;/td&gt;
					&lt;td&gt;刹车性能、恢复能力、热衰减&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;汽车厂商三种都测，因为它们暴露的问题完全不同。&lt;strong&gt;后端也一样。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二阶梯加压ramping找拐点&#34;&gt;二、阶梯加压（Ramping）：找拐点&lt;/h2&gt;
&lt;h3 id=&#34;长什么样&#34;&gt;长什么样&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;到达率
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ↑
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2000 ┤                                    ╭──── 崩溃点
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1000 ┤                        ╭───────────╯
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 700 ┤              ╭─────────╯  ← 拐点
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 400 ┤      ╭───────╯
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 100 ┤──────╯
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     └──────────────────────────────────────→ 时间
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       每级：爬升 30s + 稳态 2~5min
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;关键参数每一项都有理由&#34;&gt;关键参数（每一项都有理由）&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;参数&lt;/th&gt;
					&lt;th&gt;建议值&lt;/th&gt;
					&lt;th&gt;为什么&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;起始负载&lt;/td&gt;
					&lt;td&gt;目标容量的 10%~20%&lt;/td&gt;
					&lt;td&gt;先建立低位基线&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;每级增幅&lt;/td&gt;
					&lt;td&gt;1.5–2 倍&lt;/td&gt;
					&lt;td&gt;太大跳过了拐点，太小耗时太久&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;爬升时长&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;30 秒&lt;/td&gt;
					&lt;td&gt;让系统有时间升到该级（不要瞬间跳变）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;稳态时长&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;2–5 分钟&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;⚠️ 最关键：队列要建立、缓存要进入混合状态、GC 周期要走过至少一轮&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;终止条件&lt;/td&gt;
					&lt;td&gt;崩溃线（第 1 章 1.4 节）&lt;/td&gt;
					&lt;td&gt;避免把服务压死&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;最容易犯的错每级只跑-30-秒&#34;&gt;最容易犯的错：每级只跑 30 秒&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;为什么不行&lt;/strong&gt;：&lt;/p&gt;</description>
    </item>
    <item>
      <title>浸泡测试：唯一能发现泄漏的测试</title>
      <link>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/05-soak-testing/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/05-soak-testing/</guid>
      <description>&lt;h1 id=&#34;35-浸泡测试唯一能发现泄漏的测试&#34;&gt;3.5 浸泡测试：唯一能发现泄漏的测试&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;上一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/04-load-profiles/&#34;&gt;3.4 负载曲线&lt;/a&gt;　|　下一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/06-breakdown-testing/&#34;&gt;3.6 破坏性测试&lt;/a&gt;
配套代码：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/code/03-test-pyramid/05-soak-testing/&#34;&gt;03-test-pyramid/05-soak-testing&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一句话结论&#34;&gt;一句话结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;浸泡测试（Soak Test）是唯一能发现「缓慢泄漏」的测试&lt;/strong&gt;——内存泄漏、连接泄漏、文件描述符泄漏、缓存无界增长。它也是最少人做、回报最高的一种测试，因为它发现的问题往往是&lt;strong&gt;半夜 OOM&lt;/strong&gt; 的直接原因。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一用耐久路试理解浸泡测试&#34;&gt;一、用「耐久路试」理解浸泡测试&lt;/h2&gt;
&lt;p&gt;汽车厂商会让一台车连续跑 &lt;strong&gt;10 万公里&lt;/strong&gt;，穿越各种气候与路况。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;为什么不跑 1000 公里就够了？&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;有些问题是&lt;strong&gt;随里程累积&lt;/strong&gt;的：密封圈老化、机油消耗、变速箱磨损。&lt;/li&gt;
&lt;li&gt;短途试驾&lt;strong&gt;永远发现不了&lt;/strong&gt;这些——因为它们需要时间。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;后端完全一样&lt;/strong&gt;：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;短时间压测（10 分钟）&lt;/th&gt;
					&lt;th&gt;长时间浸泡（数小时）&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;发现「慢」和「错」&lt;/td&gt;
					&lt;td&gt;发现「&lt;strong&gt;缓慢变坏&lt;/strong&gt;」&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;内存看起来稳定&lt;/td&gt;
					&lt;td&gt;内存每小时涨 50 MB → 12 小时后 OOM&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;连接数正常&lt;/td&gt;
					&lt;td&gt;连接数每小时涨 3 个 → 一天后池子耗尽&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;文件描述符正常&lt;/td&gt;
					&lt;td&gt;FD 缓慢泄漏 → 一天后 &lt;code&gt;Too many open files&lt;/code&gt;&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;关键&lt;/strong&gt;：泄漏类问题&lt;strong&gt;不会在 10 分钟内显现&lt;/strong&gt;。它们的特点是「每天的增量很小，但永不回落」——只有拉长时间轴才能看出来。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二泄漏的四种典型形态&#34;&gt;二、泄漏的四种典型形态&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;泄漏类型&lt;/th&gt;
					&lt;th&gt;表现&lt;/th&gt;
					&lt;th&gt;常见原因&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;内存泄漏&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;堆使用持续上升，Full GC 后也不回落&lt;/td&gt;
					&lt;td&gt;静态集合持有对象、监听器未注销、&lt;code&gt;ThreadLocal&lt;/code&gt; 未清理、缓存无界&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;连接泄漏&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;池中 &lt;code&gt;active&lt;/code&gt; 持续上升，&lt;code&gt;idle&lt;/code&gt; 下降，&lt;code&gt;total&lt;/code&gt; 触顶&lt;/td&gt;
					&lt;td&gt;异常路径未归还连接、事务未关闭、&lt;code&gt;use {}&lt;/code&gt; 漏写&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;线程/协程泄漏&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;线程数或协程数持续上升&lt;/td&gt;
					&lt;td&gt;未取消的 &lt;code&gt;GlobalScope&lt;/code&gt;、未关闭的线程池、阻塞操作堆积&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;文件描述符泄漏&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;FD 数持续上升&lt;/td&gt;
					&lt;td&gt;未关闭的文件/套接字、日志句柄泄漏&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Kotlin 特有的两个泄漏源&lt;/strong&gt;：&lt;/p&gt;</description>
    </item>
    <item>
      <title>破坏性测试：崩溃点与崩溃形态</title>
      <link>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/06-breakdown-testing/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/06-breakdown-testing/</guid>
      <description>&lt;h1 id=&#34;36-破坏性测试崩溃点与崩溃形态&#34;&gt;3.6 破坏性测试：崩溃点与崩溃形态&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;上一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/05-soak-testing/&#34;&gt;3.5 浸泡测试&lt;/a&gt;　|　下一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/07-selection-and-cost/&#34;&gt;3.7 层级选择与成本&lt;/a&gt;
配套代码：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/code/03-test-pyramid/06-breakdown-testing/&#34;&gt;03-test-pyramid/06-breakdown-testing&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一句话结论&#34;&gt;一句话结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;破坏性测试的价值不在于「知道多少 QPS 会垮」，而在于「知道它是怎么垮的」。&lt;/strong&gt; 崩溃形态决定了故障的影响范围、恢复难度，以及半夜被叫起来时你该做什么。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一用碰撞试验理解破坏性测试&#34;&gt;一、用「碰撞试验」理解破坏性测试&lt;/h2&gt;
&lt;p&gt;汽车厂商会&lt;strong&gt;故意把车撞毁&lt;/strong&gt;。这不是为了证明车安全，而是为了回答：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;碰撞试验要回答的&lt;/th&gt;
					&lt;th&gt;对应后端&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;撞了之后&lt;strong&gt;哪个部位先变形&lt;/strong&gt;？&lt;/td&gt;
					&lt;td&gt;哪类资源先饱和？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;乘员舱&lt;strong&gt;能不能保住&lt;/strong&gt;？&lt;/td&gt;
					&lt;td&gt;核心功能是否还可用（优雅降级）？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;是&lt;strong&gt;吸能变形&lt;/strong&gt;还是&lt;strong&gt;直接断裂&lt;/strong&gt;？&lt;/td&gt;
					&lt;td&gt;是排队变慢，还是直接报错？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;撞完&lt;strong&gt;还能不能开&lt;/strong&gt;？&lt;/td&gt;
					&lt;td&gt;流量回落后能否自愈？&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;二次碰撞会怎样？&lt;/td&gt;
					&lt;td&gt;重试会不会造成二次打击？&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;注意第一个问题&lt;/strong&gt;：碰撞试验不是只测「多少速度会撞坏」，而是测&lt;strong&gt;撞坏的整个过程&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;后端也一样：&lt;strong&gt;「800 QPS 时崩」这个信息价值有限；「800 QPS 时连接池先满，然后所有接口一起超时，且流量回落后需要 4 分钟才恢复」才是真正有用的结论。&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二五种典型的崩溃形态&#34;&gt;二、五种典型的崩溃形态&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;崩溃形态&lt;/th&gt;
					&lt;th&gt;现象&lt;/th&gt;
					&lt;th&gt;根因&lt;/th&gt;
					&lt;th&gt;影响范围&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;① 超时级联&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;上游超时返回，但对下游的调用还在继续，资源被占住&lt;/td&gt;
					&lt;td&gt;超时链未递减（第 1 章 1.5 节）&lt;/td&gt;
					&lt;td&gt;扩散到所有接口&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;② 重试风暴&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;系统越慢，客户端重试越多，负载越高&lt;/td&gt;
					&lt;td&gt;没有退避、抖动、重试预算&lt;/td&gt;
					&lt;td&gt;自我放大，可能击穿&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;③ 连接池雪崩&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;所有连接被慢请求占住，新请求全部排队超时&lt;/td&gt;
					&lt;td&gt;池太小 + 查询变慢 + 无超时&lt;/td&gt;
					&lt;td&gt;该服务的所有数据库操作&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;④ 无界队列 OOM&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;请求堆积到内存耗尽，进程被杀&lt;/td&gt;
					&lt;td&gt;队列无上限、无拒绝策略&lt;/td&gt;
					&lt;td&gt;整个进程&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;strong&gt;⑤ 限流缺失&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;一个慢依赖拖垮整个服务的所有接口&lt;/td&gt;
					&lt;td&gt;没有隔板（按依赖隔离资源池）&lt;/td&gt;
					&lt;td&gt;全站&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&#34;怎么观察这五种形态&#34;&gt;怎么观察这五种形态&lt;/h3&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;形态&lt;/th&gt;
					&lt;th&gt;要采集的数据&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;超时级联&lt;/td&gt;
					&lt;td&gt;各层超时配置 + 各依赖的调用数与耗时&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;重试风暴&lt;/td&gt;
					&lt;td&gt;客户端重试次数、服务端 QPS 与服务端收到的实际请求数&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;连接池雪崩&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;active&lt;/code&gt;/&lt;code&gt;idle&lt;/code&gt;/&lt;code&gt;pending&lt;/code&gt;/&lt;code&gt;total&lt;/code&gt; 四条曲线 + 获取连接等待时间&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;无界队列 OOM&lt;/td&gt;
					&lt;td&gt;队列深度 + 堆使用曲线 + 拒绝/丢弃计数&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;限流缺失&lt;/td&gt;
					&lt;td&gt;各依赖的并发数分布（一个依赖是否占用了全部线程/连接）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三崩溃点是次要的恢复能力才是关键&#34;&gt;三、「崩溃点」是次要的，「恢复能力」才是关键&lt;/h2&gt;
&lt;h3 id=&#34;关键问题&#34;&gt;关键问题&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;① 崩溃点：多少 QPS 开始不可用？
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;② 恢复时间：流量回落后，多久回到正常？
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;③ 能否自愈：不重启能不能恢复？
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;④ 是否残留：恢复后有没有留下副作用（缓存被污染、连接泄漏）？
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;② 和 ③ 经常被忽略，但它们决定了故障的严重程度。&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>层级选择与成本</title>
      <link>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/07-selection-and-cost/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/07-selection-and-cost/</guid>
      <description>&lt;h1 id=&#34;37-层级选择与成本&#34;&gt;3.7 层级选择与成本&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;上一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/06-breakdown-testing/&#34;&gt;3.6 破坏性测试&lt;/a&gt;　|　下一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/08-lab3/&#34;&gt;3.8 Lab 3&lt;/a&gt;
配套代码：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/code/03-test-pyramid/07-selection-and-cost/&#34;&gt;03-test-pyramid/07-selection-and-cost&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一句话结论&#34;&gt;一句话结论&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;压测环境本身就是钱&lt;/strong&gt;（机器、数据准备、人力、时间），而不同层级的成本差几个数量级。&lt;strong&gt;能用便宜层级回答的问题，绝不用贵的层级&lt;/strong&gt;——这不只是省钱，更是为了&lt;strong&gt;迭代速度&lt;/strong&gt;，而迭代速度直接决定优化质量。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一用风洞试验按小时计费理解成本&#34;&gt;一、用「风洞试验按小时计费」理解成本&lt;/h2&gt;
&lt;p&gt;汽车研发里：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;试验&lt;/th&gt;
					&lt;th&gt;成本&lt;/th&gt;
					&lt;th&gt;一天能做几次&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;台架试验&lt;/td&gt;
					&lt;td&gt;几百元/小时&lt;/td&gt;
					&lt;td&gt;十几次&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;转鼓试验&lt;/td&gt;
					&lt;td&gt;几千元/小时&lt;/td&gt;
					&lt;td&gt;几次&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;风洞试验&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;上万元/小时&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;一次&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;工程师的直觉&lt;/strong&gt;：能用台架回答的问题，绝不进风洞。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;因为&lt;/strong&gt;：风洞一次要几小时，你一天只能验证一个假设；台架一次几分钟，你一天能验证二十个假设。&lt;strong&gt;假设验证次数直接决定你找到正确解的概率。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;后端完全一样。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二成本对照表&#34;&gt;二、成本对照表&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;层级&lt;/th&gt;
					&lt;th&gt;单次耗时&lt;/th&gt;
					&lt;th&gt;环境需求&lt;/th&gt;
					&lt;th&gt;数据准备&lt;/th&gt;
					&lt;th&gt;一天能做的轮次&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;① 微基准&lt;/td&gt;
					&lt;td&gt;秒级&lt;/td&gt;
					&lt;td&gt;一台开发机&lt;/td&gt;
					&lt;td&gt;无&lt;/td&gt;
					&lt;td&gt;上百&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;② &lt;strong&gt;组件基准&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;几十秒&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;一台开发机 + 容器&lt;/td&gt;
					&lt;td&gt;一次性准备&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;几十&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;③ 集成基准&lt;/td&gt;
					&lt;td&gt;几分钟&lt;/td&gt;
					&lt;td&gt;一台机器 + DB/缓存&lt;/td&gt;
					&lt;td&gt;一次性准备&lt;/td&gt;
					&lt;td&gt;十几次&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;④ 全链路负载&lt;/td&gt;
					&lt;td&gt;20–60 分钟&lt;/td&gt;
					&lt;td&gt;完整环境 + 独立压测机&lt;/td&gt;
					&lt;td&gt;每次可能都要准备&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;2–5&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;⑤ 浸泡测试&lt;/td&gt;
					&lt;td&gt;1–12 小时&lt;/td&gt;
					&lt;td&gt;独占环境&lt;/td&gt;
					&lt;td&gt;一次性&lt;/td&gt;
					&lt;td&gt;&amp;lt; 1&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;⑥ 容量测试&lt;/td&gt;
					&lt;td&gt;数小时&lt;/td&gt;
					&lt;td&gt;接近生产的拓扑&lt;/td&gt;
					&lt;td&gt;完整&lt;/td&gt;
					&lt;td&gt;&amp;lt; 1&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;看第 4 行和第 2 行的对比&lt;/strong&gt;：全链路一天只能试 2–5 个假设，组件基准能试几十个。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Lab 3：同一个接口的两层测试</title>
      <link>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/08-lab3/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/08-lab3/</guid>
      <description>&lt;h1 id=&#34;38-lab-3同一个接口的两层测试&#34;&gt;3.8 Lab 3：同一个接口的两层测试&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;上一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/03-test-pyramid/07-selection-and-cost/&#34;&gt;3.7 层级选择与成本&lt;/a&gt;　|　下一节：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/04-toolchain/&#34;&gt;第 4 章 工具链&lt;/a&gt;
配套代码：&lt;a href=&#34;https://www.dorkytiger.top/kotlin/kotlin-benchmark/code/03-test-pyramid/08-lab3/&#34;&gt;03-test-pyramid/08-lab3&lt;/a&gt;
预计时长：&lt;strong&gt;90 分钟&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&#34;一这个-lab-的目标&#34;&gt;一、这个 Lab 的目标&lt;/h2&gt;
&lt;p&gt;亲手验证本章的核心论断：&lt;strong&gt;不同层级会发现不同的问题，而且有些问题只有某一层能发现。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;做完之后你应该能对任何性能问题回答：&lt;strong&gt;「这个该在哪一层测，为什么不是另一层。」&lt;/strong&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;二任务清单&#34;&gt;二、任务清单&lt;/h2&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;#&lt;/th&gt;
					&lt;th&gt;任务&lt;/th&gt;
					&lt;th&gt;产出&lt;/th&gt;
					&lt;th&gt;时长&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;搭组件基准（Testcontainers + 采样循环）&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;ComponentBench.kt&lt;/code&gt; + 结果表&lt;/td&gt;
					&lt;td&gt;35 min&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;搭集成基准（Ktor 完整启动）&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;IntegrationBench.kt&lt;/code&gt; + 结果表&lt;/td&gt;
					&lt;td&gt;20 min&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;全链路压测（k6 从另一进程）&lt;/td&gt;
					&lt;td&gt;k6 报告&lt;/td&gt;
					&lt;td&gt;20 min&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;4&lt;/td&gt;
					&lt;td&gt;对比三层结果，写出「只有它能发现」的清单&lt;/td&gt;
					&lt;td&gt;实验档案&lt;/td&gt;
					&lt;td&gt;15 min&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id=&#34;三任务-1组件基准&#34;&gt;三、任务 1：组件基准&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;准备&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用 Testcontainers 起 PostgreSQL（&lt;strong&gt;不要用 H2&lt;/strong&gt;）。&lt;/li&gt;
&lt;li&gt;建表并灌 &lt;strong&gt;10 万行&lt;/strong&gt;数据，用&lt;strong&gt;幂律分布&lt;/strong&gt;（前 1% 的用户占 30%–40% 的查询）。&lt;/li&gt;
&lt;li&gt;建必要的索引，&lt;strong&gt;故意留一个没有索引的列&lt;/strong&gt;作为对照。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;要测的四件事&lt;/strong&gt;（分开测）：&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;#&lt;/th&gt;
					&lt;th&gt;测什么&lt;/th&gt;
					&lt;th&gt;预期发现&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;1&lt;/td&gt;
					&lt;td&gt;主键查询 &lt;code&gt;findById&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;走索引，P99 应该很低&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;2&lt;/td&gt;
					&lt;td&gt;二级索引查询 &lt;code&gt;findByUserId&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;走索引 + 回表&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;3&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;无索引列查询&lt;/strong&gt; &lt;code&gt;findByStatus&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;⚠️ 全表扫描，P99 随数据量线性恶化&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;4&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;批量查询 vs 循环单查&lt;/strong&gt;&lt;/td&gt;
					&lt;td&gt;量化「消除 N+1」的收益&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;方法要求&lt;/strong&gt;：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
