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

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 的都是靠缓存顶住的吗?不上缓存的话,我现在服务器的性能指标到底是否正常?
36048 次点击
所在节点    程序员
183 条回复
CoderGeek
2018-09-16 22:42:32 +08:00
你这描述 并发 500 不应该不用缓存的 ... 我这高峰 API qps500+ 都是 3 台你这配置的服务器+slb
一台也顶得住但是你作为线上业务 不应该单台的 单点故障。
ittianyu
2018-09-16 22:43:28 +08:00
@zorui 那还真是抱歉了, 不是做 java 的我不该来这看了个标题瞄到一个 500 就开始评论。一堆人讽刺,告辞!!

最后说 认为 500 并发很低的人没实操过的,我不想说话(随便开十几台机器做压测会达不到 500 ?),500 那么高的并发,那是不是可以这么理解,99.99%的公司有两三台服务器就够用了。
我又没说单机 500 并发很低,单机能到 300 就不错了,我说的是整个项目 500 并发很低。
算了, 告辞!!
Actrace
2018-09-16 22:45:58 +08:00
阿里云的 vps 你还是要考虑一下超售的问题的。
vnex
2018-09-16 22:47:44 +08:00
@sagaxu #38
请教下

你知道四核 cpu 上,10000 个线程的时候,linux 内核做一次线程调度,上下文切换开销多大吗?微秒级别,比较古老的 cpu 上,也不过 10 微秒级别。

而 10000 个线程,通常需要配备 10G 内存。所以我们一般不会开 10000 个这么多,但是几百个上千个是很轻松的,1000 个线程的时候,上下文切换占用 cpu 的开销还不到 10%,完全可以承受。

这个的计算是:

1000 个线程: 10us * 1000 == 10ms == 1% cpu

10000 个线程: 10us * 10000 == 100ms == 10% CPU

这样吗?
ebony0319
2018-09-16 22:49:29 +08:00
上个星期遇到了一个项目,感觉跟楼主差不多,最后临时把阿里云带宽加到 100M 就好了,就是这么神奇。你可以试下是不是带宽的瓶颈。
neoblackcap
2018-09-16 23:01:30 +08:00
@ittianyu 之前就有人做过测试,inner join 跟子查询的性能基本没有区别,在单机 mysql 的情况下更是如此。
jokerlee
2018-09-16 23:01:38 +08:00
加内存缓存 提高 tomcat 线程数到 500
tomcat 一般都是 io 密集操作 线程要开大,不然线程都是 block cpu 跑不满
rogerchen
2018-09-16 23:02:37 +08:00
这么简单的问题,群魔乱舞。
profile 一下搞清楚为什么 mysql 毫秒级返回,前端请求加 json 解析需要 20ms+。
如果是网络延迟,多开十倍的线程。
如果是 json encode decode 卡计算,换 rapidjson 这种高效 json 库。
如果 mysql SSD 吞吐打满了,换 RDS。
jdgui
2018-09-16 23:02:49 +08:00
楼上说 500 并发很小的。。
多半是纸上程序员吧。真的实际坐过这些的应该不会觉得这个小。
ittianyu
2018-09-16 23:05:09 +08:00
@neoblackcap 我说的是集群的情况下,减少对数据库的压力,耗时的事放在 java 上做,容易扩展。
我答的时候没细看楼主的问题。
neoblackcap
2018-09-16 23:09:16 +08:00
@sagaxu 为什么要开那么多线程呢?按照 nginx 的思路,要解决大并发以及 IO 密集型业务也不需要那么多的线程吧。过多线程之后徒增上下文切换的成本。毕竟 IO 又不占 CPU 时间片,用 IO 复用机制加非堵塞 IO 解决不好么?
jokerlee
2018-09-16 23:14:10 +08:00
@neoblackcap 你要理解同步模型和异步模型的区别
rogerchen
2018-09-16 23:16:09 +08:00
@neoblackcap 无脑加线程本来就是解决 IO 的合理方法之一,特别是规模小的时候
tcsky
2018-09-16 23:16:48 +08:00
你试试调大线程池,

你说的线程数微多与核心数 一般针对的是 cpu 密集型的应用, 如用来一些异步框架
io 阻塞的情况下 需要调大线程数, 看你 API 相应时间在小几十 ms, 你调整线程数到 100 试试. cpu 跑满后 qps 会趋于稳定

500 并发其实不小了,普通应用一天 10 小时算, 都快 2000 万 pv 了, 另外只要不是连续的突发流量, 应用都撑得住的, 一般应用用的 tcpserver 自带队列,或者会抛弃超出负载的连接. 对应现象是响应时间变长, 或部分请求会失败
palmers
2018-09-16 23:19:41 +08:00
我也觉得应该把各个业务节点的耗时整理出来然后再讨论优化 这样才会有着力点 才会知道是网络需要优化还是业务需要优化 不要小看每一个点的优化 累计是很客观的
wjqxhy
2018-09-16 23:20:17 +08:00
个人觉得可能测试的模型是建连接,发请求,断连接这个完整的过程
建连接是比较耗时的,如果用 ab 测试工具的话,应该是能看到这部分的耗时,看是不是较高

如果是的话,看看服务器端是否支持了 keep-alive,如果支持,使用 ab 测试的话可以加-k 进行,或者用 wrk 工具
另外也可以调整内核参数优化性能
neoblackcap
2018-09-16 23:26:48 +08:00
@jokerlee 那两个模型理解啊,就是理解了我才觉得多线程没法很好地解决 IO 密集业务。linux 下线程上下文切换虽然成本低,但是多了也不少啊。
而且基本上所有 linux 的 IO 都能设置成非堵塞 IO,加上 IO 复用机制,这个不是将 CPU 更好地利用么?我是没法想象出一个不能用 IO 复用机制+非堵塞 I+线程池替代单纯多线程处理的场景。因此我才觉得这个场景比较奇怪,想问问当成为什么这样考量。
neoblackcap
2018-09-16 23:28:03 +08:00
@rogerchen 你这样一说我倒是可以理解,不过这个始终不是长久之计,毕竟线程多了,上下文切换成本高,得不偿失。
tcsky
2018-09-16 23:29:32 +08:00
@neoblackcap 两种模型各有优缺点,
异步模型开发成本会更高一点, 如果业务很轻, 需要支撑大量的 tcp 连接, 走异步模型比较合适.
其他情况下开线程就行,简单快速, 性能损耗也不明显.
jokerlee
2018-09-16 23:31:03 +08:00
@neoblackcap 一般应用根本用不着去抠线程上下文切换的性能消耗 而且业务层不是都能写成无阻塞模型的

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

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

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

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

© 2021 V2EX