网关性能优化(二) - log4j2异步模型提升服务性能
zhezhongyun 2025-04-09 22:40 71 浏览
一. 背景:
webgate (网关服务)作为中台的组件之一,也是web组件的入口, 那么webgate稳定性如何、性能如何既是平台所关注的,也是使用者所关心的。近日对webgate服务进行了性能和稳定性压测。在压测过程中发现关于log4j影响服务性能,并得以解决。
二.结论先行:
webgate在使用log4j2异步模型后,服务的性能由原来的 700QPS 提升到 1000QPS。提升性能42%。 所以lo4j2的异步性能是绝佳的。
看图说话:
通过webbench并发180,持续访问 100秒 压测通过网关来路由访问demoapp/greeting 接口。
webgate在使用log4j2 同步模型时的性能
webgate在使用log4j2 异步模型后的性能
服务器性能监控:CPU 使用率70% 堆内存 使用800M(分别做了2小时,12小时的压测 图是2小时的效果图 ,期间gc正常、无fullgc发生)
看了结论,大家应该会有疑问,是如何发现服务慢,又是如何定位到log4j导致服务慢的问题。OK我们慢慢道来。
三.过程:
首先说压测准备:(这个很重要)
选择 网络、磁盘、CPU、内存 符合其服务压测的标准
- 网络,在内网进行压测所以网络瓶颈可忽略
- CPU 16核 内存 16G
2. 在网络 磁盘 CPU 内存满足服务的要求下,对于一个基于TCP协议传输的服务,系统内核参数的优化必不可少。
好在测试的同学提供的机器很给力(内核参数进行了优化,Tcp连接快速释放,端口数调大)
3. 服务部署图谱: 部署了一个网关实例(Tomcat), 部署了四个Demoapp服务实例 (本质是四个Nginx服务,避免因demoapp的性能影响网关压测)
4. tomcat[apache-tomcat-8.5.34] conf/server.xml优化:
5.Jvm设置: (这些参数设置有其关联性,需要根据具体的服务进行设置 感兴趣自行google)
-Xms4G -Xmx4G -Xmn800M -XX:PermSize=512M -XX:MaxPermSize=512M -XX:SurvivorRatio=8 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:ParallelCMSThreads=3 -XX:+CMSScavengeBeforeRemark -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=70 -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=3 -XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled6.启动Jvisualvm监控工具:
连接网关服务,监控系统资源(线程、cpu、内存等,当然这些都可以通过jdk提供的java命令去查看,它的好处在于可视化)
接下来开始压测
开始压测,QPS 只有600+ ,加到并发量 会更慢 [zuul 官方数据上万qps、性能损耗有点大,怀疑有问题。Webgate是基于zuul1实现]。
1.查看系统资源:
发现CPU正常(排除死循环,或计算型导致慢) IO 正常 内存正常(无内存、栈溢出) 查看网卡流量(网络正常)
2.查看fullGc:无fullGc产生
3.排除外部依赖原因:直接压测demoapp nginx提供的demoapp服务单机性能在7000qps
猜测:那可能是webgate中的服务阻塞、等待了。(这里可以通过jstack看堆栈信息,关注线程状态为BLOCKED、TIMED_WAITING的线程)
期间把webgate怀疑的损耗性能的方法进行了日志统一打印:发现并发大的时候各个环节耗时均有增长。数据结构如图:
4.利用可视化工具Jvisualvm 查看的 CPU快照信息,发现问题。
看第一行,org.apache.logging.log4j…….. 是不是很亲切 它花的CPU时间Number One。
疑问:日志打印耗时最长,这个不太正常
再看第二行
java.util.concurrent.LinkedBlockingQueue.poll() 队列轮询方法,它花的CPU时间 Number Two (后边会介绍)
咱们先看log4j继续跟进 通过反向跟踪 ,看是哪些方法调用了:
均是服务正常调用,然后调用打印了日志。
疑问:我们使用的是Log4j2,为什么log还会耗时最长呢?
看官方数据:
1. Log4j2 在log界号称性能第一,我们来看官方性能报告:
2.再看 sync vs aysnc logger
3.看完第二个图似乎有了答案。(来确认下我们服务使用的Log4j2的模式 – Log4j2-sync)
[有些事知道,跟去实践完全是两回事]
只知道log4j2号称性能第一,不知道它通过异步实现了高性能;只知道异步实现了高性能,殊不知它有两个模块asynclogger 和 asyncappender两个部分都实现了异步化,且可以灵活 的分模块异步和全异步。 更重要的是asynclogger异步方式 和asyncappender 异步方式不一样。Asynclogger使用的是LMAX Disruptor技术进行异步化,asyncappender 使用的是Java的ArrayBlockingQueue进行异步化。
扯远了,回正题。
4.查阅了log4j2的官方文档(一定要官方的)
https://logging.apache.org/log4j/2.x/manual/async.html
文中对异步log4j介绍的很详细 异步的几种方式的使用,性能,使用权衡(优缺点)这个需要仔细读
按照官方的介绍,在webgate上进行了实践。
Log4j2:loggers all async 全异步化后,进行压测,看图说话:
跃居第一位的是什么?
是不是很熟悉
java.util.concurrent.LinkedBlockingQueue.poll() log异步化前压测时的Number Two。
原来的org.apache.logging.log4j… 不见了。
说明一个问题:耗时最长的不是log4j2了,说明log4j2异步优化生效了。原来的Number Two 跃升为第一位 在期望中。
接下来我们看:
java.util.concurrent.LinkedBlockingQueue.poll()的方法调用链,看图说话:
Tomcat的线程池 请求轮询。[连接数是不是开的少了,线下证实了这个想法是正确的]
我们再看此时耗时第二位:
java.util.concurrent.locks.ReentrantLock.lock() – 重入锁
追踪其方法的调用链,看图说话:
这里分两部分看:
第一部分 com.lmax.disruptor.. 是什么? Log4j2 异步使用的框架[日志打印的是不是多?] 追踪方法调用链
初步结论:所有日志打印均是路由的核心类日志打印,应该是日志打印的多导致的,暂没有证实。[鉴权、限流、熔断、负载均衡、http转发]
第二部分 org.apache.http.pool.. 是什么? http连接池[webgate的核心http请求转发,情理之中?]
初步结论:跟综进去 发现是zuul路由,正常。
之前关于连接池的使用在这里踩过坑 ,那是 网关性能优化(一) – http连接池优化提升服务性能^_^
四.最后小结下
1、服务优化涉及方方面面,这里只是冰山一角,以此篇献给大家。重要的是思路不是结果。性能优化最重要的是发现问题,定位问题,关于解决方案可以有一大堆。
2、关于log4j2使用的几点建议:
1)log4j2的全异步模型性能在log界Number One。
2)使用了log4j2异步,日志中一定要有全链路唯一ID 主要是能把一次请求串起来。要不然异步后,根本没法根据日志去定位问题
3)没有最好的,只有最合适的。Log4j2 对服务来说亦是。可根据服务的业务选择最合适的。详细参考官方 log4j2使用权衡(优缺点)
相关推荐
- Python入门学习记录之一:变量_python怎么用变量
-
写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...
- python变量命名规则——来自小白的总结
-
python是一个动态编译类编程语言,所以程序在运行前不需要如C语言的先行编译动作,因此也只有在程序运行过程中才能发现程序的问题。基于此,python的变量就有一定的命名规范。python作为当前热门...
- Python入门学习教程:第 2 章 变量与数据类型
-
2.1什么是变量?在编程中,变量就像一个存放数据的容器,它可以存储各种信息,并且这些信息可以被读取和修改。想象一下,变量就如同我们生活中的盒子,你可以把东西放进去,也可以随时拿出来看看,甚至可以换成...
- 绘制学术论文中的“三线表”具体指导
-
在科研过程中,大家用到最多的可能就是“三线表”。“三线表”,一般主要由三条横线构成,当然在变量名栏里也可以拆分单元格,出现更多的线。更重要的是,“三线表”也是一种数据记录规范,以“三线表”形式记录的数...
- Python基础语法知识--变量和数据类型
-
学习Python中的变量和数据类型至关重要,因为它们构成了Python编程的基石。以下是帮助您了解Python中的变量和数据类型的分步指南:1.变量:变量在Python中用于存储数据值。它们充...
- 一文搞懂 Python 中的所有标点符号
-
反引号`无任何作用。传说Python3中它被移除是因为和单引号字符'太相似。波浪号~(按位取反符号)~被称为取反或补码运算符。它放在我们想要取反的对象前面。如果放在一个整数n...
- Python变量类型和运算符_python中变量的含义
-
别再被小名词坑哭了:Python新手常犯的那些隐蔽错误,我用同事的真实bug拆给你看我记得有一次和同事张姐一起追查一个看似随机崩溃的脚本,最后发现罪魁祸首竟然是她把变量命名成了list。说实话...
- 从零开始:深入剖析 Spring Boot3 中配置文件的加载顺序
-
在当今的互联网软件开发领域,SpringBoot无疑是最为热门和广泛应用的框架之一。它以其强大的功能、便捷的开发体验,极大地提升了开发效率,成为众多开发者构建Web应用程序的首选。而在Spr...
- Python中下划线 ‘_’ 的用法,你知道几种
-
Python中下划线()是一个有特殊含义和用途的符号,它可以用来表示以下几种情况:1在解释器中,下划线(_)表示上一个表达式的值,可以用来进行快速计算或测试。例如:>>>2+...
- 解锁Shell编程:变量_shell $变量
-
引言:开启Shell编程大门Shell作为用户与Linux内核之间的桥梁,为我们提供了强大的命令行交互方式。它不仅能执行简单的文件操作、进程管理,还能通过编写脚本实现复杂的自动化任务。无论是...
- 一文学会Python的变量命名规则!_python的变量命名有哪些要求
-
目录1.变量的命名原则3.内置函数尽量不要做变量4.删除变量和垃圾回收机制5.结语1.变量的命名原则①由英文字母、_(下划线)、或中文开头②变量名称只能由英文字母、数字、下画线或中文字所组成。③英文字...
- 更可靠的Rust-语法篇-区分语句/表达式,略览if/loop/while/for
-
src/main.rs://函数定义fnadd(a:i32,b:i32)->i32{a+b//末尾表达式}fnmain(){leta:i3...
- C++第五课:变量的命名规则_c++中变量的命名规则
-
变量的命名不是想怎么起就怎么起的,而是有一套固定的规则的。具体规则:1.名字要合法:变量名必须是由字母、数字或下划线组成。例如:a,a1,a_1。2.开头不能是数字。例如:可以a1,但不能起1a。3....
- Rust编程-核心篇-不安全编程_rust安全性
-
Unsafe的必要性Rust的所有权系统和类型系统为我们提供了强大的安全保障,但在某些情况下,我们需要突破这些限制来:与C代码交互实现底层系统编程优化性能关键代码实现某些编译器无法验证的安全操作Rus...
- 探秘 Python 内存管理:背后的神奇机制
-
在编程的世界里,内存管理就如同幕后的精密操控者,确保程序的高效运行。Python作为一种广泛使用的编程语言,其内存管理机制既巧妙又复杂,为开发者们提供了便利的同时,也展现了强大的底层控制能力。一、P...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)
- opacity 属性 (32)
- transition 属性 (33)
- 1-1. 变量声明 (31)
