所谓高并发,就是同一时间有很多流量(通常指用户)访问程序的接口、页面及其他资源,解决高并发就是当流量峰值到来时保证程序的稳定性。
我们一般用QPS(每秒查询数,又叫每秒请求数)来衡量程序的综合性能,数值越高越好,一般需要压测(ab工具)得到数据。
假设我们的一个进程(也可以是线程或者协程)处理一次请求花费了50毫秒(业内达标范围一般是20毫秒至60毫秒),那么1秒钟就可以处理20个请求,一台服务器是可以开很多这样的进程并行去处理请求的,比如开了128个,那么这台机器理论上的QPS=2560。
千万不要小瞧这个数字,当你的QPS真有这么高的时候意味着你的DAU(用户日活)有2560*200=51.2万,业内一般是放大200倍计算,有这样的日活说明做得很不错了。
一台服务器能够达到的最大QPS受很多因素的影响,比如机器参数配置、机房地理位置、CPU性能、内存大小、磁盘性能、带宽大小、程序语言、数据库性能、程序架构等,我们一一细说。

1.机器参数配置

这个很好理解,比如服务器最大可以开启128个进程,你设置了最大只开启100个,这属于服务器调优。

2.机房地理位置

如果你做海外用户,服务器机房应该选择国外的,反之应该选择国内的,因为机房距离用户越近,在传输上的时间损耗就越低。

3.CPU性能

CPU性能越好,处理速度就越快,核心数越多,能够并行开启的进程就越多。

4.内存大小

内存越大,程序就能把更多的数据直接放到内存,从内存读取数据比从磁盘读取数据的速度快很多。

5.磁盘性能

这个不用多说吧,一般固态硬盘的性能比机械硬盘的性能好很多,性能越好读写数据的速度就越快。

6.带宽大小

服务器的带宽一般指流出带宽,单位为Mb/S,比如带宽为8Mb/S即1MB/S,如果提供文件下载服务,可能一个用户的下载行为就把服务器带宽用完了。
一般把图片、视频、css文件、JavaScript脚本等资源放到第三方的CDN去,按流量计费,这样就不占用服务器带宽了。
如果用户规模小,基本上一台服务器就好了,这个时候一般会选按固定带宽大小计费。
如果用户规模很大了,基本上会用到负载均衡器来分流,即把流量按照一定的规则分配到不同的服务器上,负载均衡器一般会按流量来计费。
如果平均一次请求返回的数据大小为50KB,为了达到1000QPS这个指标,需要的带宽峰值=1000*50*8/1024=390.625Mb/S。
我们在设计接口的时候应该尽量减少返回的数据大小,比如user_id就可以简化为uid,像图片、视频、css等文件压缩的目的就是减少数据的大小。

7.程序语言

编译型语言的性能一般好于解释型语言的性能,比如go语言性能就好于php语言性能,当语言短期不会替换时,可以通过堆机器解决高并发问题。
使用性能高的函数,在满足业务的条件下尽量简化业务代码逻辑,避免循环中操作SQL,巧妙使用redis的各种类型。

8.数据库性能

一台服务器上部署的数据库总是有一个瓶颈的,比如每秒查询数、每秒写入数。
我们可以通过增加很多从库解决查询(select语句)的瓶颈,称之为多从库模型,需要注意的是主从同步数据可能有延迟,当修改数据后马上需要查询时需要设置强制从主库读取。
我们可以将业务拆分,让某些表存储在一个数据库实例上,另一些表存储在其他数据库实例上,虽然一个数据库实例有自己的瓶颈,但是很多的数据库实例堆积起来性能就会大大改善,多个数据库实例的方案称之为多主库模型,主要是为了解决写入瓶颈(insert语句、update语句、delete语句)。
如果你有多个主库又有多个从库,你就实现了多主多从模型。
如果一个表存储的数据量很大,这个时候就要考虑分表了(一般用中间件实现),比如按时间分表或者按用户分表,当把一个表的所有分表都放在一个数据库实例上都满足不了要求的时候,你应该把某些分表存储在新的数据库实例上,这个时候一个表的数据分布到了不同的数据库实例上,这就是所谓的分布式数据库方案了,你需要处理的事情就很复杂了,比如处理分布式事务。
数据库的并发连接数也是有限制的,我们可以用连接池技术来应对,就是保持一定数量的和数据库的连接不断开的长连接,需要连接数据库的时候就从池子里选择一个连接,用完放回去就好了,这个一般也是用中间件来实现。
好的索引也能提高数据库的性能,有时候比堆多个从库的方案还要好。
如果能够减少数据库的读写,也算间接提高了数据库的性能,比如我们用redis来做缓存,用消息队列异步落库等。
有时候某些数据用数据库来计算需要很长时间,可以取到元数据(最小粒度的数据)用程序来计算,这称之为用内存换时间。

总结

一般大型项目基本是前后端分离的,从性能方面说就是为了将页面渲染的处理在客户端运行,降低服务器的压力。
从带宽层面考虑,css、图片、视频、JavaScript等文件资源能用CDN的就用CDN,能压缩的就尽量压缩,接口能减小返回数据的大小就尽量减小。
为了解决编程语言的不足或者单台服务器的瓶颈,可以先堆机器应对。
索引、多主多从、分布式数据库、缓存、连接池、消息队列等是从数据库方便考虑如何优化性能。
有时候程序的低耦合性比程序的高性能更重要,不要一味地追求高性能。
 

