项目介绍

路由网关项目watchman ,接收前端http请求转发到后端业务系统,功能安全验证,限流,转发。

使用技术:spring boot+ nreflix zuul,最开始日志使用slf4j+log4j部署方式打成jar包,内部使用的是tomcat容器,设置线程数600。

工作原理

先介绍下zuul的工作原理,看图zuul中定义了四种filter分别是

1.pre 在请求到达origin之前执行,在这一步可以做认证,选择转发地址,记录日志

2.Routing 建立http请求,可以使用httpClient或者netflix的ribbon

3.Post 返回请求,可以在这一步做统计收集,设置response的http heder,把请求返回个客户端

4.Error当在以上三个步骤执行出错时执行

问题

性能压测时,tps只有400多,开启并发10个线程和100线程结果一致

分析

watchman中无任何业务逻辑,没有数据库连接操作,没有频繁io操作 只有安全验校验类和限流类,直觉上感觉肯定有问题,代码结构如下

使用jprofiler分析,首先查看CPU views下的call Tree,方法调用链路栈,

按调用时间算的百分比,最高的是WrappingRunable下面有10个百分比较高的http,这10个http就是本次压测的接口。每个接口的占用比都差不多,展开第一个9%的

同样是route为啥preroute耗时这么久,肯定有问题

一个请求进入会依次被三种filter处理,第一种prefilter,第二种route,第三组postroute,初步定为preroute有问题,结合代码看,本次开发pre包中只有两个prefilter一个是AppUrsTokenPreFilter,对app请求解签验签,另一个prefilter做流量控制,仔细检查了代码发现没有问题,spring源码包中有5个prefilter类,查看代码没有问题,没有找到问题换个方向

cpuload猜想

从cpu load看,一直很高,联想到cpu与计算有关,然后AppUrsTokenPreFilter filter中有动态md5的计算,可能与这个类有关系,验证把该类从容器中排除,继续压测,最终结果和之前一致,cpu并没有降下去,猜想错误

堆GC分析

一切正常,继续换方向

线程dump分析

通过观察thread监控,发现50个线程并发时只有5个线程处于runnable状态,其余BLOCKED和waiting,加到线程数到200, runnable还是只有个位数运行,194个BLOCKED,如图。到这可以猜测代码有大量锁竞争

使用jstack dump线程日志,全局搜索blocked 第12行 BLOCKED

其他先不管看到loadclass查看源码,同步锁。。。,问题已找到

接下来查看在哪里调用的,FormBodyWrapperFilter 137行,看代码,spring内置的一个prefilter 作用是针对form表单请求把参数进行转换,使用的是MappingJackson2HttpMessageConverter,其中在构造函数中是这样的

又调用了Jackson2ObjectMapperBuilder,继续看代码

继续看代码Jackson2ObjectMapperBuilder这个类

继续看代码,还是Jackson2ObjectMapperBuilder这个类里的

快到源头了,继续 ,这次到classutils类了

forname方法太长 我只截了关键部分

这个就是源头,loadclass使用的是同步锁

解决问题方法禁用spring自带的prefilter类zuulzuul.FormBodyWrapperFilter.pre.disable=true,改完之后重新部署压测,瞬间上去了

还没有结束

之前把自己写的两个prefilter代码注释,加上去之后重新压测,tps瞬间只有一半(红线是kill)

继续线程dump查看。是的你没看错 log4j已经成为了瓶颈

看log4j源码

从这边可以看到在转发loggingEvent到各个appender的时候,是同步的,即使你用asycAppender也没有效果,解决方法使用logback,再压测一把,平均4k+,可以接受

