Web应用扩展系列(1):架构篇(转)
在这篇文章中,我将尽量涵盖Web应用扩展或性能调优时可能会遇到的一些架构问题。
首先,让我们来统一一些名词或项目的概念,下文中我将列举在扩展Web应用时可能会遇到的多种问题,包括:
- 架构瓶颈
- 数据库扩展
- CPU依赖的应用
- IO依赖的应用
而如何确定优化Web应用线程池大小的内容将会在下一篇文章中给出。
性能(performance)这个词对于Web应用来说通常意味着一些指标,对于大部分的开发者而言,他们主要关心的是响应时间(response time)以及扩展性(scalability)。
- 响应时间
响应时间指的是自Web应用接收到请求到其返回所用的时间。应用的响应时间应该控制在合理的范围之内,如果一个应用的相应时间超出了可接受的时间范围,那么这个应用就不是一个好的应用。
- 扩展性
如果一个应用在增加资源的情况下,其服务请求的能力能够按线性增长,那么这个应用就可以说是可扩展的。有两种增加资源的模式:
- 纵向扩展(Scaling Up) :- 在单个服务单元增加计算能力数量或计算能力性能。
- 横向扩展(Scaling Out) :- 增加更多的服务单元。
横向扩展 vs 纵向扩展
横向扩展考虑的是发挥相对廉价的硬件数量优势,以取代某些需要特别购置的昂贵设备(比如超算)。但是,在单个廉价硬件单元上提升一个服务所能响应的请求数也同样重要。我们说一个应用的性能优异是指它能够在不延长响应时间的情况下通过增加更多的资源而处理更多的请求。
响应时间 vs 扩展性
响应时间和扩展性不会都朝着你所希望的方向变化。举个例子,有些应用可能有不错的响应时间,但是只能处理一定数量的请求;而其他有些应用能够处理不断增长的请求,但却需要消耗比较长的时间。所以我们必须要在这两者之间做出平衡以得到最好的应用性能。
能力规划
能力规划(capacity planning)是弄清产品需要多少硬件资源以处理期望的负载的一种活动。通常它涉及到弄清应用产品性能的极限,即基于更少的服务单元最多能响应多少请求以及单个服务单元的性能。最终,通过负载性能测试来进行验证。
可扩展架构
如果一个应用是多层次架构,并且在每个层次上都是可扩展的(横向扩展),那么这个应用的架构就说是具有扩展性的。举个例子:如下图所示,我们可以在应用层或数据库层线性地增加额外的计算单元。

