前言

这半个多月完成了这次活动的业务代码开发和测试,至于性能调优对我而言近乎玄学。总结记录,以备参考。如有错误,欢迎指正。不过其实大佬不用浪费时间看这篇低质量的流水账了。

实测过后,一个月前老板给我说的10万qps,我就当他年老无知。别说10万了,就我们这几台服务器,只要还是用传统Java Web(Servlet)这套,5000也达不到。在BIO下,为每个请求分配一个线程去处理,就算tomcat有线程池和请求等待队列,还是得堵在那儿。另外,和第三方(活动赞助商)的技术人员沟通过后,了解到他们发奖接口的qps也就千八百,而我们的某个接口会去后台调用他们的接口,意思是不论怎么优化,活动整体是有瓶颈的。虽然想逃离去学一波netty和spring 5.0, 但先得把老师的活儿给应付了,尽力而为(崩)吧。

调优前,jmeter压测某简单接口,该接口不调用第三方接口,是外网压测(有网络延时),qps=1200,该值作为调优起跑线。(提一句,jmeter简单好用,支持系统函数生成随机字符串做参数等,可以导出jmx脚本。并且阿里云的PTS压测服务支持导入jmx脚本。这几天的收获之一就是学会用这个压测工具。)


  1. 解决带宽问题

阿里云性能监控的控制台是我的主要信息渠道。阿里云的带宽是按公网出流量算的,我发现p1服务器(nginx所在)的带宽在压测期间跑满了,立马把配置从5M升级到100M。效果立竿见影,qps到了1800,显然之前的5M带宽太小了。

2. 横向扩展服务器时,发现并解决nginx处瓶颈

在我查看nginx错误日志之前,我从没想过nginx会比tomcat先有瓶颈。但是当我加了一台业务服务器而毫无性能提升,并且有大量处于NON_ESTABLISHED状态的tcp连接时,我想到了nginx这个入口会不会有问题。

1024 worker_connections are not enough

这条nginx日志说明了问题所在,要么是你的nginx配置文件里配得太小,要么是你的服务器的操作系统允许进程打开的句柄数太小(一个socket要用一个句柄)。