如何设计高并发web应用的更多相关文章

  1. PHP-学习大规模高并发Web系统架构及开发推荐书籍

    以下书籍内容涵盖大型网站开发中几个关键点:高可用.高性能.分布式.易扩展.如果想对大规模高并发Web系统架构及开发有很系统的学习,可以阅读以下书籍,欢迎补充! 一.<Linux企业集群—用商用硬 ...

  2. 转---高并发Web服务的演变——节约系统内存和CPU

    [问底]徐汉彬:高并发Web服务的演变——节约系统内存和CPU 发表于22小时前| 4223次阅读| 来源CSDN| 22 条评论| 作者徐汉彬 问底Web服务内存CPU并发徐汉彬 摘要:现在的Web ...

  3. 高并发web系统设计

    转载自:http://blog.csdn.net/qq_26562641/article/details/53170913 一.一般高并发web系统这里的一般指的是秒杀之类的电子商务系统,比如说小米抢 ...

  4. nginx简介(轻量级开源高并发web服务器:大陆使用者百度、京东、新浪、网易、腾讯、淘宝等)(并发量5w)(一般网站apache够用了,而且稳定)

    nginx简介(轻量级开源高并发web服务器:大陆使用者百度.京东.新浪.网易.腾讯.淘宝等)(并发量5w)(一般网站apache够用了,而且稳定) 一.总结 1.在连接高并发的情况下,Nginx是A ...

  5. 高并发Web服务的演变:节约系统内存和CPU

    一.越来越多的并发连接数 现在的Web系统面对的并发连接数在近几年呈现指数增长,高并发成为了一种常态,给Web系统带来不小的挑战.以最简单粗暴的方式解决,就是增加Web系统的机器和升级硬件配置.虽然现 ...

  6. 高并发WEB网站优化方案

    一.什么是高并发在互联网时代,所讲的并发.高并发,通常是指并发访问,也就是在某个时间点,有多少个访问同时到来.比如,百度首页同时有1000个人访问,那么也就是并发为1000.通常一个系统的日PV在千万 ...

  7. 高并发 Web 服务的演变:节约系统内存和 CPU

    本文内容 越来越多的并发连接数 Web 前端优化,降低服务端压力 节约 Web 服务端的内存 节约 Web 服务器的 CPU 小结 一,越来越多的并发连接数 现在,Web 系统面对的并发连接数呈现指数 ...

  8. (转)高并发Web服务的演变——节约系统内存和CPU

    一.越来越多的并发连接数 现在的Web系统面对的并发连接数在近几年呈现指数增长,高并发成为了一种常态,给Web系统带来不小的挑战.以最简单粗暴的方式解决,就是增加Web系统的机器和升级硬件配置.虽然现 ...

  9. 【WEB】高并发Web服务的演变-节约系统内存和CPU

    目前主流浏览器通常可以存在2-6个并发. 连接和请求,占据了服务器的大量CPU和内存等资源.在资源数目超过100+的网站页面中,使用更多的下载连接,非常有必要. 缓解“高并发”的压力的手段. 一. W ...

随机推荐

  1. testng.xml配置

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "htt ...

  2. 2017蓝桥杯日期问题(C++B组)

    标题:日期问题小明正在整理一批历史文献.这些历史文献中出现了很多日期.小明知道这些日期都在1960年1月1日至2059年12月31日.令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的, ...

  3. Linux ssh登录出错

    今天登录远程主机的时候,出现了以下错误: @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @    WARNING: REMOT ...

  4. String 对象-->charAt() 方法

    1.定义和用法 charAt() 方法获取指定下标的字符,下标从0开始 语法: string.charAt(index) 参数: index:指定的下标 举例:获取下标为2的字符 var str = ...

  5. itoa、ltoa

    #include <stdlib.h> /*整形转字符型*/ char * itoa(int value, char *string, int radix) { char tmp[33]; ...

  6. Java入门第一阶段总结

    前言 写了三周的模拟题,对原本就厌恶的模拟更加深恶痛绝.但是不得不说模拟题是对一门语言入门掌握其语法成效最快的一类题,轻松地从C入门到了Java.一直坚信各门语言都是想通的,一力破万法. 作业过程总结 ...

  7. Spark 1.5 to 2.1.X

    api差异参考官网地址:https://spark.apache.org/docs/2.1.1/sql-programming-guide.html#upgrading-from-spark-sql- ...

  8. python3(十四) filter

    # 和map()类似,filter()也接收一个函数和一个序列. # 和map()不同的是,filter()把传入的函数依次作用于每个元素, # 然后根据返回值是True还是False决定保留还是丢弃 ...

  9. 关于node中两个模块相互引用却不会死循环的问题

    关于node中两个模块相互引用却不会死循环的问题 node中是通过require来导入加载模块的,require有两个作用: 1.加载文件模块并执行里面的代码 2.拿到被加载文件模块导出的接口对象 现 ...

  10. Spring 下,关于动态数据源的事务问题的探讨

    开心一刻 毒蛇和蟒蛇在讨论谁的捕猎方式最高效. 毒蛇:我只需要咬对方一口,一段时间内它就会逐渐丧失行动能力,最后死亡. 蟒蛇冷笑:那还得等生效时间,我只需要缠住对方,就能立刻致它于死地. 毒蛇大怒:你 ...