原文: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):架构篇(转)的更多相关文章

  1. web开发性能优化---项目架构篇

    项目技术架构层级规划和介绍 简称四横两纵 四横即四大层次.分别为: 1.用户渠道层:用户渠道层是直接面向终于用户.通过站点的形式向用户提供产品展示.企业市场宣传.对产品的订购.互动分享.客户关怀以及用 ...

  2. 【目录】mysql 架构篇系列

    随笔分类 - mysql 架构篇系列 mysql 架构篇系列 4 复制架构一主一从搭建(半同步复制) 摘要: 一.概述 在mysql 5.5之前,mysql 的复制是异步操作,主库和从库的数据之间存在 ...

  3. 【Java探索道路安全系列:Java可扩展的安全架构】一间:Java可扩展的安全体系结构开始

    笔者:郭嘉 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells github:https://github.com/AllenWell [ ...

  4. 构建安全的Xml Web Service系列之SSL篇

    原文:构建安全的Xml Web Service系列之SSL篇 首先介绍一下SSL, SSL 的英文全称是 "Secure Sockets Layer" ,中文名为 "安全 ...

  5. mysql 架构篇系列 3 复制运行状态监控与选项参数说明

    一. 概述 在上一篇中,搭建了一主一从的复制架构,这篇通过一些诊断方法来了解复制的运行状态和一些选项参数说明.上次mysql主从服务关机,今天在打开mysql服务,出现了错误信息. 1.首先 启动主从 ...

  6. web前端知识大纲:系列一 js篇

    web前端庞大而复杂的知识体系的组成:html.css和 javascript           一.js           1.基础语法 Javascript 基础语法包括:变量声明.数据类型. ...

  7. 【目录】sql server 架构篇系列

    随笔分类 - sql server 架构篇系列 sql server 高可用镜像 摘要: 一.什么是数据库镜像 基本软件的高可用性解决方案 快速的故障转移恢复(3秒转移),低硬件成本 基于数据库级别的 ...

  8. mysql 架构篇系列 2 复制架构一主一从搭建(异步复制)

    一. 环境准备 1.1 主库环境(172.168.18.201) 环境 说明 查看脚本 操作系统版本 CentOS Linux release 7.4.1708 (Core) cat /etc/red ...

  9. Webpack系列-第三篇流程杂记

    系列文章 Webpack系列-第一篇基础杂记 Webpack系列-第二篇插件机制杂记 Webpack系列-第三篇流程杂记 前言 本文章个人理解, 只是为了理清webpack流程, 没有关注内部过多细节 ...

随机推荐

  1. HttpURLConnection的使用

    import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; ...

  2. Modsecurity原理分析--从防御方面谈WAF的绕过(一)

    0x00 背景知识 一说到WAF,在我们安全工作者,或者作为普通的白帽子来说,就很头疼,因为好多时候,我们发到服务端的恶意流量都被挡掉了,于是就产生了各种绕“WAF”的话题,绕来绕去,也就无非那么多种 ...

  3. svn提示out of date

    你需要先update一下,应该会有一个冲突标志,你查看一下历史日志,找到是谁在你之前进行了提交,和他商议一下如何合并你们两个人的修改,然后在你本地处理后,标记“冲突已解决”,最后再次commit

  4. Gogs http和ssh地址显示localhost的问题

    问题描述: 如下图所示HTTP和SSH地址显示的是localhost而不是对应的域名或地址. 解决方案: 按以下方法修改Gogs配置文件并重启服务器 域名问题 RUN_USER = git DOMAI ...

  5. post 获取checkbox值

    $str_tag=""; $s=$_POST['goods_server_name']; for($i=0;$i<count($s);$i++){ if($i==0){ $s ...

  6. android onTouchEvent

    触摸屏幕时,没搞懂每个事件的启动顺序.本文记录onTouchEvent发生时,每个事件启动的顺序. 测试代码 @Override public boolean onTouchEvent(MotionE ...

  7. web 开发之nginx--- 阿里云部署nginx

    http://blog.csdn.net/zhangjingyangguang/article/details/7441268 http://www.cnblogs.com/languoliang/a ...

  8. WORD里怎样能做到局部“分栏”就是一页里有的分有的不分

    选中你要分的部分再分栏如果不想分的部分也被分了,那就可以选中不想分的那部分,选择“分栏”->“一栏” 转自:http://zhidao.baidu.com/question/9873268.ht ...

  9. 用SQL语句创建触发器

    --假设XSCJ数据库中增加一新表XS_HIS,表结构和表XS相同,用来存放从XS--表 --中删除的记录.创建一个触发器,当XS表被删除一行,把删除的记录写到日--志表XS_HIS中. CREATE ...

  10. 用Java向数据库中插入大量数据时的优化

    使用jdbc向数据库插入100000条记录,分别使用statement,PreparedStatement,及PreparedStatement+批处理3种方式进行测试: public void ex ...