把worker_connections 从1024直接改成了10240。压测时nginx不再报错,系统增加一台业务服务器后,性能有明显提升(qps: 1800 -> 2300

3. 仍然有大量TIME_WAIT状态的tcp连接

如上图所示,每个波峰代表服务器经历了一次压测。监控图显示压测期间产生大量tcp连接,但是90%以上是TIME_WAIT态,真正ESTABLISHED的tcp很少。这个问题可以去看看相关的博客(TCP连接状态详解及TIME_WAIT过多的解决方法 - 沧海一滴 - 博客园),简单来说,就是四次挥手结束tcp链接时,TIME_WAIT状态会持续两个MSL时间,可以修改系统参数以重用TIME_WAIT态的socket、加快其回收等。监控图里框起来的最后一个波峰明显合理很多,就是修改了/etc/sysctl.conf的参数的结果。

然而,这个优化对性能(qps)毫无提升。想来也是,我们的web服务器已经能建立足够多的tcp连接,可以发足够多的请求,但是业务服务器来不及处理,qps自然上不去。所以根源还是在于tomcat的性能瓶颈。

那么如何提升tomcat的请求处理能力呢?一方面,堆业务服务器的路子前面已经走通。另一方面,单机提升就涉及到tomcat参数调优。(至于JVM调优,我暂时相信默认值比自己拍脑瓜想的值更好)

4. tomcat参数调优

这里折腾了半天,并且毫无作用。以后有机会一定要深入了解下tomcat的工作机制,为什么这东西就“油盐不进”呢?

我们的业务服务器启动参数是从数据库里读取的,我查看了下之前的配置:

不看不知道,一看不得了。JVM那两个参数小点就算了,毕竟我们的业务纯IO,对象对内存的占用少。但TOMCAT这个参数也设得太小了吧(50/10/20)!线程池里最多跑50个请求,等待队列里最多缓存20个请求,加起来70个,太小太小了。

顿时感觉自己找到了一条通往高并发的阳关大道,立马参考网上的博客设置为1000/100/1000,然后高兴地开始压测。结果qps不增反跌(qps: 2300 -> 1900),nginx也接连报错,提示连接超时(Connection reset by peer)。

网上搜索了一番,大致原因如下。

acceptCount一般设置得和线程池大小相同,这个值是有讲究的。如果设得较小,可以保证接受的请求快速响应,但是超出的请求可能就直接被拒绝;而如果设得较大,可能就会出现大量的请求超时的情况,因为我们系统的处理能力是一定的。这好比一家饭店,它的人手有限(系统处理能力),如果预先摆放的桌位太多,就会装太多顾客,这会导致每桌顾客的上菜时间严重延长。

最后把这三个tomcat参数设置为100/10/40,不再折腾。(还是直接加机器靠谱)

5. 数据库优化和Redis

直接阿里云上买了一台redis server服务,按量计费。本平台的项目代码是(controller -> service -> dao)三层,我在service层新写了对应的redisHandler可以把数据往redis server里存,就不走dao去mysql了。这个实现个人觉得不好,只是图方便。因为redis和mysql其实都是数据访问,应该都往dao层里写(只是mysql对应的是用Mybatis生成的mapper)。

然后利用平台之前集成的Quatz定时任务框架,写一个定时任务把redis的数据批量插入mysql。这个方案的初衷是考虑到活动的数据最后要导出给甲方,且用redis能支持更高并发,异步批量插入数据库也能避免mysql的并发瓶颈。

最后代码实现是完成了,但我不准备用redis了。原因有二,一是对redis不熟,数据最后是要给甲方的,怕担风险;二是之前也说过,并发量还在tomcat那儿卡着呢,mysql几千的qps应该绰绰有余。

6. 分离nginx和tomcat

查看p1服务器,发现压测期间cpu占用高达90%,显然p1同时作为tomcat业务服务器和nginx网关,有点压力太大。现在有了新增的业务服务器,干脆让p1只跑nginx和一些不重的业务,把负责主要业务(platform、frontend)的tomcat在p1上停了。

这个措施带来非常可观的性能提升。这说明,只要公司不是特别穷,网关服务和业务服务还是独立部署吧。

7. 动静分离

没啥好说的,静态资源全放阿里云OSS上做cdn加速,这是最简单易行的优化措施。当然,这个提升在接口压测中是体现不出来的,但确实很重要 -- 服务器出网带宽才100M,必须节约。


后话

容灾靠重启,就这样吧。希望老板明年良心发现,早点放实习。纸上得来终觉浅,绝知此事要躬行。

附最后成果图,qps=4500(1 * nginx + 3 * 业务server,皆为2核16G)

5000并发的qps是多少_高并发初体验记录-02相关推荐

  1. 5000并发的qps是多少_高并发架构设计

    点击蓝字,关注我们 01 概述 高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一,它通常是指,通过设计保证系统能够同时并行处理很多请求. 高并发一方面可以提高资 ...

  2. 高并发内存占用持续下降_高并发性能调试经验分享

    引文 4月份的时候看到一道面试题,据说是腾讯校招面试官提的:在多线程和高并发环境下,如果有一个平均运行一百万次才出现一次的bug,你如何调试这个bug?知乎原贴地址如下:腾讯实习生面试,这两道题目该怎 ...

  3. mysql 高并发 响应时间_高并发,你真的了解吗?

    摘要:本文介绍高并发系统的度量指标,讲述高并发系统的设计思路,再梳理高并发的关键技术,最后结合作者的经验做一些延伸探讨. 当前,数字化在给企业带来业务创新,推动企业高速发展的同时,也给企业的IT软件系 ...

  4. 高并发编程_高并发编程系列:7大并发容器详解(附面试题和企业编程指南)...

    不知道从什么时候起,在Java编程中,经常听到Java集合类,同步容器.并发容器,高并发编程成为当下程序员需要去了解掌握的技术之一,那么他们有哪些具体分类,以及各自之间的区别和优劣呢? 只有把这些梳理 ...

  5. java设计高并发内存池_高并发服务器-连接池的设计

    高并发服务器-连接池的设计 高并发服务器需要有一些池的设计,如内存池,连接池,数据库连接池. 池(pool)的设计主要考虑到一些资源的频繁申请和释放,尤其是在高并发的服务器中,几万甚至几十万并发每秒, ...

  6. java设计模式并发_[高并发Java 七] 并发设计模式

    [高并发Java 七] 并发设计模式 [高并发Java 七] 并发设计模式 为什么80%的码农都做不了架构师?>>> 在软件工程中,设计模式(design pattern)是对软件设 ...

  7. 高并发专题--5:关于redis高并发你晓得多少?

    关于redis高并发你晓得多少? 1.redis高并发跟整个系统的高并发之间的关系 2.redis不能支撑高并发的瓶颈在哪里? 3.如果redis要支撑超过10万+的并发,那应该怎么做? 4.redi ...

  8. java 高并发第三阶段实战_Java 高并发第三阶段实战---Java并发包深入解析与使用详解...

    第三阶段的课程主要围绕着Java并发包的使用,展开详细的介绍,主要内容有1.原子包源码剖析,2.并发包工具类详细介绍,3.线程服务以及Future和callable等详细介绍,4.高并发容器和阻塞容器 ...

  9. 高并发第一弹:准备阶段 了解高并发

    高并发第一弹:准备阶段 了解高并发 首先需要知道什么并发, 什么是高并发. 并发: 关于并发的学习,可以从JDK提供的并发包为核心开始,许多其他的类和封装都是对其进行扩展或者补充,我们来看一下Java ...

最新文章

  1. 智慧城市产业图谱(2020年)
  2. unity fixedupdate_unity相关
  3. 研究生的研究人员发展课程
  4. redhat6.3下配置使用cenos yum源
  5. ALGO-84 矩阵乘法
  6. 慷宝机器人_慷宝智能管家机器人亮相2018郑州国际地产行业联合采购大会
  7. css淡入动画,使用CSS淡入大动画效果
  8. cadence 软件导出ad 文件出错
  9. tensorflow:Not creating XLA devices, tf_xla_enable_xla_devices not set
  10. 【JY】从一根悬臂梁说起
  11. Qt保存QTextEdit内存至.txt文件中
  12. selenium源码通读·4 |webdriver/common分析
  13. ubuntu18.04安装Qt5.9.9后没有QtCreator启动图标
  14. VUE项目SEO问题的解决
  15. 阿里巴巴面试java研发工程师实录
  16. [Done]FindBugs: boxing/unboxing to parse a primitive
  17. hibernate_2
  18. Python3,1行代码,制作GUI图形界面,果然被种草了。
  19. protect 继承_c++三种继承方式public,protect,private
  20. 洛谷P1617 爱与愁的一千个伤心的理由

热门文章

  1. numpy 100题
  2. 全网唯一一个可以复现成功的光流计算项目
  3. opencv-python图像处理之磨皮相机
  4. python 习题集锦
  5. 300. Longest Increasing Subsequence
  6. JS 时间戳转换成日期
  7. 使用回调方式写POI导入excel工具类
  8. ASP.NET froms 身份验证之Roles
  9. WordCount案例
  10. NLineInputFormat案例