遇到真正的高并发问题了,特来求助

2018-09-16 20:25:02 +08:00
 abcbuzhiming
以前做的项目,要么服务器够多,要么访问量比较分散,一天虽然人多,但是都是不同时段。所以没遭遇到访问瓶颈。这次真刀真枪的需要进行一次单服优化,然后就发现单服性能不可思议的低。大致情况如下:
应用服务器是 Tomcat,在阿里云上的 4 核心的 xero,8GB 内存,10MB 带宽,技术实现是 spring mvc,并不是特别复杂的计算业务,说难听点仅仅是 crud,而且输出的是纯粹的 json,没有其它的静态文件之类的东西。然后 MySQL 数据库在和应用服务器同一区域的另外一台阿里云服务器上,类似的配置,4 核心,8GB 内存,用的是高效 SSD。
这样的两台(一组)服务器,能抗住多少并发呢,500 不到。。。

然后开始初步分析,发现一个问题,就是哪怕是单纯的数据库读业务,从浏览器请求到服务器,服务器从数据库读取完毕到返回给前端,最快也要 20-30ms 左右,稍微复杂点的数据结构就上 100ms 了,如果按这个计算,每秒每个线程的处理能力理论最快也就 50 个并发请求,4 核心的机器上,JVM 的线程池一般也就核心的 1.5-2 倍,顶多不到 10 个线程,这样一算,单服理论并发处理能力确实只有 500 不到。。。

我不死心于是回头去找以前的类似服务器做测试,结果发现性能是类似的,只不过当年是靠着服务器够多顶住了罢了。

我知道肯定会有人说,上缓存啊,我当然知道上缓存,我的困惑是,难道只有上缓存一条路,那些并发上 w 的都是靠缓存顶住的吗?不上缓存的话,我现在服务器的性能指标到底是否正常?
36061 次点击
所在节点    程序员
183 条回复
kran
2018-09-17 00:31:06 +08:00
要不你算算请求 /响应体大小,看看带宽吞吐能力是不是到极限了
micean
2018-09-17 00:32:07 +08:00
@jokerlee

CompletableFutrue 其实和 stream 一样为了跑并发的……
异步性能最好的还是 callback hell 那样
java 的协程好像是 Quasar 的作者在做?但是 Quasar 真的慢……
cominghome
2018-09-17 00:49:06 +08:00
@ittianyu 真的是张嘴就来,几万并发到你这好像分分钟就灰飞烟灭了
des
2018-09-17 00:49:36 +08:00
同 50 楼,感觉是 MySQL 那台服务器 io 不太好。
先看看是不是响应时间随并发数增长的,以及看看有没有超长响应时间的请求
blless
2018-09-17 01:37:36 +08:00
500 不高吧…我还以为 java 下高并发场景已经很普遍了呢…我们以前用 python+gevent 方案感觉都不止 500,而且 python 最大问题是 GIL 只能用单核,后来转 go 以后压测一下基本限制都是数据库瓶颈
ETiV
2018-09-17 04:09:19 +08:00
我觉得应该用数据说话,比较科学。
就好比你去看大夫,都要验血验尿、拿到指标才行。不看指标的可能是中医 -。-

如果能单一请求就能复现出 20-30ms 或者更长的响应时长的话,你单机做一下 Profiling 比较好…

或者,简单点儿的做法,你打点计时。
在关键步骤分别记下处理逻辑中此行代码的当前时间,
然后分别追加在 json 文件内部或者放 http response header 里,一并输出。
veelog
2018-09-17 06:05:42 +08:00
以前也做过类似的分析,最后定位到瓶颈就在 mysql
veelog
2018-09-17 06:12:19 +08:00
压测的时候可以监控下 cpu 内存,磁盘 io 网络 这些看看哪里占用高
bobuick
2018-09-17 06:28:06 +08:00
猜是猜不到的。压测+ profile 就知道了
yhvictor
2018-09-17 07:05:51 +08:00
@sagaxu 没必要的,那么多线程也是阻塞
opengps
2018-09-17 07:58:16 +08:00
查看一下硬盘队列吧。我看了目前题主的说法,依然认为出在硬盘 io 上
doggg
2018-09-17 08:02:15 +08:00
500 不管是 QPS 还是 TPS 都是相当低的水平。
大一曾经试图压榨一台 1c1g 的腾讯云服务器,Tomcat 与 MySQL 同服务器的情况下 QPS 达到 3000,TPS 达到 2000。没有任何 Redis 缓存之类的。

服务器的性能短板很难定位,但可以自己试着排除一下:
带宽问题:CND,OSS 存静态文件,减少业务服务器带宽输出,Tomcat 也可以配置 Gzip。
池优化:Tomcat 的线程池必须配置,数据库的连接池请选择 Tomcat 或者 Tomcat JDBC pool 或者 HikariCP,这两种数据库连接池差距微乎其微,几乎可以忽略不计。包括一些参数优化。
MySQL 连接参数:cachePrepStmts,prepStmtCacheSize,prepStmtCacheSqlLimit,useServerPrepStmts。
磁盘 IO 问题:这个也得自己诊断一下。


如果业务很复杂,楼主所说的 500 并发,每一个请求需要好几个 SELECT 话,那就是 500*N,那 QPS 应该是没问题的,再花点精力也许可以稍微提高一下。
xuanbg
2018-09-17 08:23:13 +08:00
根据楼主描述,似乎瓶颈就在数据库上,那么解决方案很简单:

1、换高性能 RDS,大概性能可以提升 10 倍。
2、优化 SQL,这个能提升多少不确定。
D3EP
2018-09-17 08:38:11 +08:00
@neoblackcap 现在大多数语言和大多数框架都是同步模型啊。除了 nodejs 这种天热异步的,其它语言都是同步模型占绝对主流。
D3EP
2018-09-17 08:43:02 +08:00
@neoblackcap 你说的第二种方案就是绝大多数框架的方案。关键问题是对于 MySQL 这种耗时操作的处理方案,是应该挂起来等待,还是请求后塞入事件队列。
D3EP
2018-09-17 08:46:08 +08:00
@xiaoshenke 人家说的是业务层面的同步异步模型。绝大多数还是同步写法。dubbo 也就是 io 的时候是异步的,后面的操作还是塞入线程池,业务逻辑还是同步写的。
D3EP
2018-09-17 08:47:52 +08:00
@blless Java 也有纯异步的 vertx,但用的人不多
alwayshere
2018-09-17 08:48:40 +08:00
与其大量优化代码和 cache,真的不如省点时间加点钱堆硬件配置,过来人之谈
v2orz
2018-09-17 08:52:23 +08:00
应该是 tomcat 没配置好。调一下参数或者用 resin


不过“单纯的数据库读业务,从浏览器请求到服务器,服务器从数据库读取完毕到返回给前端,最快也要 20-30ms ”
肯定不正常
star7th
2018-09-17 09:06:49 +08:00
合理使用缓存能让单机服务器的性能提高数倍,尤其是 web 服务,基本瓶颈都在数据库查询上。把结果缓存到内存中,跟每次从磁盘读,差别很大的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/489883

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX