作者:Michael T. Nygard,2007 年,ISBN:978-0-9787-3921-8
我对这本书的摘要和评论。
审查
在我读过的书中, 发布它! 是我要求所有“高级”开发人员阅读的一本(连同诸如 架构企业解决方案:基于互联网的高性能系统的模式 )。特别是关于稳定性及其模式和反模式的第一部分是必读的。在不知道和应用它们的情况下,我们创建了对问题做出反应的系统,就像干燥的大草原对燃烧的火柴一样。我还发现在最后一章的旁边,#17 透明度非常有价值,尤其是 OpsDB 的指标和设计以及观察实践。
我在摘要中遗漏的一件事非常值得一读,那就是介绍每个部分的战争故事,它们真的很有趣、鼓舞人心和有教育意义。
额外链接
- 释放它!幻灯片: http://gotocon.com/dl/jaoo-sydney-2009/slides/MichaelT.Nygard_FailureComesInFlavoursPart2.pdf
- https://github.com/Netflix/Hystrix/
- Netflix 的 Dependency Command 谈论使用断路器和线程池限制 http://techblog.netflix.com/2012/02/fault-tolerance-in-high-volume.html
- 云应用程序的 MSDN 指南:设计模式 - 断路器和更多非常有用的模式
稳定
稳定性 x 长寿错误
稳定性反模式
集成点
集成点 = 调用 DB、WS、...。稳定性风险#1。
- 每一个最终都会失败
- 许多可能的错误:网络,应用程序,......
- 症状:违反协议、响应缓慢、挂起、突然关闭连接……
- 当远程系统出现问题时,采取防御措施以防止级联故障——断路器、超时、解耦中间件、握手;使用 Test Harness 进行测试
- 例如:连接被拒绝(注意:可能需要很 长时间 才能发现您无法连接,f.ex。当它正在侦听但无法处理请求时,或者当 ACK 未到达并且它不断重试时);防火墙可能会在不告诉任何人的情况下丢弃旧连接,静默丢弃数据包
连锁反应
有缺陷的负载平衡应用程序(通常是资源泄漏或与负载相关的崩溃)。如果在一个实例中触发了缺陷并且它失败了,那么其余的更有可能失败(增加负载,......)。 Bulkheads 可以通过将节点分成单独的集合来提供帮助,希望在不同的时间发生单独的、较小的连锁反应。可能导致调用层发生级联故障。
- 一台服务器宕机会危及其余服务器
- 寻找资源泄漏
- 寻找模糊的计时错误——流量会触发模糊的竞争条件;如果死锁杀死了服务器,那么增加其余服务器的负载也更有可能触发死锁
- 用 Bulkheads 防御,在调用方使用 Circuit Breaker
级联故障
= 一层的问题导致调用者出现问题——通常是由于资源池耗尽
- 对集成点多疑
- CF 通常是由资源池引起的,当线程检出资源时资源池耗尽并被阻塞,因为它们的调用永远不会返回并且其他线程等待资源。安全资源池应始终限制线程可以等待检出资源的时间。
- 断路器通过避免调用有问题的集成点来保护您的系统,使用超时确保您可以从调用到有问题的集成点中返回
用户
- 用户消耗内存 => 最小化会话大小,仅将会话用于缓存,以便您可以在内存紧张时清除其内容(并在需要时重新创建)。 F.ex.在 Java 中使用 SoftReferences。请注意会话一直持续到最后一次交互 + 超时,默认为 30 分钟(乘以太多用户......)
- 用户做一些奇怪的、随机的事情,不要指望他们会像你期望的那样表现;如果有弱点,他们会找到的
- 恶意用户在那里 - 保持最新状态,防止 SQL 注入等。
- 有时用户进来的真的非常多 => 挂起、死锁、模糊的竞争条件;运行特殊的压力测试以锤击深层链接或热门 URL
- 当心机器人和索引蜘蛛等人工用户——他们会立即发出许多请求,可能会忽略 cookie(=> 每个都会产生一个新会话)
阻塞线程
- f.ex.从连接池中检出资源、处理缓存或对象注册表、调用外部系统或同步线程时
- 阻塞线程模式是大多数失败的直接原因;导致连锁反应和级联故障
- 仔细检查资源池——线程经常被阻塞; f.ex.数据库中的死锁或不正确的异常处理(因此无法释放连接)
-
使用经过验证的并发原语而不是创建自己的原语(请参阅
java.util.concurrent
) - 用超时来防御,这样就不会永远存在死锁——总是使用它们
- 当心您看不到的代码 – f.ex。在图书馆
自我否定的攻击
例如:营销部门发给选定用户组的特价邮件——如果用户大量涌入,他们将进一步共享该页面。所有服务器都在等待获取锁以更新相同的流行项(=> 更喜欢无共享架构或至少应用解耦中间件或通过冗余和同步协议使共享资源本身可水平扩展)。
- 被告知——确保如果有营销活动,你就知道了。确保它不使用深层链接(绕过您的缓存代理),观看我们的 URL 中的嵌入式会话 ID。为这些优惠的第一次点击创建一个静态的“着陆区”页面。
- 在流量激增的情况下保护共享资源。注意增加的前端负载会导致后端处理呈指数增长。
- 期望快速重新分发(即广泛传播)任何很酷或有价值的产品——没有分发给有限用户集这样的事情
缩放效应
当系统按比例放大时,小规模工作的东西会导致问题。每当我们有多对一或多对少的关系时,当“更多”的一面增加时,我们可能会遇到问题,例如。从 2 AS – 1 DB 到 10 AS – 1 DB 时,数据库可能会崩溃。一个常见的问题是点对点通信。
- 检查生产环境和 QA 环境之间的规模差异以发现规模效应——在小型环境或一对一环境中运行良好的模式可能会在您转向生产规模时变慢或完全失败
- 注意点对点通信——它的扩展性很差,因为 # connections 随着参与者的平方而增加
- 注意共享资源——它们可能是瓶颈、容量限制和对稳定性的威胁。如果你有一个,请对其进行严格的压力测试。如果它变慢或锁定,请确保其客户将继续工作。
不平衡的容量
UC 是缩放效应的一个特例:关系的一方比另一方扩大得多。例如:许多 Web 服务器通常主要提供静态内容,后端服务器只提供少量动态页面;如果流量模式(工作负载)突然发生变化,即许多用户使用动态功能,前端服务器将淹没为数不多的后端服务器。匹配它们应对罕见峰值的能力可能是不切实际的,因此让它们在面对海量请求时具有弹性。对于前端,当响应变慢或连接被拒绝时,断路器将通过减轻后端的压力来提供帮助。对于后端,使用握手通知前端限制请求。还可以考虑使用 Bulkheads 在后端为其他交易类型保留容量。
- 检查、比较服务器和线程数,尤其是在 Prod 与 QA 中
- 观察附近的缩放效果和用户
- 强调接口的两侧;如果您在其最昂贵的事务上用比历史最大值多 10* 的请求敲打后端,它会失败还是变慢并最终恢复?当后端停止响应或变得非常慢时,前端会做什么?
反应慢
生成缓慢的响应比拒绝连接或返回错误更糟糕,因为它占用了调用者和被调用者的资源。它们通常是由过度需求或潜在问题引起的,例如。内存泄漏和由此产生的垃圾收集、网络拥塞。
- Slow Responses trigger Cascading Failures,上游系统速度太慢,容易出现稳定性问题
- 对于网站,响应缓慢会导致更多流量,因为用户点击“重新加载”
- 考虑快速失败——f.ex。如果您的 SLA 要求在 100 毫秒内响应并且最近 20 次调用的移动平均值超过它,您可以开始拒绝请求(上游系统必须为此做好准备)
- 寻找内存泄漏或资源争用(例如数据库连接太少)
SLA 反转
SLA 反转 = 必须满足高可用性 SLA 的系统依赖于较低可用性的系统。但是您可以提供的最好的 SLA 是您对最差 SLA 的依赖之一。
解决方案:1) 与较低的 SLA 系统分离,以便您的应用程序可以在没有它们的情况下继续运行,优雅地降级。解耦中间件非常适合这个。至少使用断路器来保护您免受依赖。 2) 确定一个现实的 SLA,而不是整个系统,关注特定功能/特性及其依赖关系的可用性。
例如:允许客户在无法安排交货时继续购买。
- 对于每项服务,您的系统都取决于传输层可用性、命名服务 (DNS) 和应用程序级协议,其中任何一项都可能失败。
- 如果天真地构建,系统的故障概率是任何组件或服务发生故障的联合概率,因此 P(up) = (1 – P(internal failure)) * P(dependency 1 up) * … * P(依赖 N 向上)。因此,对于具有 99.9% 可用性的五个依赖项,我们最多可以获得 99.5%。
无限制的结果集
“带着怀疑的态度设计,你就会成功。问:“X 系统能做什么来伤害我?”然后设计一种方法来躲避、躲避、俯冲、俯冲和躲避你所谓的盟友投掷的任何扳手。” p95 其中一个系统是您的数据库——如果它突然返回 500 万行而不是通常的数百行怎么办?
- 在测试/开发中使用实际的、生产规模的数据量
- 不要依赖数据生产者来创建有限数量的数据
- 对其他应用程序级协议施加限制:WS 调用、RMI、XML-RPC ……都容易返回大量对象,从而消耗过多内存(并在用户失去兴趣后继续工作很长时间)
- 无限制的结果集是导致响应缓慢的常见原因;他们可能是由于违反稳态
稳定性模式
使用超时
你很少想永远等待(或几分钟)。
- 适用于集成点、阻塞线程和缓慢响应;它们防止对 I.Points 的调用变成 Blocked T.,从而避免 Cascading Failure。
- 结合断路器(太多时触发)和快速失败(通知您的呼叫者您无法处理请求)。
- 适用于从意外故障中恢复——当一个操作耗时太长时,我们有时不关心原因,我们只需要放弃并继续前进
- 考虑延迟重试——导致它们的网络或远程系统问题不会立即得到解决,因此立即重试只会使情况变得更糟,并使用户等待更长时间以等待不可避免的故障响应。
HttpClient 示例:
RequestConfig.custom()
.setConnectionRequestTimeout(1000).setConnectTimeout(1000).setSocketTimeout(1000).build();
断路器
Circuit Breaker包裹了一个Integration Point,像保险丝一样工作,当对系统的多次调用失败或连续超时时“熔断”(打开),从而使后续请求快速失败,而不会消耗太多资源并易于加载远程系统。有时它会允许调用以检查系统是否再次响应。
它非常适合优雅降级,即在子系统变得不可用时为用户提供有限但仍然有用的功能。
- 如果它有害,请不要这样做——CB 是保护您的系统免受各种集成点问题影响的基本模式。当他们有困难时,不要再打电话给他们了!
- 与超时一起使用
- 向 Ops 公开、跟踪和报告其状态更改
MSDN 的断路器模式 页面非常好。 Martin Fowler 对 Circuit Breaker 的介绍, 其中包含一个简单的 Ruby 示例实现和有用的链接。
实施。在 Java 中使用 Spring AOP 和 JMX: https://code.google.com/p/jianwikis/wiki/CircuitBreakerDesignPattern,Clojure 实现 。
舱壁
舱壁是船上的水密舱室;当有一个洞时,水只会淹没一个隔间,从而使船免于沉没。同样,您可以对资源(服务器等)进行分区并将分区分配给特定的客户端/功能,以便故障不会影响所有和/或更重要的功能/客户端免受不太重要的功能触发的故障。物理冗余是最常见的形式,可以防止硬件故障。一个小规模的例子是将进程绑定到 CPU 的一个子集。在进程内部,您可以创建专用于不同功能的单独线程组——f.ex。用于管理功能的单独请求处理线程池。例如:航班状态功能失败不会停止办理登机手续。
- Bulkheads 模式分区容量以在发生坏事时保留部分功能
- 分区导致容量使用效率降低(但虚拟化可能会在一定程度上减轻这种情况——按需在分区之间移动虚拟机)
- 选择一个有用的粒度——应用程序中的线程池、服务器中的 CPU 或集群中的服务器
- 当许多系统依赖于您的应用程序时,对于共享服务模型非常重要;当连锁反应发生时,你不想让他们全部倒下
稳定状态
对于每一种积累资源(数据库中的数据、日志文件、缓存消耗的内存)的机制,其他一些机制必须回收该资源。
- 避免摆弄——人工干预会导致问题;通过自动化消除重复性人工干预(磁盘清理、夜间重启)的需要
- 使用应用程序逻辑清除数据——应用程序比 DBA 更了解如何在保持一致性和完整性的同时清除旧数据(f.ex.wrt ORM)
- 限制缓存可以消耗的内存量,以免引起问题
- 滚动日志——不要保留无限量的日志文件,根据大小配置日志文件轮换
快速失败
如果一个系统可以提前确定它会在操作中失败,那么最好快速失败。
- 避免缓慢响应和快速失败——如果您的系统无法满足其 SLA,请快速通知调用者,而无需等待错误或超时(<> 断路器)
- 预留资源,尽早验证集成点——例如,如果关键的断路器打开,则立即失败
- 用于输入验证 - 甚至在您保留资源之前进行基本的用户输入验证,如果 f.ex. 不会浪费它们。缺少必需的属性
- 例如:如果系统中已经有太多用户,则立即拒绝连接(=> 节流到可管理的水平,以便我们为已经存在的用户保持合理的服务水平)
握手
- 调节它们之间通信的设备之间的信号;它通过允许服务器限制自己的工作负载来保护服务器。遗憾的是,HTTP 和 RMI 不能很好地握手。
- 创建协作需求控制——使用客户端-服务器握手将需求限制到可服务水平;两者都必须构建以支持它
- 将健康检查视为缺少 H 的应用程序级解决方法,在额外调用的成本远低于调用和失败的成本的情况下使用
- 将 H. 构建到您自己的低级协议中
测试线束
测试工具模拟集成点的远程系统,可以模拟许多错误(网络、协议、应用程序级别)来测试大多数/所有故障模式。 “一个好的测试工具应该是曲折的。它应该像现实世界的系统一样令人讨厌和恶毒。” [126]“测试工具应该像一个小黑客一样,尝试各种不良行为来破坏呼叫者。” [128]
- 套接字连接可以被拒绝,坐在监听队列中直到调用者超时,远程端我用 SYN/ACK 回复,然后从不发送任何数据,它只能发送 RESET 数据包,它可能会报告一个完整的接收窗口并且永远不会耗尽数据,可以建立连接,但是远程端永远不会发送一个字节的数据,conn.can be established but packets lost causing retransmit delays,conn.est。但是远程从不 ACK 接收数据包,导致无休止的重传,服务可以接受请求,发送响应标头(假设 HTTP),并且从不发送响应主体; srv 可以每 30 秒发送 1 个字节的响应;它可以发送 HTML 而不是预期的 XML;它可能会在预期 kB 数据时发送 MB;它可以拒绝所有授权。证书。
- 模拟超出规格的故障
- 压力测试呼叫者 – 缓慢/无/垃圾响应,..
解耦中间件
一个做得好的中间件集成(通过传递数据和事件)和解耦(通过隐藏特定知识、调用其他系统)系统。
规模:
同一主机、时间、进程
- 进程内方法调用
- 进程间通信(共享内存、管道、信号量……)
- RPC (RMI, HTTP, ..) // 同时,差异。主机和进程
- 面向消息的中间件(MQ、SMTP、SMS、..)
- 元组空间(Java/Giga/T 空间)
不同时间、宿主、过程
- 在最后的责任时刻做出决定;这是一个更改成本高昂的架构决策
- 通过完全解耦(服务器、层、应用程序)避免许多故障模式
- 学习多种架构,并在其中进行选择
测验——这里出了什么问题:
try { ... }
finally {
if (stmt != null) stmt.close();
if (conn != null) conn.close();
}
-
stmt 可能很少抛出异常,因此 conn 永远不会关闭,导致连接池耗尽
容量
用户会话是致命弱点——它们消耗内存,如果启用了复制,还会消耗 CPU 和带宽。
负载测试:现实世界对网站并不礼貌。搜索引擎蜘蛛可能会忽略 cookie 在每个请求上创建一个新会话(同时生成许多请求)。爬虫和购物机器人做同样的事情。
=> 不要按照系统的预期使用方式测试系统
有用的工具
- 如果每个请求都创建一个会话,请验证客户端正确处理 cookie,并将那些不正确处理的发送到“如何启用 cookie”页面
- 能够限制对系统的请求数量,以便我们可以将会话保持在崩溃限制以下
- 检测并阻止产生恶意流量的 IP、子网等
容量
- 性能:系统处理单个事务的速度有多快
- 吞吐量:# tx / 一个时间跨度
- 可扩展性:1)吞吐量为f(负载); 2) 如何通过增加容量来扩展系统
- 容量:对于给定的工作负载,系统可以维持的最大吞吐量,同时为每个单独的 tx 保持可接受的响应时间(工作负载可能会发生根本变化,例如当用户在特定季节对不同服务感兴趣时)
- 约束:总是有一个(当前)约束<>约束理论
容量神话:CPU、带宽和存储都很便宜。
容量反模式
9.1 资源池争用
“如果使用得当,[DB] 连接池与所有资源池一样,可以通过提高吞吐量来提高容量。然而,如果放任不管,资源池很快就会成为应用程序中的最大瓶颈。” [167] – 当存在资源争用时,即可用资源少于所需资源;然后请求线程被无限期地阻塞。此外,每个连接——即使是闲置的连接——都会消耗远程系统上的资源。
- 消除正常负载下的竞争
- 如果可能,将资源池的大小设置为请求线程池
- 防止恶性循环:竞争 => tx 需要更长的时间 => 更多竞争
- 注意阻塞线程模式(容量 => 稳定性问题)
过多的 JSP 片段
AJAX 矫枉过正
Ajax = 从浏览器到服务器的更多请求,速度更快。 req 和 resp 通常会更小。使用不当,会给 Web 和应用程序服务器带来更多负担。
会话抖动——确保会话亲和力,以便 AJAX 请求转到具有用户会话的服务器。确保您没有为每个请求创建一个新会话。
逾期会议
在最后一个请求之后会话在 mem 中停留多长时间(因为我们现在有办法知道用户永远离开了)——在 Java 中默认为 30 分钟。查看您的数据以确定会话超时:例如 avg + 1 std dev。实际上,零售网站大约需要 10 分钟,媒体网关需要 5 分钟,旅游行业网站最多需要 25 分钟。更好的办法是让会议变得不必要。 F.ex.持久数据的内存副本可以随时删除和重新创建(保留键,而不是整个对象)。
HTML 中的浪费空间
每个字节都会消耗不同网络设备和服务器上的带宽、内存和处理资源。省略不必要的字符,删除空格,用 CSS 布局替换 HTML 表格。
重新加载按钮
如果网站速度很慢,用户可能会开始点击重新加载,希望得到一个可能被卡住的响应,从而进一步增加负载。 (应用服务器不知道它应该停止处理前一个。)让你的网站变快,这样用户就永远不会想到这样做。
手工制作的SQL
ORM => 可预测的、重复的 SQL。 SQL 的可预测访问模式有利于容量,b/ca 主管 DBA 可以为他们调整数据库。 OO 开发人员不喜欢关系查询,并创建与应用程序其余部分的调整不一致的昂贵查询。
常见问题:连接非索引列,连接太多表,..。
=> 最小化,与 DBA 核对,根据真实数据验证收益。
DB富营养化
- 淤泥缓慢堆积,最终将其杀死
- 创建索引
- 清除污泥 = 旧数据(来自其他地方的产品服务器的 mv,...)
- 让报告远离 Prod
集成点延迟
调用远程点需要时间+它的处理时间,不要忽略这一点。最初的性能问题可能会成为整个系统的容量问题。避免冗长的远程协议。
曲奇怪兽
=> 保持饼干小;他们随每个请求一起发送。
容量模式
池连接
使用 & remember 来保护来电者永远不会被阻塞。调整它们的大小以获得最大吞吐量。
谨慎使用缓存
限制缓存大小。建立冲洗机制。不要缓存琐碎的对象。比较访问和更改频率。
预计算内容
并不是所有的东西都需要是动态的,甚至不是所有动态的东西都同样频繁地变化。
调整垃圾收集器
“在 Java 应用程序中,垃圾收集调优是最快、最简单的提高容量的方法。以生产量和流量运行的未调整应用程序可能会花费其 10% 的时间来收集垃圾。这应该减少到 2% 或更少。” [205](请记住,这是在 2007 年写的。)
第四部分一般设计问题
11. 网络
主题:多宿主服务器、正确路由、虚拟 IP 地址。
12. 安全
主题:最小特权原则(单独的用户/应用程序,...),配置的密码(单独在加密文件中,...)。
13.可用性
收集和记录需求(每当负责定义可用性时请参考这些需求!)、负载平衡、反向代理、集群。
14.行政
QA 是否与生产匹配?
如果 9 月保持应用程序分离。 in prod 以防止隐藏的依赖项。零、一、多——如果在生产中有很多节点,在 QA 中有 2 个。只需购买设备:“我已经看到数小时的停机时间是由于生产中存在 QA 中不存在的防火墙或负载平衡器造成的。” [238]
14.s 启动和关闭
在应用程序中构建一个清晰的启动顺序,以便一切都以正确的顺序启动,并且必须在服务请求之前完成。在里面。每个连接至少有一些连接。池(快速失败)。
干净关闭:有一个模式,现有的 tx 已完成(记住超时)但不接受新请求。
用于管理的 CLI 界面是最好的(<> 脚本)x GUI。
第四部分 操作
17 透明度
= 使人员能够深入了解系统的历史趋势、现状、瞬时状态和未来预测的品质。
观点
- 历史趋势——OpsDB 中的系统和业务级别指标 => 趋势
- 预测未来(我们可以处理多少用户,..)
- 当前状态——每个应用程序和硬件的状态——内存、垃圾回收。 (频率,..),每个池的线程,数据库连接池,每个请求通道的流量统计,每种类型的业务交易,用户(人口统计,#,使用模式,遇到的错误,......),集成点,断路器
- 瞬时行为也就是这到底是怎么回事? <> 监控系统、线程转储、堆栈跟踪、日志文件中的错误……
透明设计
尽早开始。您需要了解整个系统以避免局部优化。
使能技术
记录
- 可配置的位置(=> 不同的驱动器)
- 级别:仅将需要 Ops 注意的记录为错误/服务器;并非每个异常都是错误
- 消息目录(由 ops 要求)——使用 IDE 中的国际化工具轻松生成它;包括便于查找的键——例如创建的 i8n 键 => 独特的,易于查找
- 人为因素:传达清晰、准确、可操作的信息,以便处于压力下的人能够正确解读;使其对人类及其模式匹配能力具有可读性
- 包括事务的 ID 以跨组件跟踪它
监控系统
标准
- SNMP——广泛支持,旧的;支持自定义软件很费力
- CIM(1996 年,SNMP 的继任者)——更动态、更高级;不太普遍
- JMX——非常适合基于 JVM 的应用程序
暴露什么
- 流量指标:页面请求 [总数]、tx 计数、并发会话
- 资源池运行状况:启用状态、总资源、r。签出,高水位线,# r。创建/销毁,# 次检出,# 线程阻塞等待 r.,# 次线程阻塞
- 数据库连接运行状况:# SQL 异常、# 查询、对 q 的平均响应时间。
- 集成点运行状况:断路器状态、# 超时、# 请求、平均响应时间、# 良好响应、# 网络/协议/应用程序错误、远程端点的 IP 地址、当前 # 并发请求、并发请求。高水位线
- 缓存健康:c.中的项目,c.使用的内存,缓存命中率,垃圾收集器刷新的项目,配置的上限,创建项目所花费的时间
操作数据库 (OpsDB)
日志记录和监控会暴露即时行为/状态,但不适合历史/未来视角 => 在(操作)数据库中累积状态、指标。
OpsDB 高层结构
try { ... }
finally {
if (stmt != null) stmt.close();
if (conn != null) conn.close();
}
-
功能 ——一个具有重要业务功能的单元(与可用性 SLA 相关);通常跨多个主机(web、app、DB、..)、网络设备(如 FW、交换机等)实现。 - 节点 代表这些活动节点中的任何一个(通常它足以代表主机和应用程序)。可选择跟踪哪些节点使用其他节点。 - 观察 : 测量 主要是周期性的性能统计; 状态 是状态转换(c.breaker on/off, …)。 ObservationType 定义 Obs 的名称和具体子类型。
最后我们添加:
try { ... }
finally {
if (stmt != null) stmt.close();
if (conn != null) conn.close();
}
期望 = 指标的允许范围、事件不得 [不] 发生的时间范围、允许的状态;违规 => 警报。根据历史数据设定。 (当心误报 = 狼来了!)。最终,期望值可能成为业务节奏的函数(白天/黑夜、特殊季节……)
配套流程
建立一个有效的反馈过程,即只共享有意义的数据,这些数据是响应性的。参见计划-执行-检查-行动、Boyd 的 OODA 等。
观察要点
注意趋势和异常值。包括持续改进。
- 每周,回顾过去的w。问题,寻找重复出现的问题和最耗时的问题,对于特别麻烦的子系统/第 3 方/integr.point。
- 每个月看问题总量,考虑pr的分布。类型。趋势应该是严重程度和数量下降。
- 每日或每周查找异常、日志中的堆栈跟踪 => 查找最常见的来源,考虑它们是否表明严重问题或错误处理方面的差距。
- 查看常见问题的帮助台呼叫 => UI 改进,更稳健
- 如果要复习的问题太多,请寻找最热门的类别并随机抽样
- 每 4-6 个月,重新检查旧的相关性是否仍然适用
- 至少每月查看数据量和查询统计信息
- 检查数据库中最昂贵的查询;有他们的问题。计划改变了吗?是否有新的 €€€ 查询? <=> 在某处积累数据。检查表扫描 => 缺少索引。
- 查看需求和系统指标的每日和每周包络线;交通模式在改变吗?如果一个受欢迎的时间正在下降,那么那个时候系统可能太慢了;如果存在平台期,则可能存在限制因素,例如系统的响应能力。
重点从反应性转变为预测性。旧指标/报告松散的价值。
对于正在审查的每个指标:它与历史规范相比如何?如果趋势继续下去,相关指标会发生什么变化(# users x responsiveness);在达到限制因素之前它可以持续多长时间,然后会发生什么? => 解释和决定
18.适应
主题:适应性软件设计、依赖注入、对象设计、XP 编码实践、敏捷数据库、适应性企业架构、系统内的依赖性,d。系统之间:协议/数据库,发布不应该受到伤害(0 停机部署,......)