设为首页 加入收藏

TOP

千万级流量的优化策略实战(二)
2019-09-17 18:20:37 】 浏览:119
Tags:千万 流量 优化 策略 实战
重用性的组件(Library或Service),通过分层组织各层组件来实现良好的架构。与之相对应,Monolith Architecture则希望尽可能在一套代码库中开发,通过直接调用代码中的基础功能或原語而实现性能的优化和快速迭代。使用Monolith Architecture有很大的争议,被认为不符合“设计模式”的理念。参考文献[4],Monolithic Design主要的缺点包括:1. 缺乏美感;2. 很难重构;3. 过早优化(参见文献[6]Optimize judiciously); 4. 不可重用;5. 限制眼界。微服务架构是很多互联网公司的主流架构,典型的运用公司包括Amazon、美团等。Monolithic Architecture也有其忠实的粉丝,例如:Tripadvisor的全球网站就共用一套代码库;基于性能的考虑,Linux最终选择的也是Monolithic kernel的模式。

奥卡姆剃刀原则

系统设计以及代码编写要遵循奥卡姆剃刀原则:Entities should not be multiplied unnecessarily。一般而言,一个系统的代码量会随着其功能增加而变多。系统的健壮性有时候也需要通过编写异常处理代码来实现。异常考虑越周全,异常处理代码量越大。但是随着代码量的增大,引入Bug的概率也就越大,系统也就越不健壮。从另外一个角度来讲,异常流程处理代码也要考虑健壮性问题,这就形成了无限循环。所以在系统设计和代码编写过程中,奥卡姆剃刀原则要求:一个功能模块如非必要,就不要;一段代码如非必写,就不写。

奥卡姆剃刀原则和最小可用原则有所区别。最小可用原则主要运用于产品MVP阶段,本文所指的奥卡姆剃刀原则主要指系统设计和代码编写两个方面,这是完全不同的两个概念。MVP包含系统设计和代码编写,但同时,系统设计和代码编写也可以发生在成熟系统的迭代阶段。


性能恶化模式

在讲解性能优化模式之前,有必要先探讨一下性能恶化模式,因为:

  1. 很多性能优化模式的目标之一就是避免系统进入性能恶化模式;
  2. 不同性能优化模式可能是避免同一种性能恶化模式;
  3. 同一种性能优化模式可能在不同阶段避免不同的性能恶化模式。
    在此统一阐述性能恶化模式,避免下文重复解释。为了便于读者清晰识别恶化模式和优化模式,恶化模式采用“XXX反模式”的方式进行命名。

长请求拥塞反模式(High Latency Invocating AntiPattern)

这是一种单次请求时延变长而导致系统性能恶化甚至崩溃的恶化模式。对于多线程服务,大量请求时间变长会使线程堆积、内存使用增加,最终可能会通过如下三种方式之一恶化系统性能:

  1. 线程数目变多导致线程之间CPU资源使用冲突,反过来进一步延长了单次请求时间;
  2. 线程数量增多以及线程中缓存变大,内存消耗随之剧增,对于基于Java语言的服务而言,又会更频繁地full GC,反过来单次请求时间会变得更长;
  3. 内存使用增多,会使操作系统内存不足,必须使用Swap,可能导致服务彻底崩溃。
    典型恶化流程图如下图:
    长请求拥塞反模式

长请求拥塞反模式所导致的性能恶化现象非常普遍,所以识别该模式非常重要。典型的场景如下:某复杂业务系统依赖于多个服务,其中某个服务的响应时间变长,随之系统整体响应时间变长,进而出现CPU、内存、Swap报警。系统进入长请求拥塞反模式的典型标识包括:被依赖服务可用性变低、响应时间变长、服务的某段计算逻辑时间变长等。

多次请求杠杆反模式(Levered Multilayer Invocating AntiPattern)