一次性能优化,tps从400+到4k+的更多相关文章

  1. MYSQL一次性能优化实战经历[转]

    每次经历数据库性能调优,都是对性能优化的再次认识.对自己知识不足的有力验证,只有不断总结.学习才能少走弯路. 一.性能问题描述 应用端反应系统查询缓慢,长时间出不来结果.SQLServer数据库服务器 ...

  2. 记一次性能优化,限制tcp_timewait数量,快速回收和重用

    前言 这篇文章的主题是记录一次Python程序的性能优化,在优化的过程中遇到的问题,以及如何去解决的.为大家提供一个优化的思路,首先要声明的一点是,我的方式不是唯一的,大家在性能优化之路上遇到的问题都 ...

  3. 也记一次性能优化:LINQ to SQL中Contains方法的优化

    距离上一篇博文更新已经两个月过去了.在此,先表一表这两个月干了些啥: 世界那么大,我也想去看看.四月份的时候,我入职了上海的一家电商公司,职位是.NET高级开发工程师.工作一个月,最大的感受是比以前小 ...

  4. 一次性能优化将filter转换

    有一条SQL性能有问题,在运行计划中发现filter.遇到它要小心了,类似于nestloop.我曾经的blog对它有研究探索运行计划中filter的原理.用exists极易引起filter. 优化前: ...

  5. 记一次性能优化的心酸历程【Flask+Gunicorn+pytorch+多进程+线程池,一顿操作猛如虎】

    您好,我是码农飞哥,感谢您阅读本文,欢迎一键三连哦. 本文只是记录我优化的心酸历程.无他,唯记录尔.....小伙伴们可围观,可打call,可以私信与我交流. 干货满满,建议收藏,需要用到时常看看. 小 ...

  6. [转]linux 系统监控、诊断工具之 IO wait

    1.问题: 最近在做日志的实时同步,上线之前是做过单份线上日志压力测试的,消息队列和客户端.本机都没问题,但是没想到上了第二份日志之后,问题来了: 集群中的某台机器 top 看到负载巨高,集群中的机器 ...

  7. 一次项目实践中DBCP数据库连接池性能优化

    关于数据库连接池DBCP的关注源于刚刚结束的一轮测试,测试内容是衡量某Webserver服务创建用户接口的性能.这是一款典型的tomcat应用,使用的测试工具是Grinder.DBCP作为tomcat ...

  8. 消息服务dubbo接口性能压测性能优化案例

    最近项目中的消息服务做了运营商的改动,导致这个服务做了重新开发 压测脚本如下: 开启200线程压测: tps只有200-300之间,平均耗时在700ms左右 开启500线程压测 500并发压测,发现平 ...

  9. Lazy<T>在Entity Framework中的性能优化实践(附源码)

    在使用EF的过程中,导航属性的lazy load机制,能够减少对数据库的不必要的访问.只有当你使用到导航属性的时候,才会访问数据库.但是这个只是对于单个实体而言,而不适用于显示列表数据的情况. 这篇文 ...

随机推荐

  1. Lua 迭代器

    第一种:lua迭代器的实现依赖于闭包(closure)特性 1.1 第一个简单的写法 --迭代器写法 function self_iter( t ) local i = 0 return functi ...

  2. UITabBarItem's appearance

    1.我们知道,用tabBarController创建出来默认的tabBar似这个样子滴... -----------------我是图片分割线----------------------------- ...

  3. Linux标准目录

    本文参考鸟哥的linux私房菜 /bin 获得最小的系统可操作性所需要的命令 /boot 内核和加载内核所需要的文件 /dev 终端.磁盘.调制解调器等的设备项 /etc 关键的启动文件和配置文件 / ...

  4. XCode: duplicate symbol

    XCode: duplicate symbol 2013-05-27 17:28:21|  分类: iOS|字号 订阅     遇到引用库重复定义的问题,需要解决.   项目需要,同时引用ZBar和Q ...

  5. 深入解析FileInputStream和FileOutputStream

    http://swiftlet.net/archives/1363 FileInputStream和FileOutputStream类属于字节类,可以操作任意类型的文件.在数据流的处理过程中,有两种情 ...

  6. 关于html5的几个新标签在IE9之前不支持的解决办法

    IE8及之前的浏览器不支持用CSS的方法来使用这些尚未支持的结构元素,为了在Internet Explorer浏览器中也能正常使用这些结构元素,需要使用JavaScript脚本,如下:<scri ...

  7. GUI矩形、椭圆、线、框架

    所有的Swing组件必须由时间调度线程(event dispatch thread)进行配置,线程将鼠标点击和键盘敲击控制转移到用户接口组件.下面的代码片段是事件调度线程中的执行代码: EventQu ...

  8. 修改6S Fortran77 代码,建立查找表

      逐像元大气校正,常预先计算查找表(LUT,LookUp Tabel),6S大气辐射传输模式也可以用来计算LUT.但6S源程序输出信息多,且浮点数输出精度低,不利于提取关键信息生成LUT,本文描述了 ...

  9. android5.0----SVG

    SVG ----scalable vector Graphics 可缩放矢量图形 android L 即android 5.0的新特性. 1,SVG是干什么的? 可缩放矢量图形是基于可扩展标记语言(标 ...

  10. 笔记整理--Linux平台MYSQL的C语言

    Linux平台MYSQL的C语言API全列表 - 第三只眼的专栏 - 博客频道 - CSDN.NET - Google Chrome (2013/8/18 22:28:58)   Linux平台MYS ...