原始资源使用率增长

  更多的对象将占用更多的内存。如果某人想要支持1000个并发对象,很可能是做不到的,因为你可能根本没有足够的内存。

  隐式资源使用率增长

  大多数功能中,针对“原始”资源使用开销中的每项资源,都将会需要大量的额外资源。如果你将一个对象存储在两个不同的列表里,你的对象数目和内存开销将是原来的两倍;队列大小可能也需要向上调整;磁盘的数目需要增加;将数据复制到从机的时间在增长;将数据加载到应用中的时间在增长;为了处理这些工作CPU的使用率在增长;启动时间也在增长。

  事件的叠加

  很多系统面临的一个新的现实是无穷工作流。Web服务器和应用服务器服务着非常大的用户群,这是一个真实的可预计的关于新工作的无穷流。而工作将永不结束。一周7天24小时都会有请求进来。以的CPU使用率进行工作可以很容易使服务器达到饱和。

  习惯上我们将的CPU使用率视为一个不良的信号。作为补偿,我们将创建复杂的基础设施来对工作进行负载均衡,复制状态并做好主机集群。

  CPU永不疲倦,所以你可能会认为我们应该尝试使用尽可能多的CPU。

  在其他领域我们试图通过大限度的利用资源来提升生产率。

  而在服务器的世界里,我们尝试通过人为的方式强制地降低CPU使用率从而保证一定的响应水平。该理由是因为如果我们没有更高的CPU可用性,我们将无法在合理的延迟时间内响应新的工作或完成现有的工作。

  CPU使用率达到真的存在问题吗?我们在对系统做架构设计时,宁可使用CPU可用性和任务优先级作为架构设计认知上简略的一种解释依据,也不愿意先去理解下我们系统的底层工作流,从而使用这些信息再来做出明确的规划决策。难道这不正是真正的问题所在吗?

  我们基于负载均衡服务器做出了拙劣的架构决策,通过主观臆想猜测了使用的线程数以及这些线程的优先级。除了以上这些,我们根本没有使用工具做过任何其他事。

  扩展一个系统需要仔细地关注架构。在当前框架的应用程序中,却很少有对所辖应用是如何运行的进行说明。

  延迟的增长

  你所经历的延迟增长与规模增长可能是完全不同的。CPU饥饿是该问题的主要原因。

  任务优先级被证明是错误的

  任务优先级方案可以有效地工作在较小负载下,但是在高负载下会产生问题。举个典型的例子,有一套简陋的流控装置,一个高优先级任务向一个较低优先级的任务传递工作将会导致工作丢失和内存使用峰值,因为低优先级的任务的运行机会将会很少。

  队列容量不足够大

  大量的对象意味着可以进行更多的并发操作,这意味着队列容量将很可能需要扩充。

  启动时间更久

  更多的对象需要更久的时间才能将它们从磁盘加载到应用中。

  同步时间更久

  需要更多的时间才能将更多的对象在应用之间进行同步。

  在大型配置中没有进行足够的测试

  因为测试装置成本很高,所以我们实际花费在大型设置上的测试时间非常少。你在开发期间不需要接触大型系统,所以很可能你的设计一开始不能支持大规模的场景。

  操作耗时更久

  如果一个操作作用于每个对象,当更多的对象被添加进来后,该操作的耗时也将会更久。当数据表变得更大时,过去针对一定数据量足够快速的查询,如今的耗时也会大幅度的增长。

  更多的随机故障

  在正常操作中你可能不会看到某些故障。但在一定规模下,响应将丢失,ARP请求将丢失,文件系统可能会出现某些错误,消息可能丢失,回复也可能丢失,等等。

  更大的故障窗口

  规模化导致每个环节都会耗时更久,这意味着出现故障的概率会更大。一个数据交换协议在处理少量数据集的时候会很快,这意味着它只有很小的机会遭遇重启或超时。但是更大的规模中,故障窗口将扩大从而第一之间会遭遇到新问题。

  没有提高超时设置

  任何超时在较小的数据集中可以有效工作,但是当数据集逐渐增长后将不再适用。CPU饥饿问题而言,你所编写的代码可能还没来得及跑,超时时间却早已达到。

  没有增加重试次数

  没有办法在确定故障之前为某应用指定重试次数,因为他们没有这方面足够的信息来支持决策。每秒4次重试是否合理?为什么不是20次呢?

  优先级继承

  更久的持有大范围的锁将有更好的机会遭遇优先级继承问题。

  消费模式的打破

  在一种规模下你可以从生产者获取所有数据,但是在另一规模下你将会耗尽队列的空间或内存。举个例子:某个轮询程序在将数据传递到下一个队列之前,会一直向远程队列轮询所有的数据源。当队列中只有很少量数据项的时候该程序可以有效的运行。但是很可能因为某个功能的变更扩大了该远程队列中的数据项数量,这样一来该轮询程序将会导致某个节点内存不足。