post: first-person voice pass on the 499 post (EN+ZH, no second person in body)
Deploy / build (push) Successful in 25s
Deploy / build (push) Successful in 25s
This commit is contained in:
1 parent
80414ff2c4
commit
f5f8e74a92
2 files changed
+7
-7
No files matched your search
@@ -266,7 +266,7 @@ rewrite did not quietly drop a control.
|
||||
1. **A dashboard endpoint is not a query interface.** It is the most frequently called and least
|
||||
cached surface in an admin UI. Anything O(n) over user data belongs in a background job with a
|
||||
publish step, not in the GET that a browser polls on focus.
|
||||
2. **Your timeout budget is the smallest hop, not the sum.** Four proxies each "allowing" 120 s do
|
||||
2. **The timeout budget is the smallest hop, not the sum.** Four proxies each "allowing" 120 s do
|
||||
not add up; the request dies at whichever clock expires first, and the application cannot see any
|
||||
of them. The application-side budget has to be an order of magnitude under the smallest one.
|
||||
3. **`499` deserves an alert.** It is the only signal that reports "the caller gave up", and it
|
||||
@@ -275,8 +275,8 @@ rewrite did not quietly drop a control.
|
||||
4. **Never trust `res.json()` on a proxied route.** Read text, keep the status, keep the first line.
|
||||
The error message is the only artefact the next engineer will have.
|
||||
5. **Stale-while-revalidate beats a bigger number.** Raising a timeout moves the wall; decoupling
|
||||
compute from read removes it — and it removes it for the worst case you have not measured yet
|
||||
(2,507 s here), not just the one you did (13.6 s).
|
||||
compute from read removes it — and it removes it for the worst case I have not measured yet
|
||||
(2,507 s here), not just the one I did (13.6 s).
|
||||
|
||||
---
|
||||
|
||||
@@ -294,5 +294,5 @@ rewrite did not quietly drop a control.
|
||||
`HTTP 503 · <!DOCTYPE html>…` and the investigation starts at the right layer.
|
||||
|
||||
The single most useful line in this whole exercise was the one that lied: `Unexpected token '<'`.
|
||||
An HTML error page handed to a JSON caller is not a syntax error — it is a proxy telling you, in the
|
||||
only language it has, that it stopped waiting before your code ever woke up.
|
||||
An HTML error page handed to a JSON caller is not a syntax error — it is a proxy telling me, in the
|
||||
only language it has, that it stopped waiting before my code ever woke up.
|
||||
@@ -219,7 +219,7 @@ if (data.refreshing) { autoRetryTimer = setTimeout(window.autoReload, 3000); }
|
||||
2. **超时预算等于最小那一跳,不是各跳之和。** 四层反代各自「允许」120 秒并不叠加:请求死在最先到期的那个时钟上,而应用一个都看不见。应用侧的预算必须比最小的那个还低一个数量级。
|
||||
3. **`499` 值得配一条告警。** 它是唯一一个表达「调用方放弃了」的信号,且天然绕开所有基于 5xx 的监控。从访问日志抓单条路径上 499 与 200 的比值,几乎零成本覆盖这一整类故障。
|
||||
4. **在反代后面永远不要信 `res.json()`。** 先读文本,留下状态码,留下第一行。下一个接手的人手里只有这条错误信息。
|
||||
5. **stale-while-revalidate 优于一个更大的数字。** 抬高超时只是把墙往后推;把计算与读拆开才是把墙拆掉——而且拆掉的是你还没量到的那个最坏值(这里的 2507 秒),不只是量到的那个(13.6 秒)。
|
||||
5. **stale-while-revalidate 优于一个更大的数字。** 抬高超时只是把墙往后推;把计算与读拆开才是把墙拆掉——而且拆掉的是我还没量到的那个最坏值(这里的 2507 秒),不只是量到的那个(13.6 秒)。
|
||||
|
||||
---
|
||||
|
||||
@@ -230,4 +230,4 @@ if (data.refreshing) { autoRetryTimer = setTimeout(window.autoReload, 3000); }
|
||||
- **正确性保留而非掩盖。** 撰写时的计数:341 篇笔记、1 个缺封面、47 篇待生成朗读——同一个计算,只是搬了位置。
|
||||
- **故障再也无法伪装。** 任何一跳再次中断,卡片会打印 `HTTP 503 · <!DOCTYPE html>…`,排查从正确的层级开始。
|
||||
|
||||
整件事里最有用的一行,恰恰是那行说谎的 `Unexpected token '<'`。把 HTML 错误页递给一个 JSON 调用方,不是语法错误——那是反代用它唯一会说的语言在告诉你:你的代码还没醒,它就已经不等了。
|
||||
整件事里最有用的一行,恰恰是那行说谎的 `Unexpected token '<'`。把 HTML 错误页递给一个 JSON 调用方,不是语法错误——那是反代用它唯一会说的语言在告诉我:我的代码还没醒,它就已经不等了。
|
||||
Reference in new issue
Block a user