应用性能优化: 如何将应用延迟降低为 0 ms
2016-02-23 10:56
435 查看
之前已经提过通过 Varnish 缓存进行网站性能优化,以及延迟对商业的影响。
经历过太多这样的问题分析和定位过程:
某大型网站的 Redis 集群的机器负载每几十分钟出现一个超越平时几十倍大的高峰,结果是因为这些实例每几十分钟对所有数据进行写盘持久化。
某大型媒体网站的 MySQL 读流量异常大,结果是因为每个读操作都携带了 2MB 的页面初始化信息。这个 BUG 修正的直接结果不仅仅是降低了数据库的访问压力,而且是访问延迟直接降低了 75%,另外应用服务器的负载也降低很多,节省了服务器。
![](https://blog.eood.cn/wp-content/uploads/2016/02/latency-reduce1.png)
还有很多类似的故事。
这些故事看起来可笑,但是发生的原因并不可笑。大部分线上系统都会存在类似的问题。
一方面,所有公司都在大量使用开源软件类库,某些类库并不一定针对大流量设计。另一方面,每个运维和开发人员都难以面面俱到。而且,现在互联网应用越来越复杂,发现问题都非常难。
这种问题自底向上分析是难以避免的,也难以发现,所以应用性能优化需要自顶向下分析,从监控表现入手,寻找线索,进而定位问题。
当然应用整体性能监控、优化,运行成本的降低和把控本身是架构师的主要任务之一。
互联网应用性能优化 (APO, Application Performance Optimization) 有两个大的方向可以做:
所以,其中大部分模式都是相通的,并且可以重复利用。比如一些常见的思路和技术:负载均衡、缓存、索引、命名系统、连接重用等等。
随着流量的变化,引起的延迟变化或者机器负载变化,有经验的架构师或者运维基本心里有数。通过对商业模式的分析,相对应的在线业务系统应该有的延迟、服务器压力等等数据可以从心里估算出大致的范围。结合此业务系统的监控图表,基本可以很快看出不合理的地方。然后从一个线索入手定位问题所在,进行修复。
这里主要说明一个利用 最终一致性 的思路修改缓存系统对网页延迟的优化。
Varnish 4.0 增加了一个新功能:
Background (re)fetch of expired objects. On a cache miss where a stale copy is available, serve the client the stale copy while fetching an updated copy from the backend in the background.
假如 cache miss,立刻返回给用户一个之前的旧版本缓存,然后再从应用服务器请求新的版本。这意味着如果缓存足够大,可以让用户 100% 访问到 Varnish 服务器上缓存的版本,而跳过后端服务器的延迟。这也是为什么标题写着降低到 0ms :-) 有点标题党了。
具体的实现方式:
保证缓存存储足够大
保证 Grace 时间足够长(无限长)
假如 obj.ttl + obj.grace > 0s 则返回缓存,否则访问后端服务器。
这样离保证用户 100 % 命中缓存还差一步,就是缓存的预热。为了避免第一个用户访问后端服务器,我们通过主动抓取的方式,或者叫做缓存推送的方式进行缓存的预热。方式很简单,逐个向每个 Varnish 实例请求网站的所有 URL。另外,新生成的 URL,首先进行预热。
需要注意的是,这种方式只适合于用户对信息新旧不是非常敏感的场景,比如所有的媒体页面,说明页面,电商网站的产品说明页面,移动应用的 Feed API (跳出 Varnish,应用类似思路)。另外,这个方案适用于所有需要针对搜索引擎 SEO 进行延迟优化的场景。
经历过太多这样的问题分析和定位过程:
某大型网站的 Redis 集群的机器负载每几十分钟出现一个超越平时几十倍大的高峰,结果是因为这些实例每几十分钟对所有数据进行写盘持久化。
某大型媒体网站的 MySQL 读流量异常大,结果是因为每个读操作都携带了 2MB 的页面初始化信息。这个 BUG 修正的直接结果不仅仅是降低了数据库的访问压力,而且是访问延迟直接降低了 75%,另外应用服务器的负载也降低很多,节省了服务器。
![](https://blog.eood.cn/wp-content/uploads/2016/02/latency-reduce1.png)
还有很多类似的故事。
这些故事看起来可笑,但是发生的原因并不可笑。大部分线上系统都会存在类似的问题。
一方面,所有公司都在大量使用开源软件类库,某些类库并不一定针对大流量设计。另一方面,每个运维和开发人员都难以面面俱到。而且,现在互联网应用越来越复杂,发现问题都非常难。
这种问题自底向上分析是难以避免的,也难以发现,所以应用性能优化需要自顶向下分析,从监控表现入手,寻找线索,进而定位问题。
当然应用整体性能监控、优化,运行成本的降低和把控本身是架构师的主要任务之一。
互联网应用性能优化 (APO, Application Performance Optimization) 有两个大的方向可以做:
1. 应用本身的 BUG 和不合理的地方
无论网站还是移动应用 API,或者是实时通讯和聊天系统,本质上都是用户通过 HTTP 和其他 TCP 协议交互信息的过程。所以,其中大部分模式都是相通的,并且可以重复利用。比如一些常见的思路和技术:负载均衡、缓存、索引、命名系统、连接重用等等。
随着流量的变化,引起的延迟变化或者机器负载变化,有经验的架构师或者运维基本心里有数。通过对商业模式的分析,相对应的在线业务系统应该有的延迟、服务器压力等等数据可以从心里估算出大致的范围。结合此业务系统的监控图表,基本可以很快看出不合理的地方。然后从一个线索入手定位问题所在,进行修复。
2. 应用业务之外的架构层次的修改
假如不考虑程序的 BUG 或者代码本身的优化,在这之上的一个层次也可以有很多可以优化的方向。这里主要说明一个利用 最终一致性 的思路修改缓存系统对网页延迟的优化。
Varnish 4.0 增加了一个新功能:
Background (re)fetch of expired objects. On a cache miss where a stale copy is available, serve the client the stale copy while fetching an updated copy from the backend in the background.
假如 cache miss,立刻返回给用户一个之前的旧版本缓存,然后再从应用服务器请求新的版本。这意味着如果缓存足够大,可以让用户 100% 访问到 Varnish 服务器上缓存的版本,而跳过后端服务器的延迟。这也是为什么标题写着降低到 0ms :-) 有点标题党了。
具体的实现方式:
保证缓存存储足够大
保证 Grace 时间足够长(无限长)
假如 obj.ttl + obj.grace > 0s 则返回缓存,否则访问后端服务器。
这样离保证用户 100 % 命中缓存还差一步,就是缓存的预热。为了避免第一个用户访问后端服务器,我们通过主动抓取的方式,或者叫做缓存推送的方式进行缓存的预热。方式很简单,逐个向每个 Varnish 实例请求网站的所有 URL。另外,新生成的 URL,首先进行预热。
需要注意的是,这种方式只适合于用户对信息新旧不是非常敏感的场景,比如所有的媒体页面,说明页面,电商网站的产品说明页面,移动应用的 Feed API (跳出 Varnish,应用类似思路)。另外,这个方案适用于所有需要针对搜索引擎 SEO 进行延迟优化的场景。
相关文章推荐
- 玩转 Varnish 缓存代理
- Xcode模拟器正常显示图片,真机无法显示,找不到图片
- Dianping River Plugin for Elasticsearch
- GitHub for Windows提交失败“failed to sync this branch”
- nginx+tomcat集群配置(4)--rewrite规则和多应用根目录设定思路
- js获得桌面size
- Oracle 分区表的新增、修改、删除、合并。普通表转分区表方法
- Ubuntu 软件源sources.list
- Jenkins进阶系列之——02email-ext邮件通知模板
- win32 ios android 获取系统时间
- 【备查】adb命令
- 1073 家族【解题报告】
- iOS8 【xcode6中添加pch全局引用文件】
- List of Algorithms
- android特殊字符
- String,StringBuffer,StringBuilder的一些面试题
- STL容器list&vector间的复制
- 计算输入的字符的字节数
- iOS-SQLite3和FMDB使用
- Nginx源码分析:核心模块剖析及常见问题