赞
踩
所谓高并发, 就是同一时间有很多流量 (通常指用户) 访问程序的接口、页面及其他资源, 解决高并发就是当流量峰值到来时保证程序的稳定性。
我们一般用 QPS(每秒查询数, 又叫每秒请求数)来衡量程序的综合性能, 数值越高越好, 一般需要压测 (ab 工具) 得到数据。
假设我们的一个进程 (也可以是线程或者协程) 处理一次请求花费了 50 毫秒(业内达标范围一般是 20 毫秒至 60 毫秒), 那么 1 秒钟就可以处理 20 个请求, 一台服务器是可以开很多这样的进程并行去处理请求的, 比如开了 128 个, 那么这台机器理论上的 QPS=2560。
千万不要小瞧这个数字, 当你的 QPS 真有这么高的时候意味着你的 DAU(用户日活)有 2560*200=51.2 万, 业内一般是放大 200 倍计算, 有这样的日活说明做得很不错了。
一台服务器能够达到的最大 QPS 受很多因素的影响, 比如机器参数配置、机房地理位置、CPU 性能、内存大小、磁盘性能、带宽大小、程序语言、数据库性能、程序架构等, 我们一一细说。
这个很好理解, 比如服务器最大可以开启 128 个进程, 你设置了最大只开启 100 个, 这属于服务器调优。
如果你做海外用户, 服务器机房应该选择国外的, 反之应该选择国内的, 因为机房距离用户越近, 在传输上的时间损耗就越低。
CPU 性能越好, 处理速度就越快, 核心数越多, 能够并行开启的进程就越多。
内存越大, 程序就能把更多的数据直接放到内存, 从内存读取数据比从磁盘读取数据的速度快很多。
这个不用多说吧, 一般固态硬盘的性能比机械硬盘的性能好很多, 性能越好读写数据的速度就越快。
服务器的带宽一般指流出带宽, 单位为 Mb/S, 比如带宽为 8Mb/S 即 1MB/S, 如果提供文件下载服务, 可能一个用户的下载行为就把服务器带宽用完了。
一般把图片、视频、css 文件、JavaScript 脚本等资源放到第三方的 CDN 去, 按流量计费, 这样就不占用服务器带宽了。
如果用户规模小, 基本上一台服务器就好了, 这个时候一般会选按固定带宽大小计费。
如果用户规模很大了, 基本上会用到负载均衡器来分流, 即把流量按照一定的规则分配到不同的服务器上, 负载均衡器一般会按流量来计费。
如果平均一次请求返回的数据大小为 50KB, 为了达到 1000QPS 这个指标, 需要的带宽峰值 = 1000508/1024=390.625Mb/S。
我们在设计接口的时候应该尽量减少返回的数据大小, 比如 user_id 就可以简化为 uid, 像图片、视频、css 等文件压缩的目的就是减少数据的大小。
编译型语言的性能一般好于解释型语言的性能, 比如 go 语言性能就好于 php 语言性能, 当语言短期不会替换时, 可以通过堆机器解决高并发问题。
一台服务器上部署的数据库总是有一个瓶颈的, 比如每秒查询数、每秒写入数。
我们可以通过增加很多从库解决查询 (select 语句) 的瓶颈, 称之为多从库模型, 需要注意的是主从同步数据可能有延迟, 当修改数据后马上需要查询时需要设置强制从主库读取。
我们可以将业务拆分, 让某些表存储在一个数据库实例上, 另一些表存储在其他数据库实例上, 虽然一个数据库实例有自己的瓶颈, 但是很多的数据库实例堆积起来性能就会大大改善, 多个数据库实例的方案称之为多主库模型, 主要是为了解决写入瓶颈(insert 语句、update 语句、delete 语句)。
如果你有多个主库又有多个从库, 你就实现了多主多从模型。
如果一个表存储的数据量很大, 这个时候就要考虑分表了(一般用中间件实现), 比如按时间分表或者按用户分表, 当把一个表的所有分表都放在一个数据库实例上都满足不了要求的时候, 你应该把某些分表存储在新的数据库实例上, 这个时候一个表的数据分布到了不同的数据库实例上, 这就是所谓的分布式数据库方案了, 你需要处理的事情就很复杂了, 比如处理分布式事务。
数据库的并发连接数也是有限制的, 我们可以用连接池技术来应对, 就是保持一定数量的和数据库的连接不断开的长连接, 需要连接数据库的时候就从池子里选择一个连接, 用完放回去就好了, 这个一般也是用中间件来实现。
好的索引也能提高数据库的性能, 有时候比堆多个从库的方案还要好。
如果能够减少数据库的读写, 也算间接提高了数据库的性能, 比如我们用 redis 来做缓存, 用消息队列异步落库等。
有时候某些数据用数据库来计算需要很长时间, 可以取到元数据 (最小粒度的数据) 用程序来计算, 这称之为用内存换时间。
比如实现同样的功能, 初级程序员写的程序需要循环 100 次, 而高级程序员写的程序只需要循环 10 次, 效果肯定不一样。
总结
一般大型项目基本是前后端分离的, 从性能方面说就是为了将页面渲染的处理在客户端运行, 降低服务器的压力。
从带宽层面考虑, css、图片、视频、JavaScript 等文件资源能用 CDN 的就用 CDN, 能压缩的就尽量压缩, 接口能减小返回数据的大小就尽量减小。
为了解决编程语言的不足或者单台服务器的瓶颈, 可以先堆机器应对。
索引、多主多从、分布式数据库、缓存、连接池、消息队列等是从数据库方便考虑如何优化性能。
有时候程序的低耦合性比程序的高性能更重要, 不要一味地追求高性能。
开发的原因, 需要对吞吐量 (TPS)、QPS、并发数、响应时间(RT) 几个概念做下了解, 查自百度百科, 记录如下:
响应时间是指系统对请求作出响应的时间。直观上看, 这个指标与人对软件性能的主观感受是非常一致的, 因为它完整地记录了整个计算机系统处理请求的时间。由于一个系统通常会提供许多功能, 而不同功能的处理逻辑也千差万别, 因而不同功能的响应时间也不尽相同, 甚至同一功能在不同输入数据的情况下响应时间也不相同。所以, 在讨论一个系统的响应时间时, 人们通常是指该系统所有功能的平均时间或者所有功能的最大响应时间。当然, 往往也需要对每个或每组功能讨论其平均响应时间和最大响应时间。
对于单机的没有并发操作的应用系统而言, 人们普遍认为响应时间是一个合理且准确的性能指标。需要指出的是, 响应时间的绝对值并不能直接反映软件的性能的高低, 软件性能的高低实际上取决于用户对该响应时间的接受程度。对于一个游戏软件来说, 响应时间小于 100 毫秒应该是不错的, 响应时间在 1 秒左右可能属于勉强可以接受, 如果响应时间达到 3 秒就完全难以接受了。而对于编译系统来说, 完整编译一个较大规模软件的源代码可能需要几十分钟甚至更长时间, 但这些响应时间对于用户来说都是可以接受的。
吞吐量是指系统在单位时间内处理请求的数量。对于无并发的应用系统而言, 吞吐量与响应时间成严格的反比关系, 实际上此时吞吐量就是响应时间的倒数。前面已经说过, 对于单用户的系统, 响应时间 (或者系统响应时间和应用延迟时间) 可以很好地度量系统的性能, 但对于并发系统, 通常需要用吞吐量作为性能指标。
对于一个多用户的系统, 如果只有一个用户使用时系统的平均响应时间是 t, 当有你 n 个用户使用时, 每个用户看到的响应时间通常并不是 n×t, 而往往比 n×t 小很多(当然, 在某些特殊情况下也可能比 n×t 大, 甚至大很多)。这是因为处理每个请求需要用到很多资源, 由于每个请求的处理过程中有许多不走难以并发执行, 这导致在具体的一个时间点, 所占资源往往并不多。也就是说在处理单个请求时, 在每个时间点都可能有许多资源被闲置, 当处理多个请求时, 如果资源配置合理, 每个用户看到的平均响应时间并不随用户数的增加而线性增加。实际上, 不同系统的平均响应时间随用户数增加而增长的速度也不大相同, 这也是采用吞吐量来度量并发系统的性能的主要原因。一般而言, 吞吐量是一个比较通用的指标, 两个具有不同用户数和用户使用模式的系统, 如果其最大吞吐量基本一致, 则可以判断两个系统的处理能力基本一致。
并发用户数是指系统可以同时承载的正常使用系统功能的用户的数量。与吞吐量相比, 并发用户数是一个更直观但也更笼统的性能指标。实际上, 并发用户数是一个非常不准确的指标, 因为用户不同的使用模式会导致不同用户在单位时间发出不同数量的请求。一网站系统为例, 假设用户只有注册后才能使用, 但注册用户并不是每时每刻都在使用该网站, 因此具体一个时刻只有部分注册用户同时在线, 在线用户就在浏览网站时会花很多时间阅读网站上的信息, 因而具体一个时刻只有部分在线用户同时向系统发出请求。这样, 对于网站系统我们会有三个关于用户数的统计数字: 注册用户数、在线用户数和同时发请求用户数。由于注册用户可能长时间不登陆网站, 使用注册用户数作为性能指标会造成很大的误差。而在线用户数和同事发请求用户数都可以作为性能指标。相比而言, 以在线用户作为性能指标更直观些, 而以同时发请求用户数作为性能指标更准确些。
每秒查询率 QPS 是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准, 在因特网上, 作为域名系统服务器的机器的性能经常用每秒查询率来衡量。对应 fetches/sec, 即每秒的响应请求数, 也即是最大吞吐能力。 (看来是类似于 TPS, 只是应用于特定场景的吞吐量)
我们在日常工作中经常会听到 QPS/TPS 这些名词, 也会经常被别人问起说你的系统吞吐量有多大。这个问题从业务上来讲, 可以理解为应用系统每秒钟最大能接受的用户访问量。或者每秒钟最大能处理的请求数;
QPS: 每秒钟处理完请求的次数; 注意这里是处理完。具体是指发出请求到服务器处理完成功返回结果。可以理解在 server 中有个 counter, 每处理一个请求加 1, 1 秒后 counter=QPS。
TPS: 每秒钟处理完的事务次数, 一般 TPS 是对整个系统来讲的。一个应用系统 1s 能完成多少事务处理, 一个事务在分布式处理中, 可能会对应多个请求, 对于衡量单个接口服务的处理能力, 用 QPS 比较多。
并发量: 系统能同时处理的请求数
RT: 响应时间, 处理一次请求所需要的平均处理时间
计算关系:
QPS = 并发量 / 平均响应时间
并发量 = QPS * 平均响应时间
Queries Per Second 意思是 “每秒查询率”, 是一台服务器每秒能够相应的查询次数, 是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
是 TransactionsPerSecond 的缩写, 也就是事务数 / 秒。它是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请时开始计时, 收到服务器响应后结束计时, 以此来计算使用的时间和完成的事务个数。
ab 是一种用于测试 Apache 超文本传输协议 (HTTP) 服务器的工具。apache 自带 ab 工具, 可以测试 apache、IIs、tomcat、nginx 等服务器。
但是 ab 没有 Jmeter、Loadrunner 那样有各种场景设计、各种图形报告和监控, 只需一个命令即可, 有输出描述可以简单的进行一些压力测试。
ab 命令同时满足 http 及 https 的请求, 常用请求参数: -n
请求次数, -c
并发数
示例:
ab -n 100 -c 10 http://test.com/
其中 -n
表示请求数, -c
表示并发数。
概念: 某个时刻服务器所接受的请求数目, 简单的讲, 就是一个会话。
概念: 要注意区分这个概念和并发连接数之间的区别, 一个用户可能同时会产生多个会话, 也即连接数。
计算公式: 处理完成所有请求数所花费的时间 / (总请求数 / 并发用户数), 即
Time per request = Time taken for tests /( Complete requests / Concurrency Level)
计算公式: 处理完成所有请求数所花费的时间 / 总请求数, 即
Time taken for / testsComplete requests
可以看到, 它是吞吐率的倒数。
同时, 它也 = 用户平均请求等待时间 / 并发用户数, 即
Time per request / Concurrency Level
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LLNYkDd8-1670570688182)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/web-test-total.webp)]
这段展示的是 web 服务器的信息, 可以看到服务器采用的是 nginx, 域名是 wan.bigertech.com, 端口是 80
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aSJlHWNd-1670570688182)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/web-test-1.webp)]
这段是关于请求的文档的相关信息, 所在位置 “/”, 文档的大小为 338436 bytes(此为 http 响应的正文长度)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P60M8gBs-1670570688183)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/web-test-2.webp)]
这段展示了压力测试的几个重要指标
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EFzcL9n4-1670570688183)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/web-test-3.webp)]
Concurrency Level: 100
// 并发请求数
Time taken for tests: 50.872 seconds
// 整个测试持续的时间
Complete requests: 1000
// 完成的请求数
Failed requests: 0
// 失败的请求数
Total transferred: 13701482 bytes
// 整个场景中的网络传输量
HTML transferred: 13197000 bytes
// 整个场景中的 HTML 内容传输量
Requests per second: 19.66 [#/sec] (mean)
// 吞吐率, 大家最关心的指标之一, 相当于 LR 中的每秒事务数, 后面括号中的 mean 表示这是一个平均值
Time per request: 5087.180 [ms] (mean)
// 用户平均请求等待时间, 大家最关心的指标之二, 相当于 LR 中的平均事务响应时间, 后面括号中的 mean 表示这是一个平均值
Time per request: 50.872 [ms] (mean, across all concurrent requests)
// 服务器平均请求处理时间, 大家最关心的指标之三
Transfer rate: 263.02 [Kbytes/sec] received
// 平均每秒网络上的流量, 可以帮助排除是否存在网络流量过大导致响应时间延长的问题
这段表示网络上消耗的时间的分解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hbJTAI3-1670570688183)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/web-test-4.webp)]
这段是每个请求处理时间的分布情况, 50% 的处理时间在 4930ms 内, 66% 的处理时间在 5008ms 内…, 重要的是看 90% 的处理时间。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RRUo1dF0-1670570688183)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/web-test-5.webp)]
有时候进行压力测试需要用户登录, 怎么办? 请参考以下步骤:
先用账户和密码登录后, 用开发者工具找到标识这个会话的 Cookie 值 (Session ID) 记下来
如果只用到一个 Cookie, 那么只需键入命令:
ab -n 100 -C key=value http://test.com/
如果需要多个 Cookie, 就直接设 Header:
ab -n 100 -H "Cookie: Key1=Value1; Key2=Value2" http://test.com/
总的来说 ab 工具 ab 小巧简单, 上手学习较快, 可以提供需要的基本性能指标, 但是没有图形化结果, 不能监控。因此 ab 工具可以用作临时紧急任务和简单测试。
同类型的压力测试工具还有: webbench、siege、http_load 等。
Usage: ab [options] [http[s]://]hostname[:port]/path
Options are:
-n requests Number of requests to perform
-c concurrency Number of multiple requests to make at a time
-t timelimit Seconds to max. to spend on benchmarking
This implies -n 50000
-s timeout Seconds to max. wait for each response
Default is 30 seconds
-b windowsize Size of TCP send/receive buffer, in bytes
-B address Address to bind to when making outgoing connections
-p postfile File containing data to POST. Remember also to set -T
-u putfile File containing data to PUT. Remember also to set -T
-T content-type Content-type header to use for POST/PUT data, eg.
'application/x-www-form-urlencoded'
Default is 'text/plain'
-v verbosity How much troubleshooting info to print
-w Print out results in HTML tables
-i Use HEAD instead of GET
-x attributes String to insert as table attributes
-y attributes String to insert as tr attributes
-z attributes String to insert as td or th attributes
-C attribute Add cookie, eg. 'Apache=1234'. (repeatable)
-H attribute Add Arbitrary header line, eg. 'Accept-Encoding: gzip'
Inserted after all normal header lines. (repeatable)
-A attribute Add Basic WWW Authentication, the attributes
are a colon separated username and password.
-P attribute Add Basic Proxy Authentication, the attributes
are a colon separated username and password.
-X proxy:port Proxyserver and port number to use
-V Print version number and exit
-k Use HTTP KeepAlive feature
-d Do not show percentiles served table.
-S Do not show confidence estimators and warnings.
-q Do not show progress when doing more than 150 requests
-l Accept variable document length (use this for dynamic pages)
-g filename Output collected data to gnuplot format file.
-e filename Output CSV file with percentages served
-r Don't exit on socket receive errors.
-m method Method name
-h Display usage information (this message)
-I Disable TLS Server Name Indication (SNI) extension
-Z ciphersuite Specify SSL/TLS cipher suite (See openssl ciphers)
-f protocol Specify SSL/TLS protocol
(TLS1, TLS1.1, TLS1.2 or ALL)
ab 命令是 Apache 的 Web 服务器的性能测试工具, 它可以测试安装 Web 服务器每秒种处理的 HTTP 请求。
ab(选项)(参数)
-A: 指定连接服务器的基本的认证凭据;
-c: 指定一次向服务器发出请求数;
-C: 添加 cookie;
-g: 将测试结果输出为 "gnuolot" 文件;
-h: 显示帮助信息;
-H: 为请求追加一个额外的头;
-i: 使用 "head" 请求方式;
-k: 激活 HTTP 中的 "keepAlive" 特性;
-n: 指定测试会话使用的请求数;
-p: 指定包含数据的文件;
-q: 不显示进度百分比;
-T: 使用 POST 数据时, 设置内容类型头;
-v: 设置详细模式等级;
-w: 以 HTML 表格方式打印结果;
-x: 以表格方式输出时, 设置表格的属性;
-X: 使用指定的代理服务器发送请求;
-y: 以表格方式输出时, 设置表格属性。
主机: 被测试主机。
可以通过压力测试对网站及服务器性能进行高压测试, 暴露出其所存在的问题。从而对服务器及网站进行调整和优化。
注意在进行压力测试时要在单独的机器上进行不要在待测服务器上进行。目前主要有 apache 的 ab、http_load、webbench、Siege 等。
程序非常小, 解压后也不到 100K
http_load 以并行复用的方式运行, 用以测试 web 服务器的吞吐量与负载。但是它不同于大多数压力测试工具, 它可以以一个单一的进程运行, 一般不会把客户机搞死。还可以测试 HTTPS 类的网站请求。
下载并编译安装:
wget http://www.acme.com/software/http_load/http_load-09Mar2016.tar.gz
tar zxf http_load-09Mar2016.tar.gz
cd http_load-09Mar2016
make && make install
命令格式:
http_load -p 并发访问进程数 -s 访问时间 需要访问的 URL 文件
参数其实可以自由组合, 参数之间的选择并没有什么限制。比如你写成 http_load -parallel 5 -seconds 300 urls.txt
也是可以的。
我们把参数给大家简单说明一下。
-parallel
简写 -p
: 含义是并发的用户进程数。-fetches
简写 -f
: 含义是总计的访问次数-rate
简写 -r
: 含义是每秒的访问频率-seconds
简写 -s
: 含义是总计的访问时间准备 URL 文件: urllist.txt
, 文件格式是每行一个 URL, URL 最好超过 50-100 个测试效果比较好.
例如:
http_load -p 30 -s 60 urllist.txt
参数了解了, 我们来看运行一条命令来看看它的返回结果
命令: % ./http_load -rate 5 -seconds 10 urls
说明执行了一个持续时间 10
秒的测试, 每秒的频率为 5
。
49 fetches, 2 max parallel, 289884 bytes, in 10.0148 seconds5916 mean bytes/connection4.89274
fetches/sec, 28945.5 bytes/secmsecs/connect: 28.8932 mean, 44.243 max, 24.488 minmsecs/first
-response: 63.5362 mean, 81.624 max, 57.803 minHTTP response codes: code 200 -- 49
结果分析:
要注意是否系统遇到了瓶颈。
特殊说明:
测试结果中主要的指标是 fetches/sec
、msecs/connect
这个选项, 即服务器每秒能够响应的查询次数, 用这个指标来衡量性能。似乎比 apache 的 ab 准确率要高一些, 也更有说服力一些。
Qpt - 每秒响应用户数和 response time, 每连接响应用户时间。
测试的结果主要也是看这两个值。当然仅有这两个指标并不能完成对性能的分析, 我们还需要对服务器的 cpu、men 进行分析, 才能得出结论。
webbench 是 Linux 下的一个网站压力测试工具, 最多可以模拟 3 万个并发连接去测试网站的负载能力。下载
地址可以到 google 搜, 我这里给出一个,下载地址: http://soft.vpser.net/test/webbench/webbench-1.5.tar.gz
这个程序更小, 解压后不到 50K, 呵呵,安装非常简单:
wget http://soft.vpser.net/test/webbench/webbench-1.5.tar.gz
tar zxvf webbench-1.5.tar.gz
cd webbench-1.5
make && make install
会在当前目录生成 webbench 可执行文件, 直接可以使用了
用法:
webbench -c 并发数 -t 运行测试时间 URL
如:
webbench -c 5000 -t 120 http://www.google.com
ab 是 apache 自带的一款功能强大的测试工具安装了 apache 一般就自带了, 用法可以查看它的说明。
ab 参数众多, 一般我们用到的是 -n
和 -c
例如:
./ab -c 1000 -n 100 http://www.google.com/index.php
这个表示同时处理 1000 个请求并运行 100 次 index.php
文件.
一款开源的压力测试工具, 可以根据配置对一个 WEB 站点进行多用户的并发访问, 记录每个用户所有请求过程的相应时间, 并在一定数量的并发访问下重复进行。
官方: http://www.joedog.org/
Siege 下载: wget http://download.joedog.org/siege/siege-4.0.2.tar.gz
解压:
tar zxf siege-4.0.2.tar.gz
进入解压目录:
cd siege-4.0.2
安装:
./configure
make && make install
使用
siege -c 200 -r 10 -f example.url
-c
是并发量, -r
是重复次数。 url 文件就是一个文本, 每行都是一个 url, 它会从里面随机访问的。
example.url 内容:
http://www.google.com
http://www.baidu.com
结果说明
Lifting the server siege… done.
Transactions: 3419263 hits // 完成 419263 次处理
Availability: 100.00 % //100.00 % 成功率
Elapsed time: 5999.69 secs // 总共用时
Data transferred: 84273.91 MB // 共数据传输 84273.91 MB
Response time: 0.37 secs // 相应用时 1.65 秒: 显示网络连接的速度
Transaction rate: 569.91 trans/sec // 均每秒完成 569.91 次处理: 表示服务器后
Throughput: 14.05 MB/sec // 平均每秒传送数据
Concurrency: 213.42 // 实际最高并发数
Successful transactions: 2564081 // 成功处理次数
Failed transactions: 11 // 失败处理次数
Longest transaction: 29.04 // 每次传输所花最长时间
Shortest transaction: 0.00 // 每次传输所花最短时间
Load testing is a good idea before any deployment. It’s nice to quickly establish a best-case scenario for a project before running more detailed tests down the road.
The ApacheBench tool (ab) can load test servers by sending an arbitrary number of concurrent requests. Although ab was designed for testing Apache installations, it can be used to benchmark any HTTP server.
In this tutorial, we will see how a Ruby interpreter with different servers performs under load. The tutorial steps assume a fresh Ubuntu 13.10 x32 image. The results were obtained from a 512 MB droplet.
Refresh the package database.
apt-get update
Install the apache2-utils package to get access to ApacheBench.
apt-get install apache2-utils
Next, create the user that will manage Ruby. It’s not a good idea to run some of the commands in the next section as root.
useradd -m -d /home/test -s /bin/bash -g sudo test
What this command accomplishes:
useradd
- create a new user-m
- create the home directory-d /home/test
- set the user’s home directory to /home/test-s /bin/bash
- make the user’s default shell bash (Ubuntu uses dash by default)-g sudo
- add user to the sudo group (for running commands with sudo)test
- the name of the new userSet the password for the new user.
passwd test
Switch to the new user.
su test
The Ruby Version Manager makes it easy to work with different Ruby environments. It takes care of the process of installing specific Ruby versions and isolating gemsets. It is currently installed by running a bash script from their website.
\curl -L https://get.rvm.io | bash -s stable
In order to use the rvm command, you need to first run the rvm script.
source ~/.rvm/scripts/rvm
If you want, you can put it in your .bashrc so that rvm is available any time you login as the user.
echo "source ~/.rvm/scripts/rvm" >> ~./bashrc
You can verify that the rvm script is being used by checking the head of type. It should be a function and not hashed.
type rvm | head -1
rvm is a function
Next, install Ruby 2.0.0. RVM will ask for the user’s password because it needs to install an assortment of dependencies before it can make Ruby. Since RVM builds Ruby from source, this step may take a while.
rvm install 2.0.0
Switch to the new Ruby. This might happen by default after the installation, but checking doesn’t hurt.
rvm use 2.0.0
Now that Ruby is installed, you can create a simple site and see how many requests it can handle.
Install Sinatra. It’s a microframework/DSL for creating Ruby web applications. The --no-* flags skip the documentation.
gem install sinatra --no-rdoc --no-ri
Create the sample sinatra app which just echoes “hello world”.
cd ~
vim app.rb
## app.rb
require 'sinatra'
get '/' do
'hello world'
end
Run the server.
ruby app.rb
With the server finally up, you can start load testing. A call to ab looks like this:
ab -n <num_requests> -c <concurrency> <addr>:<port><path>
Open another terminal and ssh into the server again. Run a test with ApacheBench. I used 1000 requests with a concurrency of 100. Don’t forget the final’/’ for the path.
ab -n 1000 -c 100 http://localhost:4567/
Server Software: WEBrick/1.3.1
Server Hostname: localhost
Server Port: 4567
Document Path: /
Document Length: 11 bytes
Concurrency Level: 100
Time taken for tests: 3.410 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 288000 bytes
HTML transferred: 11000 bytes
Requests per second: 293.23 [#/sec] (mean)
Time per request: 341.034 [ms] (mean)
Time per request: 3.410 [ms] (mean, across all concurrent requests)
Transfer rate: 82.47 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 2.0 0 11
Processing: 185 332 90.3 311 578
Waiting: 28 280 83.2 267 574
Total: 193 333 89.7 311 578
Percentage of the requests served within a certain time (ms)
50% 311
66% 357
75% 423
80% 446
90% 467
95% 480
98% 490
99% 501
100% 578 (longest request)
My results converged around 300 requests/second. WEBrick is not known for its speed. Go ahead and interrupt the server with Ctrl-c.
Thin is a popular ruby web server that uses Mongrel for parsing and EventMachine for non-blocking IO. Install Thin and run the server again. Sinatra should load Thin automatically and let you know (“…with backup from Thin”).
gem install thin
ruby app.rb
Now, try the load test again. It should be a bit faster this time.
Server Software: thin
Server Hostname: localhost
Server Port: 4567
Document Path: /
Document Length: 11 bytes
Concurrency Level: 100
Time taken for tests: 1.339 seconds
Complete requests: 1000
Failed requests: 0
Write errors: 0
Total transferred: 244000 bytes
HTML transferred: 11000 bytes
Requests per second: 747.00 [#/sec] (mean)
Time per request: 133.870 [ms] (mean)
Time per request: 1.339 [ms] (mean, across all concurrent requests)
Transfer rate: 178.00 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 1 1.8 0 8
Processing: 55 128 19.9 132 155
Waiting: 42 116 19.7 121 144
Total: 62 129 18.5 132 156
Percentage of the requests served within a certain time (ms)
50% 132
66% 135
75% 137
80% 139
90% 144
95% 149
98% 152
99% 155
100% 156 (longest request)
At least in this case, it looks like Thin makes for a notably faster server than WEBrick at over 700 requests/second (You can try raising the total requests, but it didn’t get much higher for me).
Note: I was able to get 1000 requests/second on an Arch Linux droplet.
Obviously, these results do not reflect realistic server performance. HTTP is just one piece of the puzzle. A slow templating engine and/or database will drag these numbers down significantly. Still, it gives you a quick ballpark figure for comparison.
Other performance tools you might be interested in:
You develop an application, it starts growing, but at the same time your expanding userbase might slow the app down. So what can you do about it? Well, it’s time for load testing! I’ll focus on the one of the easiest tools - Apache Bench.
You develop an application, it starts growing and growing, and you feel pretty good about it. But as it keeps growing, your userbase might not feel quite as good about it as you do - it’s infuriating to use a laggy app or website. So what can we do about it? Well, it’s time for load testing! We’ll focus on the one of the easiest tools - Apache Bench.
The tool was originally intended for testing Apache HTTP servers, nevertheless it does a good job of testing any web server. It generates a flood of queries to the given URL and returns the results. You don’t have to install any additional plugins because ab is already on your OS X or Linux system. The only thing we have to do is run it in the console, for example:
$ ab -n 1000 -c 20 http://yoursite.com/
This benchmark hits the address 1000 times (-n option), making 20 concurrent requests (-c option) - basically the number of users making requests at the same time.
Let’s try testing the netguru site.
$ ab -n 500 -c 20 https://netguru.co/
As you can see I’ve made 500 requests with a concurrency level of 20. You might have expected all the requests to be completed with status code 200 (meaning that everything’s okay), but there were over 40 failed requests! Don’t worry - these failed requests don’t mean that there isn’t a status code 200, but rather that the response time across requests was different.
You may also notice two values of time per request. The first one indicates how much time was needed to complete one request. For users, this translates into how much time it took to load the whole page. The second value (across all concurrent requests) means how much the total time would increase if we added one extra request (-n 501) with the same concurrency level (at least, in theory). Moreover, there’s a couple of connection times possible for the requests.
You can also use Apache Bench to benchmark a website where the authentication is based on session. All you need is to get a cookie value before the test. For Rails applications, the session name will be called yourapplication_session
. When you have the cookie, you can use:
$ ab -n 1000 -c 20 -C session_name=cookie_value http://yoursite.com/admin
It’s worth observing how your application behaves as it gets bigger or with a sudden influx of visitors. With this data, you can consider how to improve your application’s performance or even check the traffic while benchmarking using New Relic.
You are working for months on a new web application or e-commerce system and usually a few weeks or just days before the launch a complete enough feature set is running on a production-like system so that you can run a realistic load-test. Hopefully providing you with accurate picture of the performance of your future system.
To safe time and effort, you probably opt for the simple solution and use the wide-spread Apache Benchmark (ab) or siege commandline tools to setup a load-test. Both allow you to generate load on a given URL and collect performance metrics. Siege even allows you to provide a list of URLs and login if necessary with a little more effort. The results from both tools are simple numbers that are easy to communicate: users / second and average, min, max response time.
We often advise to resist the temptation of simple tools and numbers, because they are suited for benchmarking and you cannot trust the results of ab or siege to be realistic real-world load-simulation of your system.
There are a number of reasons for this:
The problem with this approach is that you will probably have a much higher cache ratio in all parts of your stack (Reverse Proxy, MySQL, Memcache, Opcode Cache, Kernel) then under real-world traffic.
You need more randomness in bot users following different paths, starting at and visiting different pages to simulate the real amount of cache misses.
In more complex load-testing setups, you would define several different scenarios such as anonymous user, search-engine bot, logged in user, random traffic user, buying user and so on. Then you would configure your test to run different shares of each scenario to provide a more realistic model of your real world traffic.
ab and siege cannot be used to define complex use-cases with form submission or multi-step processes (for example a checkout). Code triggered by complex use-cases usually has a higher resource usage that can affect the performance of the other endpoints. Example: If your homepage can handle 100 users / second without traffic on any other pages, then maybe its only 20 users / second as soon as other, heavier pages are requested at the same time.
The requests / second and average response time metrics are simple to understand and communicate, but are misleading in the end.With requests / second metric, all you can actually say is “When our site is used with this unrealistic traffic pattern, then we can handle so many users per second.” Not very re-assuring, given the three previous arguments about how far of we are from real-world usage.Second, you should never use the average to analyse response times. The average is calculated assuming a statistical normal distribution. But response time data is almost always either log-normal distributed or the distribution has peaks due to caching. This means different percentiles at 50%, 75%, 90%, 95% and 99% provide you with much better insights.
Are there reasons to use ab or siege? Yes. When you develop locally on a specific page and try to optimize it using a benchmark. You can quickly get a relative comparison of the performance before and after a change under similar traffic conditions.
But if you want a realistic estimate of the traffic your production system can handle, then you should use specialized tools such as Apache jMeter.
In addition to a UI, where you can click together complex use-cases and scenarios using different load-generating strategies, jMeter is also fully programmable to every possible use-case. It does take time to learn jMeter, but as a result you are much more flexible to run different detailed scenarios and get detailed data from every single request that you can analyze.
The Apache JMeter™ application is open source software, a 100% pure Java application designed to load test functional behavior and measure performance. It was originally designed for testing Web Applications but has since expanded to other test functions.
Apache JMeter may be used to test performance both on static and dynamic resources, Web dynamic applications.
It can be used to simulate a heavy load on a server, group of servers, network or object to test its strength or to analyze overall performance under different load types.
一个小型的网站, 可以使用最简单的 html 静态页面就实现了, 配合一些图片达到美化效果, 所有的页面均存放在一个目录下, 这样的网站对系统架构、性能的要求都很简单。
随着互联网业务的不断丰富, 网站相关的技术经过这些年的发展, 已经细分到很细的方方面面, 尤其对于大型网站来说, 所采用的技术更是涉及面非常广, 从硬件到软件、编程语言、数据库、WebServer、防火墙等各个领域都有了很高的要求, 已经不是原来简单的 html 静态网站所能比拟的。
大型网站, 比如门户网站, 在面对大量用户访问、高并发请求方面, 基本的解决方案集中在这样几个环节: 使用高性能的服务器、高性能的数据库、高效率的编程语言、还有高性能的 Web 容器。这几个解决思路在一定程度上意味着更大的投入。
除了门户和信息发布类型的网站, 对于交互性要求很高的社区类型网站来说, 尽可能的静态化也是提高性能的必要手段, 将社区内的帖子、文章进行实时的静态化, 有更新的时候再重新静态化也是大量使用的策略, 像 Mop 的大杂烩就是使用了这样的策略, 网易社区等也是如此。
同时, html 静态化也是某些缓存策略使用的手段, 对于系统中频繁使用数据库查询但是内容更新很小的应用, 可以考虑使用 html 静态化来实现, 比如论坛中论坛的公用设置信息, 这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中, 这些信息其实大量被前台程序调用, 但是更新频率很小, 可以考虑将这部分内容进行后台更新的时候进行静态化, 这样避免了大量的数据库访问请求。
对于 Web 服务器来说, 不管是 Apache、IIS 还是其他容器, 图片是最消耗资源的, 于是我们有必要将图片与页面进行分离, 这是基本上大型网站都会采用的策略, 他们都有独立的图片服务器, 甚至很多台图片服务器。这样的架构可以降低提供页面访问请求的服务器系统压力, 并且可以保证系统不会因为图片问题而崩溃, 在应用服务器和图片服务器上, 可以进行不同的配置优化, 比如 apache 在配置 ContentType 的时候可以尽量少支持, 尽可能少的 LoadModule, 保证更高的系统消耗和执行效率。
大型网站都有复杂的应用, 这些应用必须使用数据库, 那么在面对大量访问的时候, 数据库的瓶颈很快就能显现出来, 这时一台数据库将很快无法满足应用, 于是我们需要使用数据库集群或者库表散列。
在数据库集群方面, 很多数据库都有自己的解决方案, Oracle、Sybase 等都有很好的方案, 常用的 MySQL 提供的 Master/Slave 也是类似的方案, 您使用了什么样的 DB, 就参考相应的解决方案来实施即可。
上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用 DB 类型的限制, 于是我们需要从应用程序的角度来考虑改善系统架构, 库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离, 不同的模块对应不同的数据库或者表, 再按照一定的策略对某个页面或者功能进行更小的数据库散列, 比如用户表, 按照用户 ID 进行表散列, 这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu 的论坛就是采用了这样的架构, 将论坛的用户、设置、帖子等信息进行数据库分离, 然后对帖子、用户按照板块和 ID 进行散列数据库和表, 最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。
网站架构和网站开发中的缓存也是非常重要。这里先讲述最基本的两种缓存。高级和分布式的缓存在后面讲述。
架构方面的缓存, 对 Apache 比较熟悉的人都能知道 Apache 提供了自己的缓存模块, 也可以使用外加的 Squid 模块进行缓存, 这两种方式均可以有效的提高 Apache 的访问响应能力。
网站程序开发方面的缓存, Linux 上提供的 Memory Cache 是常用的缓存接口, 可以在 web 开发中使用, 比如用 Java 开发的时候就可以调用 MemoryCache 对一些数据进行缓存和通讯共享, 一些大型社区使用了这样的架构。另外, 在使用 web 语言开发的时候, 各种语言基本都有自己的缓存模块和方法, PHP 有 Pear 的 Cache 模块, Java 就更多了, .net 不是很熟悉, 相信也肯定有。
镜像是大型网站常采用的提高性能和数据安全性的方式, 镜像的技术可以解决不同网络接入商和地域带来的用户访问速度差异, 比如 ChinaNet 和 EduNet 之间的差异就促使了很多网站在教育网内搭建镜像站点, 数据进行定时更新或者实时更新。在镜像的细节技术方面, 这里不阐述太深, 有很多专业的现成的解决架构和产品可选。也有廉价的通过软件实现的思路, 比如 linux 上的 rsync 等工具。
负载均衡将是大型网站解决高负荷访问和大量并发请求采用的终极解决办法。
负载均衡技术发展了多年, 有很多专业的服务提供商和产品可以选择, 我个人接触过一些解决方法, 其中有两个架构可以给大家做参考。
第四层交换使用第三层和第四层信息包的报头信息, 根据应用区间识别业务流, 将整个区间段的业务流分配到合适的应用服务器进行处理。 第四层交换功能就象是虚 IP, 指向物理服务器。它传输的业务服从的协议多种多样, 有 HTTP、FTP、NFS、Telnet 或其他协议。这些业务在物理服务器基础上, 需要复杂的载量平衡算法。在 IP 世界, 业务类型由终端 TCP 或 UDP 端口地址来决定, 在第四层交换中的应用区间则由源端和终端 IP 地址、TCP 和 UDP 端口共同决定。
在硬件四层交换产品领域, 有一些知名的产品可以选择, 比如 Alteon、F5 等, 这些产品很昂贵, 但是物有所值, 能够提供非常优秀的性能和很灵活的管理能力。Yahoo 中国当初接近 2000 台服务器使用了三四台 Alteon 就搞定了。
大家知道了硬件四层交换机的原理后, 基于 OSI 模型来实现的软件四层交换也就应运而生, 这样的解决方案实现的原理一致, 不过性能稍差。但是满足一定量的压力还是游刃有余的, 有人说软件实现方式其实更灵活, 处理能力完全看你配置的熟悉能力。
软件四层交换我们可以使用 Linux 上常用的 LVS 来解决, LVS 就是 Linux Virtual Server, 他提供了基于心跳线 heartbeat 的实时灾难应对解决方案, 提高系统的鲁棒性, 同时可供了灵活的虚拟 VIP 配置和管理功能, 可以同时满足多种应用需求, 这对于分布式的系统来说必不可少。
一个典型的使用负载均衡的策略就是, 在软件或者硬件四层交换的基础上搭建 squid 集群, 这种思路在很多大型网站包括搜索引擎上被采用, 这样的架构低成本、高性能还有很强的扩张性, 随时往架构里面增减节点都非常容易。这样的架构我准备空了专门详细整理一下和大家探讨。
CDN 的全称是内容分发网络。其目的是通过在现有的 Internet 中增加一层新的网络架构, 将网站的内容发布到最接近用户的网络 “边缘”, 使用户可以就近取得所需的内容, 提高用户访问网站的响应速度。
CDN 有别于镜像, 因为它比镜像更智能, 或者可以做这样一个比喻: CDN = 更智能的镜像 + 缓存 + 流量导流。因而, CDN 可以明显提高 Internet 网络中信息流动的效率。从技术上全面解决由于网络带宽小、用户访问量大、网点分布不均等问题, 提高用户访问网站的响应速度。
CDN 的实现分为三类: 镜像、高速缓存、专线。
镜像站点 (Mirror Site), 是最常见的, 它让内容直接发布, 适用于静态和准动态的数据同步。但是购买和维护新服务器的费用较高, 还必须在各个地区设置镜像服务器, 配备专业技术人员进行管理与维护。对于大型网站来说, 更新所用的带宽成本也大大提高了。
高速缓存, 成本较低, 适用于静态内容。Internet 的统计表明, 超过 80% 的用户经常访问的是 20% 的网站的内容, 在这个规律下, 缓存服务器可以处理大部分客户的静态请求, 而原始的服务器只需处理约 20% 左右的非缓存请求和动态请求, 于是大大加快了客户请求的响应时间, 并降低了原始服务器的负载。
CDN 服务一般会在全国范围内的关键节点上放置缓存服务器。
专线, 让用户直接访问数据源, 可以实现数据的动态同步。
举个例子来说, 当某用户访问网站时, 网站会利用全球负载均衡技术, 将用户的访问指向到距离用户最近的正常工作的缓存服务器上, 直接响应用户的请求。
当用户访问已经使用了 CDN 服务的网站时, 其解析过程与传统解析方式的最大区别就在于网站的授权域名服务器不是以传统的轮询方式来响应本地 DNS 的解析请求, 而是充分考虑用户发起请求的地点和当时网络的情况, 来决定把用户的请求定向到离用户最近同时负载相对较轻的节点缓存服务器上。
通过用户定位算法和服务器健康检测算法综合后的数据, 可以将用户的请求就近定向到分布在网络 “边缘” 的缓存服务器上, 保证用户的访问能得到更及时可靠的响应。
由于大量的用户访问都由分布在网络边缘的 CDN 节点缓存服务器直接响应了, 这就不仅提高了用户的访问质量, 同时有效地降低了源服务器的负载压力。
采用 GCDN 加速方式
采用了 GCDN 加速方式以后, 系统会在浏览用户和您的服务器之间增加一台 GCDN 服务器。浏览用户访问您的服务器时, 一般静态数据, 如图片、多媒体资料等数据将直接从 GCDN 服务器读取, 使得从主服务器上读取静态数据的交换量大大减少。
为 VIP 型虚拟主机而特加的 VPN 高速压缩通道, 使用高速压缩的电信 <> 网通、电信 <> 国际 (HK)、网通 <==> 国际 (HK) 等跨网专线通道, 智能多线, 自动获取最快路径, 极速的动态实时并发响应速度, 实现了网站的动态脚本实时同步, 对被墙站有一个更加明显的加速效果。
每个网络运营商 (电信、网通、铁通、教育网) 均有您服务器的 GCDN 服务器, 无论浏览用户是来自何处, GCDN 都能让您的服务器展现最快的速度! 另外, 我们将对您的数据进行实时备份, 让您的数据更安全!
一个初建的网站往往用户群都是很小的, 最简单的网站架构就能解决实际的用户需求, 当然为了保证网站的稳定性和安全性, 我们会把网站的应用部署到至少两台机器上, 后台的存储使用数据库, 如果经济实力允许, 数据库使用单台服务器部署
一个数据库主要负责写操作我们称之为主库, 一个数据库专门负责读操作我们称之为副库, 副库的数据都是从主库导入的, 数据库的读写分离可以有效的保证关键数据的安全性, 但是有个缺点就是当用户浏览数据时候, 读的数据都会有点延时, 这种延时比起全站不可用那肯定是可以接受的。
缓存主要是适用于读操作, 并且缓存的读操作的效率要远远高于从数据库以及硬盘读取数据的效率。
业务再接着的增长下去, 数据量也会随之越来越大了, 这样发展下去总有一天主库也会产生瓶颈了, 那么接下来我们又该如何解决主库的瓶颈了? 方法很简单就是我们要拆分主库的数据了, 那么我该以什么维度拆分数据了? 一个数据库里有很多张表, 不同的表都针对不同的业务, 网站的不同业务所带来的数据量也不是不同的, 这个时候系统的短板就是那些数据量最大的表, 所以我们要把那些会让数据库产生瓶颈的表拆出来, 例如电商系统里商品表和交易表往往数据量非常大, 那么我们可以把这两种表建立在单独的两个数据库里, 这样就拆分了数据库的压力, 这种做法叫做数据垂直拆分。
一个数据库由很多表的构成, 每个表对应着不同的业务, ** 垂直切分是指按照业务将表进行分类, 分布到不同的数据库上面 **, 这样也就将数据或者说压力分担到不同的库上面:
优点:
缺点:
表数据的处理已经超出了单台服务器的能力, 这个时候我们就得对这个单库单表的数据进行更进一步的拆分, 也就是将一张表分布到两台不同的数据库里, 这个做法就是叫做数据的水平拆分了。可以根据项目拆分, 再结合按年的拆分等。
相对于垂直拆分的区别是: 垂直拆分是把不同的表拆到不同的数据库中, 而水平拆分是把同一个表拆到不同的数据库中。
相对于垂直拆分, 水平拆分不是将表的数据做分类, 而是按照某个字段的某种规则来分散到多个库之中, 每个表中包含一部分数据。简单来说, 我们可以将数据的水平切分理解为是按照数据行的切分, 就是将表中 的某些行切分到一个数据库, 而另外的某些行又切分到其他的数据库中, 主要有分表, 分库两种模式
优点:
缺点:
刚开始的时候应用和静态资源是保存在一起的, 当并发量达到一定程度的时候就需要将静态资源保存到专门的服务器中, 静态资源主要包括图片、视频、js、css 和一些资源文件等, 这些文件因为没有状态所以分离比较简单, 直接存放到响应的服务器就可以了, 一般会使用专门的域名去访问。
通过不同的域名可以让浏览器直接访问资源服务器而不需要再访问应用服务器了。架构图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NpI4JYIU-1670570688183)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/app-static-separation.png)]
页面缓存是将应用生成的页面缓存起来, 这样就不需要每次都生成页面了, 从而可以节省大量的 CPU 资源, 如果将缓存的页面放到内存中速度就更快了。如果使用 Nginx 服务器就可以使用它自带的缓存功能, 当然也可以使用专门的 Squid 服务器。页面缓存的默认失效机制一班都是按缓存时间处理的, 当然也可以在修改数据之后手动让相应的缓存失效。
页面缓存主要是使用在数据很少发生变化的页面, 但是很多页面是大部分数据都很少发生变化, 而其中很少一部分数据变化频率却非常高, 比如说一个显示文章的页面, 正常来说完全可以静态化, 但是如果文章后面有 “顶” 和 “踩” 的功能而且显示的有响应的数量, 这个数据的变化频率就比较高了, 这就会影响静态化。这个问题可以用先生成静态页面然后使用 Ajax 来读取并修改响应的数据, 这样就可以一举两得来, 既可以使用页面缓存也可以实时显示一些变化频率高的数据来。
其实大家都知道, 效率最高、消耗最小的就是纯静态化的 html 页面, 所以我们尽可能使我们的网站上的页面采用静态页面来实现, 这个最简单的方法其实也是最有效的方法。但是对于大量内容并且频繁更新的网站, 我们无法全部手动去挨个实现, 于是出现了我们常见的信息发布系统 CMS, 像我们常访问的各个门户站点的新闻频道, 甚至他们的其他频道, 都是通过信息发布系统来管理和实现的, 信息发布系统可以实现最简单的信息录入自动生成静态页面, 还能具备频道管理、权限管理、自动抓取等功能, 对于一个大型网站来说, 拥有一套高效、可管理的 CMS 是必不可少的。
除了门户和信息发布类型的网站, 对于交互性要求很高的社区类型网站来说, 尽可能的静态化也是提高性能的必要手段, 将社区内的帖子、文章进行实时的静态化, 有更新的时候再重新静态化也是大量使用的策略, 像 Mop 的大杂烩就是使用了这样的策略, 网易社区等也是如此。
同时, html 静态化也是某些缓存策略使用的手段, 对于系统中频繁使用数据库查询但是内容更新很小的应用, 可以考虑使用 html 静态化来实现, 比如论坛中论坛的公用设置信息, 这些信息目前的主流论坛都可以进行后台管理并且存储再数据库中, 这些信息其实大量被前台程序调用, 但是更新频率很小, 可以考虑将这部分内容进行后台更新的时候进行静态化, 这样避免了大量的数据库访问请求。
集群是每台服务器都具有相同的功能, 处理请求时调用那台服务器都可以, 主要起分流作用。
分布式是将不同的业务放到不同的服务器中, 处理一个请求可能需要用到多台服务器, 这样就可以提高一个请求的处理速度, 而且集群和分布式也可以同时使用。
集群有两个方式: 一种是在静态资源集群。另一种是应用程序集群。静态资源集群比较简单。应用程序集群在处理过程中最核心的问题就是 Session 同步问题。
Session 同步有两种处理方式: 一种是在 Session 发生变化后自动同步到其他服务器, 另一种就是用个程序统一管理 Session。所有集群的服务器都使用同一个 Session, Tomcat 默认使用就是第一种方式, 通过简单的配置就可以实现, 第二种方式可以使用专门的服务器安装 Mencached 等高效的缓存程序统一来管理 session, 然后再应用程序中通过重写 Request 并覆盖 getSession 方法来获取制定服务器中的 Session。
对于集群来说还有一个核心的问题就是负载均衡, 也就是接收到一个请求后具体分配到那个服务器去处理的问题, 这个问题可以通过软件处理也可以使用专门的硬件 (如: F5) 解决。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0LOgNQNH-1670570688183)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/cluster-distribution.png)]
反向代理指的是客户端直接访问的服务器并不真正提供服务, 它从别的服务器获取资源然后将结果返回给用户。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l3mFNMHH-1670570688183)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/reverse-proxy.png)]
代理服务器的作用是代我门获取想要的资源然后将结果返回给我们, 所要获取的资源是我门主动告诉代理服务器的, 比如, 我门想访问 Facebook, 但是直接访问不了, 这时就可以让代理服务器访问, 然后将结果返回给我们。
反向代理服务器是我门正常访问一台服务器的时候, 服务器自己去调用了别的服务器资源并将结果返回给我们, 我门自己并不知道。
代理服务器是我们主动使用的, 是为我们服务的, 他不需要有自己的域名; 反向代理服务器是服务器自己试用的, 我门并不知道, 它有自己的域名, 我门访问它和访问正常的网址没有任何区别。
反向代理服务器主要有三个作用:
CDN 其实是一种特殊的集群页面缓存服务器, 他和普通集群的多台页面缓存服务器相比, 主要是它存放的位置和分配请求的方式有点特殊。CDN 服务器是分布在全国各地的, 当接收到用户请求后会将请求分配到最合适的 CDN 服务器节点获取数据。比如联通的用户分配到联通的节点, 上海的用户分配到上海的节点。
CDN 的每个节点其实就是一个页面缓存服务器, 如果没有请求资源的缓存就会从主服务器获取, 否则直接返回缓存的页面。
CDN 分配请求 (负载均衡) 的方式是用专门的 CDN 域名解析服务器在解析域名的时候就分配好的。一般的做法是在 ISP 哪里试用 CNAME 将域名解析到一个特定的域名, 然后再将解析到的那个域名用专门的 CDN 服务器解析道相应的 CDN 节点。如图。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EjDKogTr-1670570688184)(https://hjs-1251193177.cos.ap-shanghai.myqcloud.com/web/CDN.png)]
第二步访问 CDN 的 DNS 服务器是应为 CNAME 记录的目标域名使用 NS 记录指向了 CDN 的 DNS 服务器。CDN 的每个节点可能也是集群了多台服务器。
前面说的所有都是架构都是建立在最前面介绍的基础结构之上的。很多地方都需要通过网络传输数据, 如果可以加快网络传输的速度, 那将会让整个系统得到改善。
大型网站都有复杂的应用, 这些应用必须使用数据库, 那么在面对大量访问的时候, 数据库的瓶颈很快就能显现出来, 这时一台数据库将很快无法满足应用, 于是我们需要使用数据库集群或者库表散列。
在数据库集群方面, 很多数据库都有自己的解决方案, Oracle、Sybase 等都有很好的方案, 常用的 MySQL 提供的 Master/Slave 也是类似的方案, 您使用了什么样的 DB, 就参考相应的解决方案来实施即可。
上面提到的数据库集群由于在架构、成本、扩张性方面都会受到所采用 DB 类型的限制, 于是我们需要从应用程序的角度来考虑改善系统架构, 库表散列是常用并且最有效的解决方案。我们在应用程序中安装业务和应用或者功能模块将数据库进行分离, 不同的模块对应不同的数据库或者表, 再按照一定的策略对某个页面或者功能进行更小的数据库散列, 比如用户表, 按照用户 ID 进行表散列, 这样就能够低成本的提升系统的性能并且有很好的扩展性。sohu 的论坛就是采用了这样的架构, 将论坛的用户、设置、帖子等信息进行数据库分离, 然后对帖子、用户按照板块和 ID 进行散列数据库和表, 最终可以在配置文件中进行简单的配置便能让系统随时增加一台低成本的数据库进来补充系统性能。
网站架构的整个演变过程主要是围绕大数据和高并发这两个问题展开的, 解决方案主要分为使用缓存和多资源两种类型。多资源主要指多存储(包括多内存)、多 CPU 和多网络, 对于多资源来说又可以分为单个资源处理一个完整的请求和多个资源合作处理一个请求两种类型, 如多存储和多 CPU 中的集群和分布式, 多网络中的 CDN 和静态资源分离。理解了整个思路之后就抓住了架构演变的本质, 而且自己可能还可以设计出更好的架构。
首先, 我认为解决问题之前首先要有清晰的思路, 如果只是用来别人的解决方案那也只能是拿来主义, 没有真正理解, 没有做到举一反三。
海量数据和高并发经常被连在一块说事儿, 虽然他们完全是两回事儿。海量数据纯指的是数据库的海量数据, 而并发指的却包括数据库和服务器的高访问量。
那么问题来了, 既然是数据库的数据量大, 那怎么办呢? 要想解决问题, 首先要知道问题是什么! ! ! 那么海量数据会给我带来什么样的问题呢?
海量数据带来的问题无非就是增删改查的问题, 除了之外还能有啥问题呢? 总不能是带来安全问题吧(打脸一, 还真有可能是安全问题)
要解决数据库访问缓慢的问题还有几种方法, 既然访问数据库慢的话, 在逻辑允许的情况下可以不访问数据库呢?
其实这个问题必须结合上面的海量数据来讨论, 什么情况下会出现高并发呢? 一定是平时访问量就比较大的情况, 那么平时访问量比较大相应的数据存储也就越来越多, 这都是相辅相成的, 当然也有个例, 比如刚需, 比如 12306, 这里的高并发相比于它的数据来说已经不算海量了。那么平时访问量大如何解决呢? 因为这里牵扯到服务器和数据库的问题, 所以要从这两方面来进行优化
在通向第二种解决方法之前, 还有没有除了数据库服务器之外能做的一些优化手段呢? 当然有
好多事情都是相辅相成的, 相比来说使用缓存更多是用来解决高并发问题的, 因为海量数据导致了访问的缓慢, 容易造成高并发问题的严重性, 又因为数据库一般是 web 访问的瓶颈, 所以我们在业务逻辑允许的情况下尽量先避免操作数据库, 于是, 就有了缓存。将必要的数据存放在内存中, 而不必每次都去数据库中读取造成不必要的性能浪费和加快访问速度 — 这就是缓存带来的好处。那使用缓存以及选用管理缓存软件时应该注意些什么东西呢?
需要注意的地方实在太多, 应该作为单独的一章拿出来讲
为什么要分离呢? 说一个我实际环境中遇到的问题吧! 有一个表只有 10 几个字段, 表有 130 万条数据, 但大小已经到了 5G 的数据, 这本身是不太合理的, 这么少的数据占用了太多的数据, 说明其中有些字段存储了大量的字符串(比如说文章内容等), 每次检索这个表时大部分是用不到这些大字段内容的, 但却需要耗时比较长, 产生很多的慢日志。这时我们可以考虑将表进行垂直切分, 将活跃数据分离开来, 这样能大大加快访问速度
在操作系统中, 是指一个时间段中有几个程序都处于已启动运行到运行完毕之间, 且这几个程序都是在同一个处理机上运行, 但任意一个时刻上只有一个程序在处理机上运行。
我们说的高并发是什么?
上面的定义明显不是我们通常所言的并发, 在互联网时代, 所讲的并发、高并发, 通常是指并发访问。也就是在某个时间点, 有多少个访问同时到来通常如果一个系统的日 PV 在千万以上, 有可能是一个高并发的系统, 但是有的公司完全不走技术路线, 全靠机器堆, 这不在我们的讨论范围。
高并发的问题, 我们具体该关心什么?
峰值一般是平均值的倍数, 根据实际情况来定
QPS 不等于并发连接数
QPS 是每秒 HTTP 请求数量, 并发连接数是系统同时处理的请求数量
(总 PV 数 * 80%)/(6 小时秒数 * 20%)= 峰值每秒请求数(QPS)
80% 的访问量集中在 20% 的时间! ! !
随着 QPS 的增长, 每个阶段需要根据实际情况来进行优化, 优化的方案也与硬件条件、网络带宽息息相关。
可以称之为小型网站, 一般的服务器就可以应付
假设关系型数据库的每次请求在 0.01 秒完成
假设单页面只有一个 SQL 查询, 那么 100QPS 意味这 1 秒钟完成 100 次请求, 但是此时我们并不能保证数据库查询能完成 100 次
方案: 数据库缓存层、数据库的负载均衡
假设我们使用百兆带宽, 意味着网站出口的实际带宽是 8M 左右
假设每个页面只有 10k, 在这个并发条件下, 百兆带宽已经吃完
方案: CDN 加速、负载均衡
假设使用 Memcache 缓存数据库查询数据, 每个页面对 Memcache 的请求远大于直接对 DB 的请求
Memcache 的悲观并发数在 2W 左右, 但有可能在之前内网带宽已经吃光, 表现出不稳定
方案: 静态 HTML 缓存
这个级别下, 文件系统访问锁都成为灾难
方案: 做业务分离, 分布式存储
什么是数据库缓存?
MySQL 等一些常见的关系型数据库的数据都存储在磁盘中, 在高并发场景下, 业务应用对 MySQL 产生的增、删、改、查的操作造成巨大的 I/O 开销和查询压力, 这无疑对数据库和服务器都是一种巨大的压力, 为了解决此类问题, 缓存数据的概念应运而生
为什么是要使用缓存?
缓存数据是为了让客户端很少甚至不访问数据库服务器进行数据的查询, 高并发下, 能最大程度的降低对数据库服务器的访问压力极大地解决数据库服务器的压力
提高应用数据的响应速度
用户请求 -->数据查询 -->连接数据库服务器并查询数据 -->将数据缓存起来 (HTML、内存、JSON、序列化数据)–> 显示给客户端
用户再次请求或者新用户访问 -->数据查询 -->直接从缓存中获取数据 -->显示给客户端
什么是 CDN?
CDN 的全称是 Content Delivery Network, 即内容分发网络, 尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节, 使内容传输的更快、更稳定
在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络
CDN 系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上
使用 CDN 的优势?
本地 Cache 加速, 提高了企业站点 (尤其含有大量图片和静态页面站点) 的访问速度
跨运营商的网络加速, 保证不同网络的用户都得到良好的访问质量
远程访问用户根据 DNS 负载均衡技术智能自动选择 Cache 服务器
自动生成服务器的远程 Mirror(镜像)cache 服务器, 远程用户访问时从 cache 服务器上读取数据, 减少远程访问的带宽, 分担网络流量, 减轻原站点 WEB 服务器负载等功能
广泛分布的 CDN 节点加上节点之间的智能冗余机制, 可以有效地预防黑客入侵
七层负载均衡的实现
基于 URL 等应用信息的负载均衡
Nginx 的 proxy 是它一个很强大的功能, 实现了 7 层负载均衡
Nginx 实现的优点
首先将请求都分给高权重的机器, 直到该机器的权值降到了比其他机器低, 才开始将请求分给下一个高权重的机器
当所有后端机器都 down 掉时, Nginx 会立即将所有机器的标志位清成初始状态, 以避免造成所有的机器都处于 timeout 的状态
Nginx 内置的另一个负载均衡的策略, 流程和轮询很类似, 只是七种的算法和具体的策略有些变化
IP Hash 算法是一种变相的轮询算法
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。