pattern.compile pattern函数

背景

经常做后端服务开发的同学,或多或少都遇到过CPU负载极高的问题。尤其是周末或者半夜的时候,突然群里有人反映在线机器负载特别高,不熟悉定位流程和思路的同学可能会急着上服务器,定位流程就掉头了。

pattern.compile pattern函数

对此,很多同学整理了相关的流程或方法论,类似于把一头大象放进冰箱需要多少个步骤。传统的方案一般有四个步骤:

1.top order by with p:1040//首先根据进程负载找到axload (PID)。2.Top-HP进程PID:1073//找到相关的加载线程PID。3.Prinf \”0x% x \\ n \”线程PID:0x 431//将线程PID转换为十六进制。准备稍后搜索jstack日志。4.jstack进程PID | vim +/十六进制线程PID-//比如:jstack 1040 | vim+/0x 431-但是对于在线问题定位来说,分秒必争,以上四个步骤还是太繁琐耗时。有没有可能封装成一个工具,在有问题的时候一键定位有问题的代码行,两秒钟就找到?

当然可以!工具链的成熟度不仅体现了一个开发者的运维能力,也体现了开发者的效率意识。淘宝的Oldratlee把上面的流程封装成一个工具:show-busy-Ja-threads . sh(https://github . com/oldratlee/useful-scripts),在线上就可以轻松定位这类问题。我举两个例子看看实际效果。

快速安装和使用:

来源& lt(curl-fsSL https://raw . githubusercontent . com/oldratlee/useful-scripts/master/test-cases/self-installer . sh)

1.ja正则表达式回溯导致CPU 100%。

导入Ja . util . ArrayList;导入Ja . util . list;导入Ja . util . regex . matcher;导入Ja . util . regex . pattern;public class regex load { public static void main(String[]args){ String[]pattern match = { \”([\\ \\ w \\ \\ s]+)+([\\ \\ w \\ \\ s]+)\”,\”([\\ \\ w \\ \\ s]+)+([+\\ \\-/*])+([\\ \\ w \\ \\ s]+)+([+\\ \\-/*])+([+\\ \\ w \\ \\ s]+)+([\\ \\ w \\ \\ s]+)\” };列表& lt字符串& gtpatternList = new ArrayList & lt字符串& gt();patternList.add(\”平均体积单位产品A +体积单位产品A \”);patternList.add(\”平均体积单位/体积单位乘积A \”);patternList.add(\”平均零售商库存/数量单位计划/商店数量\”);patternList.add(\”平均手量单位计划商店计数\”);patternList.add(\”1 -平均商户交易量单位\”);patternList.add(\”零售商发货总数\”);for(String s:pattern list){ for(int I = 0;我& lt模式匹配.长度;i++){ Pattern Pattern = Pattern . compile(Pattern match[I]);匹配器matcher = pattern . matcher(s);system . out . println(s);if(matcher . matches()){ system . out . println(\” Passed \”);}else System.out.println(\”失败;);}}}}编译运行以上代码后,我们可以观察到服务器有一个100% CPU的ja进程:

怎么用?

Show-busy-Ja-threads.sh#从所有Ja进程中找出消耗CPU最多的线程(默认为5个)并打印出它们的线程栈。show-busy-Ja-threads . sh-c & lt;要显示的线程堆栈数>;show-busy-Ja-threads . sh-c & lt;要显示的线程堆栈数>;-p & lt;指定的Ja process >;# -F选项:执行jstack命令时添加-F选项(force jstack),一般不需要使用show-busy-Ja-threads . sh-p;-fs how-busy-Ja-threads . sh-s & lt;指定jstack命令的完整路径> #对于sudo模式下的操作,JA_HOME环境变量无法传递给root,#而且root用户往往不会配置JA_HOME,配置起来也不方便。#显式指定jstack命令的路径更方便。show-busy-Ja-threads . sh-a;show-busy-Ja-threads . sh-t & lt;重复次数>-I & lt;重复间隔秒数> #默认执行一次;默认执行间隔为3秒# # # # # # # # # # # # # # # # # # # # #注意:# # # # # # # # # # # # # #为了切换到Ja进程的用户,需要添加sudo来执行,这样可以解决问题:sudo show-busy-ja-threads.sh示例:

work @ dev _ ZZ _ Master 10 . 48 . 186 . 32 23:45:50 ~/demo & gt;bash show-Busy-ja-threads . sh[1]Busy(96.2%)thread(8577/0x 2181)用户(work)下Ja进程(8576)的堆栈:\” main \” prio = 10 tid = 0x 00007 f0c 64006800 NID = 0x 2181 RUNNABLE[0x 0007 f0c 6 a 64 a 000]Ja . lang . thread . state:RUNNABLE at Ja . util . regex . pattern $ group head . match(pattern . Ja:4…at ja . util . regex . matcher . match(matcher . Ja:1127)at Ja . util . regex . matcher . matcher(matcher . Ja:502)at regex load . main(regex load . Ja:27)[2]用户(工作)下Ja进程(8576)的繁忙(1.5%)线程(8591/0x218f)堆栈:“C2编译器线程1”守护进程prio = 10 tid = 0x00007f0c64095800可见直接一键定位异常代码行很方便。

2、线程死锁,程序挂起

导入Ja . util . *;公共类SimpleDeadLock扩展线程{公共静态对象L1 = new Object();公共静态对象L2 = new Object();private int索引;公共静态void main(String[]a){ Thread t1 = new Thread 1();线程T2 = new thread 2();t1 . start();T2 . start();}私有静态类Thread1扩展Thread { public void run(){ synchronized(L1){ system . out . println(\” Thread 1:Holding lock 1 … \”);试试{ thread . sleep(10);} catch(interrupted exception e){ } system . out . println(\”线程1:正在等待锁2 … \”);synchronized(L2){ system . out . println(\” Thread 2:Holding lock 1 & amp;2…\”);} } } }私有静态类Thread2扩展Thread { public void run(){ synchronized(L2){ system . out . println(\” Thread 2:Holding lock 2 … \”);试试{ thread . sleep(10);} catch(interrupted exception e){ } system . out . println(\”线程2:等待锁1 … \”);synchronized(L1){ system . out . println(\” Thread 2:Holding lock 2 & amp;1…\”);}}}执行后的效果:

如何使用工具定位:

一键定位:可以清晰的看到线程互相锁定等待资源,导致死锁,直接定位代码行和具体原因。

通过上面两个例子,我觉得同学们应该对这个工具和工具能解决什么问题有了更深的理解,遇到100% CPU的问题就可以不慌张了。但更多的还是要靠大家去实践,毕竟实践出真知~

3.免费实用的脚本工具礼包

除了文中提到的show-busy-ja-threads.sh,oldratlee还集成了很多开发和运维中涉及到的常用脚本工具,我简单列举一下我觉得特别有用的:

(1)显示-复制-Ja-类

偶尔会遇到在本地开发测试很正常的类异常,上线后却莫名其妙。苦心经营,原因竟然是罐子冲突!这个工具可以在Ja Lib(Ja库,也就是Jar文件)或者class directory(类目录)中找到重复的类。

Ja开发中一个比较麻烦的问题就是Jar冲突(即多个版本的Jar),或者重复的类。会有NoSuchMethod之类的问题,但那时候不一定是问题。找到具有重复类的jar可以防患于未然。

#在当前目录的所有jar中查找重复的类show-duplicate-ja-classes#在多个指定目录的所有jar中查找重复的类show-duplicate-Ja-class path/to/lib _ dir 1/path/to/lib _ dir 2 #在多个指定的类目录中查找重复的类。类目录使用-c选项指定show-duplicate-Ja-classes-cpath/to/Class _ dir 1-c/path/to/Class _ dir 2 #。找到指定类目录中重复类的Jar show-duplicate-Ja-class path/to/lib _ dir 1/path/to/lib _ dir 2-cpath/to/class _ dir 1-cpath/to/class _ dir 2以及指定目录下的所有Jar。例如:

#在war模块目录中执行以生成war文件$ mvn install…#解压war文件,war文件包含Jar文件$ unzip target/*。战争-目标/战争…#检查重复的类$ show-duplicate-Ja-classes-CT arget/war/we b-INF/classes target/war/we b-INF/lib…(2)在罐子里找东西。

在当前目录的所有jar文件中查找一个类或资源文件。

用法:注意Pattern是grep的扩展正则表达式。

在罐子里找\’ log4j\\。属性“在jars中查找”log4j\\可扩展标记语言

-d /path/to/find/directoryfind-in-jars log4j\\\\.xmlfind-in-jars \’log4j\\.properties|log4j\\.xml\’

示例:

$ ./find-in-jars服务. class

./WEB-INF/libs/spring-2.5.6.SEC03.jar!org/springframework/stereotype/Service.class./rpc-benchmark-0.0.1-SNAPSHOT.jar!com/taobao/rpc/benchmark/service/HelloService.class

(3)housemd pid [ja_home]

很久以前,我们使用BTrace来解决问题。在感叹BTrace威力的同时,我们也几次挂线系统。2012年,淘宝的巨石写了HouseMD,将几个常用的Btrace脚本整合在一起,形成一个独立的风格应用。它的核心代码是Scala,HouseMD是基于字节码技术的诊断工具。因此,除了Ja,HouseMD支持最终以字节码形式运行在JVM上的任何语言的诊断。如Clojure(感谢@Killme2008提供使用介绍)、Scala、Groovy、JRuby、Jython、Kotlin等。

使用housemd对ja程序进行运行时跟踪,支持的操作有:

查看加载类跟踪方法查看环境变量查看对象属性值详细信息请参考: https://github.com/CSUG/HouseMD/wiki/UserGuideCN

(4)jvm pid

执行jvm调试工具,包括ja栈、堆、线程、gc等视图。支持的功能有:

= = = = = =线程关联= = = = = 1:查看占用cpu最高的线程2:打印所有线程3:打印线程数4:按线程状态统计线程数= = = = = = GC关联= = = = = 5:垃圾收集统计(包括原因)可以指定间隔时间和执行次数。您可以指定间隔时间和执行次数。默认是1秒,10次。8:打印perm区*的内存情况会导致程序暂停响应。9:查看directbuffer的情况= = = = = = =堆对象关联= = = = = 10:将堆转储到文件*会导致程序暂停响应。默认情况下会保存到pwd`/dump.bin *会让程序暂停响应*12:打印jvm堆统计*会让程序暂停响应*13:打印jvm堆中的前20个对象。*会让程序暂停响应*参数:1:按实例数排序,2:按内存占用排序,默认值为114:触发全gc后打印jvm堆中前20个对象。*会让程序暂停响应*参数:1:按实例数排序,2:按内存占用排序,默认值为115:输出perm中类加载器生成的所有对象。可以指定间隔时间和执行次数= = = = = =其他= = = = = 16:打印终结器队列。17:显示类加载器统计信息。18:显示jit编译统计信息。19:死锁检测。20:等待x秒。默认为1q: exit。进入jvm工具后,可以输入序列号来执行相应的命令。

您可以使用分号“;”一次执行多个命令分离,如:1;3;4;5;六

每个命令都可以接受参数,用冒号“:”分隔,同一命令的参数用逗号分隔,例如:

输入命令队列:1;5:1000,100;10:/data1/output.bin

(5)灰人[@IP:PORT]

PS:目前Greys只支持Linux/Unix/Mac上的Ja6+,Windows暂时不支持。

Greys是JVM进程执行过程中的异常诊断工具,可以在不中断程序执行的情况下轻松完成问题调查。和HouseMD一样,《Grey-Anatomy》被命名为《实习医生格蕾》(Grey\’s Anatomy),这是一部同名美剧,目的是为了向前辈致敬。代码是参考BTrace和HouseMD的思想编写的。

用grey对ja程序进行运行时跟踪(参数不传递,先需要greys -C pid,再需要greys)。支持的操作有:

查看加载类,方法信息查看JVM当前基础信息方法执行监控(调用量,失败率,响应时间等)方法执行数据观测、记录与回放(参数,返回结果,异常信息等)方法调用追踪渲染详细信息请参考: https://github.com/oldmanpushcart/greys-anatomy/wiki

(6)sjksjk -命令sjk -帮助

使用sjk对Ja进行诊断、故障排除和优化。

ttop:监控指定jvm进程的各个线程的cpu使用情况jps: 强化版hh: jmap -histo强化版gc: 实时报告垃圾回收信息

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。

发表回复

登录后才能评论