扩展负载均衡器
负载均衡器能够通过指定DNS到多个IP地址,或是使用DNS轮询的办法进行扩展。还有一种方法是使用分级的的负载均衡器,由前端负载均衡器将请求分发到下一级的负载均衡器。
增加多个负载均衡器对使用nginx或HAProxy的单个计算单元来说是十分罕见的,这类强大的软件能够在单个单元上同时处理超过两万个并发连接,这比其他的web应用容器要强大得多。所以通过它们单个的负载均衡单元能够处理多个web应用单元的请求。
扩展数据库
数据库的扩展是一种最常见的扩展问题。在数据库层中增加额外的业务(存储过程或函数)会带来额外的负担和复杂性。
关系型数据库
关系型数据库可以通过主-从模式进行扩展,这样做可以实现读写分离,即主库负责读写,而从库负责读。主-从模式提供了读的有限扩展,除此之外,开发者们通常将数据库进行划分来进行横向扩展。
NoSQL
CAP理论说得明白,不可能同时满足一致性、可用性以及分区容错性。NoSQL数据库通常牺牲一致性来获取高可用及分区容错性。
数据库划分
数据库的划分可以采用纵向划分(分区)或横向划分(分片)的模式。
- 纵向划分(分区):数据库能够基于领域概念而被划分成为多个松散的子库。举个例子,客户数据库、产品数据库诸如此类。还可以将一个实体少量的列移动到不同的数据库中。比如客户数据库、客户联系方式数据库以及客户订单数据库。
- 横向划分(分片):数据库能够基于一些离散的属性被横向的划分为多个库。比如美国客户数据库、欧洲客户数据库等。
使用分区或分片,将数据库从单库模式转换到多库模式是一项具有挑战性的工作。
架构瓶颈
扩展的瓶颈主要因为两个问题而存在:
- 中心化组件:应用架构中的某个组件,它不能够通过增加整个架构或请求通道处理的请求数量上限来进行横向扩展。
- 高延迟组件:一个速度较慢的组件,拉低了应用请求通道响应时间的下界。通常的解决方式是将此类高延迟组件作为后台任务执行,或是异步地使用队列的方法来执行。
CPU密集型应用
如果一个应用的吞吐量被CPU所限制,那么我们称这个应用为CPU密集型应用(CPU Bound Application)。通过增加CPU的运行速度,可以使应用的响应时间减少。
一些可能的CPU密集型应用场景:
- 应用是用来计算或处理数据的,而不会发生IO操作(金融或交易应用)
- 应用严重依赖缓存,而不会产生IO操作
- 应用是异步的(非阻塞式),不需要等待外部资源(被动模式的应用,NodeJS应用)
在上面提到的场景中,应用已经在高效的运行了,不过有少数应用实例可能是因为代码层面的原因,发生了一些完全不必要的操作去计算或轮询每个请求,进而使CPU利用率很高。通过分析可以很容易的发现低效之处并作出改进。
这些问题可以通过以下方式解决:
- 缓存住先前的计算结果
- 在互相分离的后台任务中运行计算
使用不同的方式进行缓存,缓存如何能够减少负载以提升效能和web应用的扩展性在接下来的博文中会有有详述。
IO密集型应用
如果一个应用的吞吐量被IO或网络能力所限制,无法通过增加CPU速度的方法带来应用性能提升的话,那么这个应用就被称为IO密集型应用(IO Bound Application)。大部分的应用都是IO密集型应用,因为大部分应用都依赖于CURD操作,在这些应用中提升性能或扩展都是一件很困难的事情因为 它严重依赖于其他的下游系统。
下面一些是可能的IO密集型应用场景:
- 应用依赖于数据库与大量的CRUD操作
- 应用使用web服务来完成它自身的操作
下篇博文将会聊聊如何优化设置Web应用的线程池大小。
Web应用扩展系列(1):架构篇(转)的更多相关文章
- web开发性能优化---项目架构篇
项目技术架构层级规划和介绍 简称四横两纵 四横即四大层次.分别为: 1.用户渠道层:用户渠道层是直接面向终于用户.通过站点的形式向用户提供产品展示.企业市场宣传.对产品的订购.互动分享.客户关怀以及用 ...
- 【目录】mysql 架构篇系列
随笔分类 - mysql 架构篇系列 mysql 架构篇系列 4 复制架构一主一从搭建(半同步复制) 摘要: 一.概述 在mysql 5.5之前,mysql 的复制是异步操作,主库和从库的数据之间存在 ...
- 【Java探索道路安全系列:Java可扩展的安全架构】一间:Java可扩展的安全体系结构开始
笔者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell [ ...
- 构建安全的Xml Web Service系列之SSL篇
原文:构建安全的Xml Web Service系列之SSL篇 首先介绍一下SSL, SSL 的英文全称是 "Secure Sockets Layer" ,中文名为 "安全 ...
- mysql 架构篇系列 3 复制运行状态监控与选项参数说明
一. 概述 在上一篇中,搭建了一主一从的复制架构,这篇通过一些诊断方法来了解复制的运行状态和一些选项参数说明.上次mysql主从服务关机,今天在打开mysql服务,出现了错误信息. 1.首先 启动主从 ...
- web前端知识大纲:系列一 js篇
web前端庞大而复杂的知识体系的组成:html.css和 javascript 一.js 1.基础语法 Javascript 基础语法包括:变量声明.数据类型. ...
- 【目录】sql server 架构篇系列
随笔分类 - sql server 架构篇系列 sql server 高可用镜像 摘要: 一.什么是数据库镜像 基本软件的高可用性解决方案 快速的故障转移恢复(3秒转移),低硬件成本 基于数据库级别的 ...
- mysql 架构篇系列 2 复制架构一主一从搭建(异步复制)
一. 环境准备 1.1 主库环境(172.168.18.201) 环境 说明 查看脚本 操作系统版本 CentOS Linux release 7.4.1708 (Core) cat /etc/red ...
- Webpack系列-第三篇流程杂记
系列文章 Webpack系列-第一篇基础杂记 Webpack系列-第二篇插件机制杂记 Webpack系列-第三篇流程杂记 前言 本文章个人理解, 只是为了理清webpack流程, 没有关注内部过多细节 ...
随机推荐
- 利用Python操作Word文档【图片】
利用Python操作Word文档
- PHP——小尾巴之权限管理
流程: 在权限管理页面,默认显示用户的角色,更改复选框的按钮内容,可以改变角色,点击确定提交至数据库 在登陆之后,只显示该用户的角色所对应的权限 数据库: guanli.php <!DOCTYP ...
- VisualStudio快捷键
ctrl+k,c 注释选中行 ctrl+k,u 取消对选中行的注释 CTRL + SHIFT + B:生成解决方案 CTRL + F7 :生成编译 CTRL + O :打开文件 CTRL + SHIF ...
- multimap 小例子
场景: 按DDX值倒序取前十的板块代码,用 map<float, string, greater<float> > mapBKDDX; 存储时,相同DDX值的板块只能存储第一个 ...
- JAVA在语言级支持多线程
进程:任务 任务并发执行是一个宏观概念,微观上是串行的. 进程的调度是有OS负责的(有的系统为独占式,有的系统为共享式,根据重要性,进程有优先级). 由OS将时间分为若干个时间片. JAVA在语言级支 ...
- ztree获取选中节点时不能进入可视区域出现BUG如何解决
zTree 是一个依靠 jQuery 实现的多功能 “树插件”.优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. zTree 的特点编辑 ● zTree v3.0 将核心代码按照功能进 ...
- MathType模板不见了如何处理
MathType是一款在编辑公式方面非常好用的软件!并广泛应用在文档编辑与期刊排版中.但是新手用户在使用MathType编辑公式时会遇到一些处理不了的状况,这个时候就需要去找一些相关的教程来解决问题. ...
- gcc安装(centos)
gcc 4.8 安装 [root@DS-VM-Node239 ~]# curl -Lks http://www.hop5.in/yum/el6/hop5.repo > /etc/yum.repo ...
- __del__()
__del__() 是类的内置函数,用于定义在脚本退出之前要执行的代码,因为有这个特性,通常被用来在脚本退出前关闭文件.关闭数据库连接.关闭网络连接等操作 [root@localhost ~]$ ca ...
- Unable to instantiate application com.android.tools.fd.runtime.BootstrapApplication 解决办法
相信很多人都遇到过这个问题,用Android Studio正在运行程序的时候,突然不知道什么原因,报一个找不到application或者找不到activity的错误(java.lang.ClassNo ...