随着负载的增长,你精心设计的程序可能会遭遇很多突如其来的问题:系统原有的平稳将被打破,我们将对这些问题逐一考察。当然,你可以进行横向或纵向的扩展,也可以选择编写出更好的程序,让你的系统可以处理更高的负载。这样做可以节省更多的硬件开支,并让你的整个应用更加可靠,具有更快的响应时间。对于程序员来说,这必将获得非常大的满足感。

  大量的对象

  当系统中的对象数量增长到一定程度,我们通常将面临规模问题。随着对象数目的增长,所有类型的资源开销显然会带来很大的压力。

  持续的故障会产生一个无穷事件流

  在大型网络的故障场景中,我们没有时间进行系统恢复。因为我们始终处于一个持续的压力状态下。

  大量的高优先级任务

  举个例子,重选路由(rerouting)是个高优先级的活动。如果存在大量不能分发(shed)或取消(squelched)的重选路由任务,资源将连续不断的被消耗以支持高优先级任务。

  更大的数据流

  当媒体资源大小增长得更大时,系统的负载将会增长。系统负载会随着请求来源数目的增长而增长。

  功能变更

  在系统原有设计之外添加更多的功能后,系统中的漏洞也随之暴露。

  客户端的增长

  更多的客户端意味着更多的资源消耗。需要设置线程为客户端推送事件;客户端队列会消耗内存;通信会消耗带宽;需要为每个客户端维持一份独立数据。

  不够好的设计决策

  以下是一些会加剧规模问题的设计问题。

  设计未考虑处理大量对象。

  缺乏端到端应用级别的流控。

  应用级别的重试将导致资源再分配和消息发送。

  内存中代码库的开销。

  并不真正可靠的发布。

  特定数据结构过度占用内存。

  消息协议没有处理所有故障场景。

  使用磁盘作为存储。

  磁盘同步没有使用块复制。

  认为应用层协议会更有好。

  依靠大功耗的CPU来提升功能负载。

  操作系统不支持进程架构。(译者注:该点讨论见原文链接处的评论)

  缺乏对于某些敏感操作(甚至是单条消息的删除)的硬件支持。

  特别的网络问题,比如ARP数据包,当网络负载增长时会出现丢失。

  无效的假设

  你所做的大部分假设都是无效的,比如你需要使用多少内存,某些任务需要运行多少时间,设置多少超时时间才算合理,一次会消费多少资源,可能发生什么样的故障,系统在不同点的延迟,你的队列需要多大,等等。

  内存不足

  内存使用基线的增长和内存使用峰值的增长,都会导致内存不足。

  CPU饥饿

  随着对象操作的增加,将需要占用更长的时间,这是因为这些操作需要操作更多的对象。可用CPU将变得更少从而导致其他的操作将面临CPU饥饿。系统一处出现了饥饿,会传播到其他各处。这样一来没有足够的CPU来处理那些需要去完成的必要任务。导致这样的原因可能是任务的基数过高或某些情况下很多高优先级的任务需要完成。