Open bingoohuang opened 3 years ago
125 MB/s
全双工
(vs 半双工
),也就是上下行是并行工作的,也就是说上行下行同时能达到理论值 125 MB/s
2.5G
网卡具有高达 2500Mbps
的传输速率,是千兆网卡速度的 2.5 倍带宽
是千兆,无论下载还是上传 极限就是千兆,就像一条公路,就那么宽,无论你车是往那个方向开千兆网络
,要路由器、交换机、网卡、带宽等所有硬件/指标都要达到千兆规格,实际上速度能达到 100MB/s
就不错了TPS
:Transactions Per Second(每秒传输的事务处理个数),即服务器每秒处理的事务数TPS
是软件测试结果的测量单位。一般的,评价系统性能均以TPS
来衡量。系统整体处理能力取决于处理能力最低模块的TPS值QPS
:Queries Per Second意思是“每秒查询率”,是一台服务器每秒能够处理的查询次数RT
是一个系统最重要的指标之一,它的数值大小直接反应了系统的快慢。并发数
是指系统同时能处理的请求数量
,这个也是反应了系统的负载能力TPS = 并发数/平均响应时间
并发数 = QPS*平均响应时间
我们通过一个实例来把上面几个概念串起来理解。按二八定律来看,如果每天 80%
的访问集中在 20%
的时间里,这 20%
时间就叫做峰值时间。
( 总 PV 数 * 80% ) / ( 每天秒数 * 20% ) = 峰值时间TPS
峰值时间 TPS / 单台机器 QPS = 需要的机器数量
例如:
NGINX轻松管理10万长连接 --- 基于2GB内存的CentOS 6.5 x86-64
C10K 就是 Client 10000 问题,即「在同时连接到服务器的客户端数量超过 10000 个的环境中,即便硬件性能足够, 依然无法正常提供服务」,简而言之,就是单机 1 万个并发连接问题。这个概念最早由 Dan Kegel 1999 年提出。C10K 就是单机同时处理 1 万个请求(并发 1 万连接)的问题。
现在我们早已经突破了 C10K 这个瓶颈,思路就是通过单个进程或线程服务于多个客户端请求,通过异步编程和事件触发机制替换轮训,IO 采用非阻塞的方式,减少不必要的性能损耗,等等。 底层的相关技术包括 epoll、kqueue、libevent 等,应用层面的解决方案包括 OpenResty、Golang、Node.js 等,比如 OpenResty 的介绍中是这么说的:
OpenResty 通过汇聚各种设计精良的 Nginx 模块,从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 C10K 乃至 C1000K 以上单机并发连接的高性能 Web 应用系统。
实际上,在大多数场景中,我们并不需要单机并发 1000 万的请求。通过调整系统架构,把这些请求分发到多台服务器中来处理,通常是更简单和更容易扩展的方案。
问题是,一些同学就记住了 C10K,是并发处理 1 万请求,把括弧中的"并发 1 万连接"给忽略了,把 Client 的 C 当成了 Concurrence 的 C,然后就慢慢与并发 1 万 TPS 画上了等号。然后就经常下意识的问,你们的系统能支撑住 10 万 TPS 么?搞得 10 万 TPS 是标配,没有 10 万 TPS 那系统就是做得太烂了似的感觉。
空接口的意义,在于提供了实际业务压测的在特定环境约束下的一个比较现实的基准。
很多网络应用程序,都提供一个 /status
的网络服务,返回例如 {"status":200,"message":"成功"}
的 JSON 响应报文,表明应用还在正常运行中。很多情况下,这个 /status
的接口实现,就是一个空接口,什么也不干,就是直接返回一个接口对象,例如, fastrest中的实现如下:
package fastrest
type Status struct{ DummyService }
func (p *Status) Process(*Context) (interface{}, error) {
return &Rsp{Status: 200, Message: "成功"}, nil
}
我们使用 Berf 跑一下它的性能测试:
root@bx-PC:~/bingoohuang# ./berf :14142/status -c 26 -v -d30s
Berf benchmarking http://127.0.0.1:14142/status for 30s using 26 goroutine(s), 96 GoMaxProcs.
@Real-time charts is on http://127.0.0.1:28888
Summary:
Elapsed 30s
Count/RPS 4489715 149652.214
200 4489715 149652.214
ReadWrite 208.316 196.345 Mbps
Connections 26
Statistics Min Mean StdDev Max
Latency 31µs 163µs 136µs 5.598ms
RPS 136749.48 149628.08 2858.46 153222.51
Latency Percentile:
P50 P75 P90 P95 P99 P99.9 P99.99
138µs 187µs 254µs 319µs 606µs 1.854ms 2.314ms
Latency Histogram:
158µs 4337178 96.60% ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
243µs 122233 2.72% ■
439µs 25696 0.57%
1.051ms 3179 0.07%
1.728ms 974 0.02%
2.087ms 373 0.01%
2.274ms 75 0.00%
2.689ms 7 0.00%
可以看到,这个空接口的 TPS 能达到 15万,平均延时 163µs, P99 延时 606µs。
这时候小明同学就问,我这个啥业务也没有,测量这个空接口的意义何在呢?其实,它的意义非常重要:
空接口的意义,在于提供了实际业务压测的在特定环境约束下的一个比较现实的基准。(另一方面,空接口提供了框架底座的基本性能指标,可以帮助框架洗清”冤屈嫌疑“。)
一个实际的问题是,明明同学在自己的环境(比如他自己的个人电脑中)验证同样的空接口,可能达不到这个 15 万(应该说99%的情况下都达不到),例如,测得的结果是 8 万,那也不要气馁,无论 8 万还是 15 万,只是特定环境下的一个特定值而已,基准 的意义,仍然会发挥作用。
在测量之前,我们先在脑中做一下预估:
以上只需要预估量级就行。
实验步骤:
./httplive
/berf :5003/status -ci 30:5s:30 -v -c 300
,即每 5 秒增加 30 并发连接,达到 300 后,再每 5 秒减少 30 并发./berf :5003/status -v -c 100 -d15s
持续使用 100 并发连接,压测15秒./berf :5003/status -v -c 120 -d15s
持续使用 120 并发连接,压测15秒./berf :5003/status -v -c 150 -d15s
持续使用 150 并发连接,压测15秒直接使用 Berf 测试工具,我们可以看出:
因此,并发连接数不是越多越好,在一个合理值下,取得较大 TPS,以及较小延时,才是一个合理的压测并发连接数。
TPS 哪些事儿
TPS 具体是指什么?
TPS 的英文全称是 Transactions Per Second,即每秒事务数。例如,每秒钟签名数量,每秒钟加密数量,每秒钟生成订单的数量等。有时候,我们见到类似的 HPS (每秒点击数),QPS(每秒查询数),RPS(每秒请求数)等,我们可以理解成是 TPS 的事务映射成点击、查询、请求的更加具体的解释上,为了方便起见,以下我们都统称 TPS。
为了让大家有一个直观的概念,我这里从一篇 2019 年的博客Database Comparison - SQL vs. NoSQL (MySQL vs PostgreSQL vs Redis vs MongoDB)上,扒拉了一个图,如下:
从这张图中,我们可以看到,查询性能上,Redis 能达到 500 万左右 TPS ( 5000/0.001), MongoDB 达到 5000 万左右 TPS ,简直令人咂舌,而可怜的 MySQL/PostgreSQL,只有 500 TPS左右(5000/10)。那么问题来了,如果我们自己在本机压测一下,会达到类似效果吗?思考几秒钟先。对了,你就需要去仔细检查人家的测试环境,包括硬件环境、网络环境、软件环境、测试数据等等,可以说,我们几乎不可能测得类似的结果。