用于高@- @ 性能 ASP_ .}NET moto\ MS K3widget 站点的新建筑Name
Stylo.Bot 发布序列的一部分 @. ASP=.@NET 用户界面 覆盖服务器@- @ rendered 仪表板表面 @; 寻找和遏制无约束增长 包括被约束状态背后的可靠性纪律 学习加快速度 先前的适应性工作@- @cache work_.
您如何快速回应复杂的仪表板而不发疯 @ ? @ 停止在请求路径@ MS K1 上添加这些响应?
问题在于 @: @ per @ -_ 请求粉丝@ MS K2 @ out
仪表板是一种非常昂贵的页面@.}它看起来像一个 URL @,}(但其实是一个配音引擎,上面印着“-”形大衣}♪.}*

不久即将在Stylo.Bot
信号闪烁是即将到来的仪表板结构@. 上面部署的仪表盘是当前的表面 @. 它的多@MS K2widget形状 是这个设计解决了.的问题
操作员看到一个仪表盘@;}服务器看到慢速 @-#移动集成 ,活名单和昂贵的窗口视图.}
flowchart TB
P[One dashboard page] --> H[Headline counters]
P --> T[Time-series chart]
P --> B[Top bots]
P --> E[Top content pages]
P --> C[Countries / filters]
H --> M[Shared hydrated page model]
T --> M
B --> M
E --> M
C --> M
M --> S[Versioned widget shingles]
S --> U[Independent HTMX OOB updates]
classDef outline stroke:#cbd5e1,stroke-width:1.5px;
classDef emphasis stroke:#38bdf8,stroke-width:2px;
class P,H,T,B,E,C,M,S,U outline;
class M,S,U emphasis;
linkStyle default stroke:#94a3b8,stroke-width:1.3px;
熟悉的 ASP.NET 实施时, 每个部件都有自己获取数据的部件@,}开始同步拨打这些电话。 然后在翻譯该页面前等待所有电话。 @.}
flowchart LR
R[One page request] --> W1[Summary query]
R --> W2[Time-series query]
R --> W3[Countries query]
R --> W4[Endpoints query]
R --> W5[Bot query]
W1 --> J[Task.WhenAll]
W2 --> J
W3 --> J
W4 --> J
W5 --> J
J --> V[Render response]
classDef outline stroke:#cbd5e1,stroke-width:1.5px;
classDef danger stroke:#fb7185,stroke-width:2px;
class R,W1,W2,W3,W4,W5,V outline;
class J danger;
linkStyle default stroke:#94a3b8,stroke-width:1.3px;
它与一个人和一个小数据组看得很快 大约10个独立电话重叠,}所以页面需要大概只要它最慢的部件 而不是它们的总和.
上 Stylo. 蝙蝠侠 上一个正常的页面加载意谓在网站上大约10个平行呼叫@/\QGateway 边界 @.#30- 天视图可以扫描超过100万行@MS K4} 一个静悄悄的负载已经是多@-\çsecond_.}在同时的交通下>,"P95"过了七秒钟 因为每个访客都在等待,Q和启动“,” 约十次昂贵的业务.}
平行主义是有用的 @.Per-请求 fan{-Out 是问题所在 在五个同时出现的观众}♪.}*,约十通电话在五十个竞合的呼叫中 ~♪MSk550个左右
平行扇*-_Out通过乘以在负载下摧毁系统的压力来更快地查看单一请求@.#
这对仪表板来说是错误的缩放曲线@ . @ 一个仪表盘是一个共享的观测面@ I. @ 它应该会变得更便宜, 因为更多的人看同样的东西@ MPK2# 没有更昂贵的@.}
| +正常多@-+Widget 仪表板 @ | +Signal Shingle仪表盘# | _ | |
|---|---|---|---|
| @ | }每份请求都启动自己的数据扇@-Out { | }请阅读一个即时的投影 *# | * |
| @ | @ 每一个部件都可以独立老化和失效 @ | @% 元件来自一代人\ MS K2} @ stamped model { | } |
| 更多浏览器创建更多的数据库工作 @ | @ 更多共享温暖模型和闪烁@ MS K2 @ | ||
| 装入会减慢响应本身@ | 负载伸缩恢复上升速度, 而反应保持快速 @ |
对于Stylo.Bot,, 仪表板在机器人激增或事故中最值钱@,恰好当数据路径处于压力下时 @. 因此对稳定的选择性首先:a fast_,}一个具有明确年龄的同步快照比一个理论上更新的页面更有用,因为这个页面慢一点+,部分或不可用@MS K7}
解决方案@:信号闪烁
信号闪烁将每个仪表板部件作为预@ - @ rendered, self @ MS K2} 足装的页面片段{. 它的身份是它所代表的数据,以及它是如何被实现的#:* 元件%,}行,}窗口_,}过滤器和显示参数♪.}刷新通道不是这个身份=.}
它的指纹很简单 widget + normalised parameters + data-surface generation. 国家更新不应取消活的@- visitors card @; 更改后的过滤器不应该让其他部件都感冒@MS K3 新一代只重新-Kkeys 受影响的shingle}.
这些碎片生活在一个捆绑的 LFU 缓存@. @}溫暖讀者讀者: 持續監視的元件
信号R 客户端询问受影响的部件批量@;}# HTMX 应用返回 @ -_ of@ MS K1_ 带碎片 与 白痴@. 信号带有肮脏的提示@,}从不复制仪表板数据 .
在图案中的“,”中 信号讯号 意指““”或“考虑刷新”和 “”;” 闪闪 是独立可处理结果@. @%
架构将响应合同与刷新工作区分@. @% 此回复是静态 @ -} like:} a fast\ ,}来自缓存@ MS K4}的一致快照。 动态侧面是一个单独的\ MSKO5}预算流程, 可以更新并交付已更改的碎片@ I.load 在不减慢页面回覆时可以保持恢复速度 *.}
如果每个失手者都启动新的数据库扫描 , ,那么昂贵的工作仍然非常昂贵。 “.”信号星光使用两个“-”级缓存和一个刻意窄小的暗藏器“MS K5”
flowchart LR
D[Gateway<br/>authoritative events] --> B[Incremental window buckets<br/>data stays single-source]
B --> C[Delivery cache 1<br/>hydrated page result]
C --> S[Delivery cache 2<br/>versioned OOB widget HTML]
S --> R[Request path<br/>read + Razor shell]
T[Schedule tick/poll + LFU demand] --> W[Bounded prewarm waves]
W --> B
W --> C
X[Coalesced SignalR dirty beacon] --> U[HTMX batch update]
U --> S
classDef outline stroke:#cbd5e1,stroke-width:1.5px;
classDef emphasis stroke:#38bdf8,stroke-width:2px;
class D,B,C,S,R,T,W,X,U outline;
class C,S,W emphasis;
linkStyle default stroke:#94a3b8,stroke-width:1.3px;
数据预测和交付缓存
两者的区别是: 型号模型 和其实际数额 构件交付装置任何藏匿处都无法成为探测数据的权威
数据预测=:增量桶
该网关拥有数据@., 它在 @ -memory LFU中持有一个捆绑的\ ,, 在“ MS K2memoryLFU” 里对递增\ ,窗口式桶的投影。 “ 30-day lipple reservation@ MSQ5 一个工作集+, 不是第二个数据存储器.}
使用精细的桶用于 6 @-}小时和 24-hour changage table_,}小时对长窗口的滚动@.}关键是请求的窗口将桶合起来,而不是重新-}阅读原始事件=.}
last 24 hours → merge 288 five-minute buckets
last 30 days → merge 720 hourly buckets
not
last 30 days → scan and aggregate 1,000,000+ event rows again
新的观察更新了最新的桶.}历史部分没有被重新删除, 因为页面已加载@.}这个网关仍然是唯一的作家和唯一决定探测意味着什么的地方 @.}
运货缓存 @1:水分含量模型
上流@,}网站缓存水化仪表板模型,}由正常部件键入的...
保存 CSRF 值@,}认证chrome @,}在请求中的标记和非括号 * - rendered shell where they belongs *\ MASK3}
在冷键上 @, 返回一个清晰的变暖状态, 而不是同步重计@. 只有滴答器能赢得新的页面结果 @MS K2 后来读到为最新成功的一代服务, 即使新来的在飞行中#.
发送缓存@ 2: @ 闪烁转换缓存
仪表板刻意分割@:(网关拥有数据) @;(网站拥有Razor)和浏览器关系.(交付快递缓存){2}为本地小更新服务,而不会成为相竞的数据存储}#;(它只持有来自网关_-(后背页面模型)的版本HTML}%.*}
一旦页面模型存在 ,}一元件可以作为 OOB 元素制成,并保存在连接的 LFU Shiingle 缓存中,带有安全性 TTLQMS K1 一个温暖的闪烁绕过构成和 Razor 翻譯\ ; {一个错误读取已经@-}/ warm 页面结果(如果可能) @, 使该部件只添加\ MPK5} hx-swap-oob="morph"@, 并存储结果 在它的指纹@.
批次端点分区部件组成温暖的指纹, 而 miss@ , 构成支持的错误一次 * MS K1}\ 返回 OOB HTML .} a 摘要或国家更改为\ MPK3\ keys 只表示表面@.}
这不是多余的 caching. 发送缓存 @ 1 回答 @ MPK2 什么是一致的仪表板模型@?” 交付缓存\ MS K4 答: @“ 这个浏览器岛能接收什么\ MASK6 第一个可以共享构成=;}第二个让部分更新几乎自由Q.
缓存边界@: @
回应缓存值得直接比较“. 正常响应缓存存储 一个不透明的 HTTP 解答 “; 独立缓存部件开发独立的过期和失效模式@. ”页面可以快速加载, 同时不再描述一个一致的状态. 在操作仪表板上 < , 与它下面的行不符的计算使得操作员调查幽灵>=.}
熟悉的缓存模式都是有用的 它们只是保护不同的边界
| “ | ”模式“ | ”它储存什么? | ||
|---|---|---|---|---|
| HTTP 响应缓存 | HTTP 响应@, 通常以 URL 为键, 并请求 @-vary 规则 @MS K3 公众获得端点和 CDN}- 方便的內容 @ | 它根本不知道 仪表板=' 内部部件或者它们的数据是否同意. @ @ @MSKO8 | ||
| ASP.NET 输出缓存 | 生成服务器输出@, 且有明确的差异和驱逐政策 @ | 昂贵的页面,并有一个小#, 稳定请求}-key space { | 它可以快速缓存此页面} , 但它仍然是不透明的页面结果而不是一个协调的直播投影_. □ | |
| @ ,_ 或独立缓存的碎片@ | _ Pages 其铬稳定且小动态区域是真正独立的 @ | } 它使每个洞都拥有自己的缓存生命周期\ ;,这就是仪表板如何在内部变得前后不一致吗? | ||
| 信号闪烁 | 1 水合 , 一代- 標章頁樣本加上版本的部件交付碎片 | 一个其部件必须独立更新的仪表板 和 继续描述一个状态 @ | @ 缓存边界为配制的投影@ MS K1} shingles 是来自它的 ,} 不是竞争商店 @ MPK3 * @ I | } |
关卡@-2_闪烁 是 输出缓存@ , @ 故意小和碎片@ I-_ magid @ MS K2} 区别在于碎片不能独立决定数据现实 * . 内容模型由 1 代以下的 first\ ,\ 组成 ;\ 每一个闪烁都是该型号的成份 's cliche=.}
flowchart LR
D[One authoritative<br/>gateway dataset] --> G[Generation 184]
G --> M[One hydrated<br/>page model]
M --> H[Headline shingle<br/>generation 184]
M --> T[Chart shingle<br/>generation 184]
M --> B[Bot-list shingle<br/>generation 184]
M --> C[Country shingle<br/>generation 184]
H --> P[One coherent page]
T --> P
B --> P
C --> P
classDef outline stroke:#cbd5e1,stroke-width:1.5px;
classDef emphasis stroke:#38bdf8,stroke-width:2px;
class D,G,M,H,T,B,C,P outline;
class G,M,P emphasis;
linkStyle default stroke:#94a3b8,stroke-width:1.3px;
当数据改变@,}当受影响的成分接收到新一代的#. 浏览器可以简要地看到上一个版本, 而更新在飞行中 @,, 但这个年龄是明确和相交的.。 它从来不是一组单独的%-}拥有的缓存, 其中对 &“Now_”.}提出相互矛盾的要求
一个权威 , 一种构成的一代 MS K1 许多可重复使用的投射碎片.
逐步提升第二
Stylo.Bot 仪表板 Razor 雷乱 在 JavaScript 运行前的 , 连接和导航@.HTMX,信号 阿尔卑山 然后加强该页面,而不是替换它 @.}#
flowchart LR
R[GET dashboard] --> S[Razor SSR<br/>complete useful HTML]
S --> V[Operator can read<br/>and navigate now]
S --> H[HTMX enhancement]
S --> A[Alpine enhancement]
S --> G[SignalR enhancement]
G --> D[Dirty beacon<br/>not dashboard JSON]
D --> H
H --> O[GET OOB widget batch]
O --> W[Versioned HTML shingles]
W --> M[HTMX / Idiomorph morph]
A --> I[Local UI state<br/>menus, filters, affordances]
classDef outline stroke:#cbd5e1,stroke-width:1.5px;
classDef emphasis stroke:#38bdf8,stroke-width:2px;
class R,S,V,H,A,G,D,O,W,M,I outline;
class S,W,M emphasis;
linkStyle default stroke:#94a3b8,stroke-width:1.3px;
浏览器文件夹
Razor 雷乱 使服务器上的页面@. @% HTMX 请求和互换 HTML 岛屿@. @ 信号R 带有小变化信标@. @% 阿尔卑山 本地交互状态@. @% 白痴 更新一个岛屿, 同时保存稳定的 DOM 节点, 如焦点和悬停状态@. @ @
删除其中任何一个, 且SSR页面仍然有用@; @+3 添加所有三个并获得 live @, @ lowQ-_ churn 更新@ .}
为什么这不是一个客户端? -+_发送仪表板
基本原因是简单@: 仪表板必须对于每个客户端有用, 而不需要 JavaScript. 一个脚本已禁用的浏览器@ ,一个缓慢连接, 一个辅助客户端{, 一个自动化工具或爬行器仍然接收有意义的 HTML_,链接}MS K6表格和控制}MPK7JavaSchrippt 改进了体验=; 它不是入场券□.
客户端@- @ 发送仪表板在本地有丰富的应用程序状态为产品时非常合适 =% .} 它会让这个仪表盘依赖 JavaScript 才能显示数据.} 。 它还会在浏览器中重新创建构成逻辑, 或者使浏览器协调部件 APIs_ MS K3 = 将它变成新颖性( MSSK4) {,} 错误和一致性 . 的又一个状态参与者
| +客户端@-+发送仪表板 @ | +信号闪烁仪表盘# | _ |
|---|---|---|
| 浏览器获取 JSON 并拥有已提供视图的状态@ | 服务器构成该模型,并使 HTML;浏览器增强它 @ | |
| @ | 客户调节独立回应@,装货状态和简数据 { | 服务器印章在交付前统一生成 |
| 第一个有用的内容取决于 JavaScript 和 API 补全@ | }第一个有用的内容是 SSR HTML=;}现场更新 | |
| “ | 最佳当富饶的本地应用状态是产品时, 当仪表板是一个共享的业务预测时, |
该设计使仪表板在默认情况下保持通用性@:网关数据和组成在服务器 @,}网页上提供的数据和构成,并在浏览器中的可选捷径, 和可选短距{-}生活互动状态*.
刷新是预定任务@, @}不是交通意外副作用
重新刷新在页面请求@. @ 这是硬边界@ :} 一个冷读返回变暖结果 MS K2} 而只有滴答器组成\ .}页面请求是一致投影的阅读@ MPK4}从不成为开始昂贵数据工作的借口 *.}
协调者队列被固定并最近@-}读取信封 @,}然后在捆绑的波浪中用页面#-count and wall_-clock building*.o} 在它分批匹配工作的波里 =;}一个计量的成本预算可以阻止以后的波流完全.}这不算什么 Task.WhenAll 使用新名称@. @%
组合货币限额是正确性的一部分 @: 刷新回路获得已知的能力预算@, never a unfounded communited . 完全热切的请求根本不包含构成或 Razor 提供}#.
管弦乐队=,}不是暴风雨.* 这就是操作规则 .
升温前是覆盖@, @% 不是愿望的缓存
只热的缓存无法保护第一个请求 之后 此请求已到达@ . @ so the register has two jobs=. @ Pinned 默认缺省 保留真实的 @6@h,}#24_H•,}{7}和@30*d 窗口选择取暖#MS K6} 要求的--gated信封 覆盖过滤器实际使用的人,}按存取计数和中度计算排序 <%.>}只有真正的请求才能保存一个活的{.
flowchart TB
P[Pinned default windows<br/>6h · 24h · 7d · 30d] --> Q[Warm queue]
L[Recently read filtered views<br/>LFU hotness order] --> Q
Q --> G{Tick budget<br/>still available?}
G -->|yes| W[Bounded warm wave<br/>compose once, store model]
G -->|no| N[Defer to next tick<br/>serve prior generation]
W --> H[Delivery cache 1<br/>hydrated page model]
H --> Z[Delivery cache 2<br/>rendered on demand]
classDef outline stroke:#cbd5e1,stroke-width:1.5px;
classDef emphasis stroke:#38bdf8,stroke-width:2px;
class P,L,Q,G,W,N,H,Z outline;
class Q,W,H emphasis;
linkStyle default stroke:#94a3b8,stroke-width:1.3px;
如果UI提供四个正常窗口, 暖气者知道第一个#,}3/4的预产物路径仍为冷 @.}
LFU不只是驱逐 : 这是需求信号
LFU 不只是驱逐在这里@. @Access is the demand signal signation <:Q} 它决定了哪些仍然是常住的#,, 哪些应该重新恢复工作? ,}和什么可以安全地消失吗?. 让无限制的过滤空间能够被控制.}一个国家过滤器整天监视着
压力下的稳定
传统的实时仪表板通过做更多的工作来应对更多交通流量,然后在操作员最需要的时候变得最少有用。 “.” 信号光照(Signal Shingle) 扭转了这种关系“.” 更新控制器根据预算“MS K3” 昂贵的周期衡量刷新成本。
refresh cost <= budget → preserve requested cadence
refresh cost > budget → lengthen effective cadence
cost settles → cautiously shorten it again
这是对受保护资源的闭路循环@, @% 绝非从原始 RPS.} 在加载系统下向静态快照移动, 而不是创建更多的数据库工作来维持一个无法实现的活性承诺@ ._ Stylo @ MSQK3# Bot 因此随着事件变大而变得更平静了 @ MPK4}
负载使仪表板减少工作@, @ not more @.}所以图案会退化而不是崩溃=.}
这是最后已知的一致投影@,_受新政策约束, 并贴上诚实的标签 @.}
静态和动态设计
上述分离使仪表板有一个快速响应合同和一个单独预算的刷新流程@. 调度机-驱动的到期检查 @,非选用的活部件信号R加速度和重新连接保持动态侧面的回同步值}#. 即使当快照变老时反应仍然很快,年龄依然可见.
这样系统就可以在两个有用的模式之间连续滑动@ : @
quiet / cheap refreshes → dynamic dashboard, short effective cadences
busy / expensive refreshes → static-like snapshot, longer declared cadences
这不是在游泳池失败后添加的恐慌开关@.
更新属于部件@ : @ 1 non MS K1} 可转让变量
不是每个部件都配得上相同的新鲜@. @ 趋势图或终点排名可以是小于 @ ;} 最近访问者或当前分数列表的分钟或小时, 或者需要更紧一点的candence@ MS K2 。 音节与元件一同生活\ ' @ sregness class # .#
-=YTET -伊甸园字幕组=- 翻译: |---|---|---:|---| @|Agress accountry_BARBAR|},}趋势: ,}(各国) <,}♪端点:"|>-分钟到一个小时#|} 信号变化足够缓慢,稳定性比churn@.}更宝贵 @|ZLive |Q}最近的访客,QA 会话MS K3Q 名字\ ,Q分数{,Q 威胁@|Q 约一分钟左右}#|Q 操作员正在寻找当前运动_.Q NSK9}
两个明显相同的部件可以要求不同的逗号@ . @ 在缓存密钥中插入 candence 重复数据\ ;} 接受第一个可留下一个较晚的消费 stale.}
变量是简单的@: @%
共享缓存条目绝对不能为粘贴器服务, 而不是任何活跃的消费者要求的. @% 1
正式的:
effective cadence(entry) = MIN(requested cadence of every active consumer)
Cadence is a per-消费者 下楼“,”不是签名的一部分“.” 如果一个消费者要求“MS K2 秒”,另一个5分钟“,” 一个共享的条目复习,每个@60 秒” @.“当快速消费者离开<,> 重新计算最小值$; 时, 当没有消费者继续保留‘,’ 停止排期让 LFU收回它’.}
活动消费者是指根据实际请求而设定的短期-Living,可再生需求租赁。
诚实铬和一致性规则
一个适应性系统应该诚实地对它的适应性表示 <. 元件铬> 显示当前有效的 cadence : _ @ “ > 更新到每个@60 s”, * @“ #%”, @ MPK8 data
有几条规则需要 保持一个诚实的投影
- 发行邮票 每个块@ / @ shingle 记录它从 .} 建立的数据生成。 信标和响应生成邮票是比较@ I,} 这样旧的更新无法覆盖较新的视图Q.
- 折叠信号 . 繁忙的探测器每秒可能生成许多事件, 信号路径将它们分解成一个肮脏的信标和一个刷新决定, 而不是点燃浏览器或更新环@ .
- 重新连接后再同步@ . @ 重新连接不作为未发生意外的证据@. @ a dueQ-_ check 关闭缺失的@ -# pulse 差距确定=.}
- TTL 折叠后退@ . @ 保留区块一旦超过等级,且无法刷新#,,便不能成为不朽的@.。 它会变得寒冷 @/}升温而不是永远静默地躺着*.
- 无内容渗漏@. @% 活闪光可能包含名称@, @ 指纹或计分@ .} 它们的内容留在记忆中@ I,没有登录@ MPK3{ 并且任何诊断都默认会修改@ OMK4}
目标不是即时一致 . 它是一个年龄和生育相交的预测
利益和交易
其好处是结构上的“:”稳定请求 lantency,一个一致的页面生成元件“MS K2 分享公众观点的工作” “, 和没有 JavaScript. 没有JavaSccripp}MSK4 在压力下,这个系统提供诚实老化的预测,而不是将每个页面视图变成更多的数据库压力 •.
成本是真实的 @.}这个架构增加了一个调度器% ,}缓存密钥\ , 生成跟踪@,}需求租赁和可观察性, 正常控制器不需要 需求租赁且普通控制器在使用前可能显示变暖状态 =.}操作员必须选择可接受的新鲜度约束而不是假装每个表面需要 real_ MS K6-time data.} 每个复制网站也需要自己封闭的缓存。 刷新信号 <;> 缓存内容刻意为本地@MS K9}不是新的共享权限_.}
对于每个响应都是独一无二的 ,}或者对于真正要求每个用户立即看到每一个变化的表面来说 它是一个非常适合共享,}读@-Heavy操作仪表板 非常合适
信号闪烁拼写了熟悉的 ASP.NET piets@: 一种LUU},SignalR,批量合成 *, RazorMS K5HTMX 和一个有真实货币汇率预算的排程器.这个网关保留权威=;网站提供一个投影 <;>浏览器接收小版本碎片\MSC9
仪表板保持快速,因为观测不再导致计算@. @