正则匹配问题导致 CPU 飙高总结

一、事件背景

1.1 需求说明

我们的各个业务系统上报了用户的登录日志(包括成功和失败的),这些登录日志我们要存起来,对用户的行为进行分析,以便发现一些异常的用户;也为用户画像提供更多的基础数据支持。

但是我们的登录是可以使用邮箱和用户名两种情况登录的,上报的日志是从多个业务场景上报,高峰量还是非常大的,并且我们并没有用户数据库的直连权限,这里有需要将使用用户名登录的和使用邮箱登录的分开存储。

所以在存储之前我们得弄清楚用户是使用哪种场景登录的。

这里的邮箱登录还是用户名登录,我们就是使用的正则来做的一个简单判断。

1.2 事件发生时间及发现过程

发生时间还好是上班时间,钉钉告警出来,正好在工位就立马发现能解决了;避开了悲催的半夜被告警铃声吵醒美梦的悲剧。

下面是使用top命令查看当时CPU使用情况的截图,也是后背一凉。

二、问题排查过程

2.1 初步定位

实际上面1.2的图就可以看到是哪一个进程导致的CPU飙高,这就非常方便我们定位了,直接找到对应的程序,然后使用jstack命令查看一下堆栈情况。

2.2 详细排查

打印出来的堆栈情况,可以清晰的看到大量的java.util.regex.Pattern对象,这个时候如果想不到我们可以dump一下具体分析,万幸的是这个项目从头到尾都是我负责的,里面只有唯一的一个地方使用到了正则,所以我立马定位到了具体的代码(疯狂的牛马)。

下面是我真正正则校验的代码,实际看起来还是非常清晰明了的。

java 复制代码
/** 正则表达式:验证邮箱 */
public static final String REGEX_EMAIL = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";

/**
 * 校验邮箱
 *
 * @param email 邮箱
 * @return 校验通过返回true,否则返回false
 */
public static boolean isEmail(String email) {
	return Pattern.matches(REGEX_EMAIL, email);
}

单独从上面实际是不怎么看的出我们的问题的。

三、问题原因分析

3.1 问题分析

找到了问题产生点,问题分析说起来就非常简单了;哪怕我想不到,我也可以直接问问AI。

哎,看了AI的回答,相信你也猜到了问题产生的核心原因。

看到前面的正则,我们就知道,我这里是符合贪婪匹配与长文本贪婪匹配与长文本 这两点的,至于并发问题,因为我的实际处理程序是通过MQ削峰的,所以这里并不满足。

当然,如果你并不能直接看出来,那也简单,你把上面的正则丢给AI分析分析。

咋样,强大的AI立马告诉了你结果。并且他还可以给出一些解决办法。

四、问题解决措施

4.1 按照业务合理解决

前面已经说过AI会给你提供一些解决办法,但是AI并不是万能的,每个业务场景都有自己的特殊,我们可以根据自己的业务来综合考虑。

先看看AI的优化建议。

AI的优化建议非常标准,但是我考虑这里业务场景实际有很大限制,所以没必要按照它的来。

业务场景补充描述:

  • 邮箱最长长度是80

  • 用户名最长长度是256(你别说,还真有人定格设置)

4.2 解决办法

前面补充了业务场景,相信很多人已经猜到了解决办法。

没有,就是限制一下触发正则的前提。

java 复制代码
if (username.length() <= 80 && username.contains("@")) {
    // 进行正则校验    
}

4.3 影响范围

虽然排查到解决,看着都非常简单,但是实际操作起来还是很繁琐的,一顿骚操作,再经过测试到发布到正式环境,也耗时1小时多。

五、总结

任何代码都不是万能的,这个正则校验工具类,经过了不知道多长时间的使用,在本项目就是踩坑了,要是不从堆栈去仔细排查,你怕是脑子想爆炸都找不到原因。

在开发过程中真的需要多多思考,结合业务场景仔细去设计代码,没有万能的代码,但是有万能的程序员,相信你看了这篇文章也会有不一样的收获。

相关推荐
在未来等你几秒前
互联网大厂Java求职面试:电商商品推荐系统中的AI技术应用
java·缓存·kafka·推荐系统·向量数据库·jvm调优·spring ai
@ chen19 分钟前
常见排序算法及其java实现
java·算法·排序算法
带刺的坐椅1 小时前
SpringBoot2 可以使用 SolonMCP 开发 MCP(江湖救急)
java·spring·ai·solon·mcp
shengjk11 小时前
序列化和反序列化:从理论到实践的全方位指南
java·大数据·开发语言·人工智能·后端·ai编程
jimsten1 小时前
苍穹外卖 - Day02 学习笔记
java·笔记·学习
工业互联网专业1 小时前
基于springboot+vue的医院门诊管理系统
java·vue.js·spring boot·毕业设计·源码·课程设计·医院门诊管理系统
wgc2k1 小时前
Java游戏服务器开发流水账(5)Spring 在游戏开发中的使用简介
java·服务器·游戏
API小爬虫1 小时前
如何用Jsoup库提取商品名称和价格?
java·爬虫
Black_Cat_yyds2 小时前
rabbitmq
java·rabbitmq·java-rabbitmq
摆烂且佛系2 小时前
FastByteArrayOutputStream和ByteArrayInputStream有什么区别
java·开发语言