客户端一次用户点击行为往往会触发多次服务端请求,这是一次请求杠杆;每个服务端请求进而触发多个更底层服务的请求,这是第二次请求杠杆。每一层请求可能导致一次请求杠杆,请求层级越多,杠杆效应就越大。在多次请求杠杆反模式下运行的分布式系统,处于深层次的服务需要处理大量请求,容易会成为系统瓶颈。与此同时,大量请求也会给网络带来巨大压力,特别是对于单次请求数据量很大的情况,网络可能会成为系统彻底崩溃的导火索。典型恶化流程图如下图:
多次请求杠杆反模式
多次请求杠杆所导致的性能恶化现象非常常见,例如:对于美团推荐系统,一个用户列表请求会有多个算法参与,每个算法会召回多个列表单元(商家或者团购),每个列表单元有多种属性和特征,而这些属性和特征数据服务又分布在不同服务和机器上面,所以客户端的一次用户展现可能导致了成千上万的最底层服务调用。对于存在多次请求杠杆反模式的分布式系统,性能恶化与流量之间往往遵循指数曲线关系。这意味着,在平常流量下正常运行服务系统,在流量高峰时通过线性增加机器解决不了可用性问题。所以,识别并避免系统进入多次请求杠杆反模式对于提高系统可用性而言非常关键。

反复缓存反模式(Recurrent Caching AntiPattern)

为了降低响应时间,系统往往在本地内存中缓存很多数据。缓存数据越多,命中率就越高,平均响应时间就越快。为了降低平均响应时间,有些开发者会不加限制地缓存各种数据,在正常流量情况下,系统响应时间和吞吐量都有很大改进。但是当流量高峰来临时,系统内存使用开始增多,触发了JVM进行full GC,进而导致大量缓存被释放(因为主流Java内存缓存都采用SoftReference和WeakReference所导致的),而大量请求又使得缓存被迅速填满,这就是反复缓存。反复缓存导致了频繁的full GC,而频繁full GC往往会导致系统性能急剧恶化。典型恶化流程图如下图:
反复缓存反模式
反复缓存所导致性能恶化的原因是无节制地使用缓存。缓存使用的指导原则是:工程师们在使用缓存时必须全局考虑,精细规划,确保数据完全缓存的情况下,系统仍然不会频繁full GC。为了确保这一点,对于存在多种类型缓存以及系统流量变化很大的系统,设计者必须严格控制缓存大小,甚至废除缓存(这是典型为了提高流量高峰时可用性,而降低平均响应时间的一个例子)。反复缓存反模式往往发生在流量高峰时候,通过线性增加机器和提高机器内存可以大大减少系统崩溃的概率。


性能优化模式

水平分割模式(Horizontal partitioning Pattern)

原理和动机

典型的服务端运行流程包含四个环节:接收请求、获取数据、处理数据、返回结果。在一次请求中,获取数据和处理数据往往多次发生。在完全串行运行的系统里,一次请求总响应时间满足如下公式:

一次请求总耗时=解析请求耗时 + ∑(获取数据耗时+处理数据耗时) + 组装返回结果耗时

大部分耗时长的服务主要时间都花在中间两个环节,即获取数据和处理数据环节。对于非计算密集性的系统,主要耗时都用在获取数据上面。获取数据主要有三个来源:本地缓存,远程缓存或者数据库,远程服务。三者之中,进行远程数据库访问或远程服务调用相对耗时较长,特别是对于需要进行多次远程调用的系统,串行调用所带来的累加效应会极大地延长单次请求响应时间,这就增大了系统进入长请求拥塞反模式的概率。如果能够对不同的业务请求并行处理,请求总耗时就会大大降低。例如下图中,Client需要对三个服务进行调用,如果采用顺序调用模式,系统的响应时间为18ms,而采用并行调用只需要7ms。
水平分割模式

水平分割模式首先将整个请求流程切分为必须相互依赖的多个Stage,而每个Stage包含相互独立的多种业务处理(包括计算

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 2/7/7
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Unity 游戏框架搭建 2018 (一) 架.. 下一篇SSM衍生的配置文件

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目