宁武皇仁光九年锦文轩刻本《异闻录》载: 扶桑画师浅溪,居泰安,喜绘鲤。院前一方荷塘,锦鲤游曳,溪常与嬉戏。 其时正武德之乱,潘镇割据,战事频仍,魑魅魍魉,肆逆于道。兵戈逼泰安,街邻皆逃亡,独溪不舍锦鲤,未去。 是夜,院室倏火。有人入火护溪,言其本鲤中妖,欲取溪命,却生情愫,遂不忍为之。翌日天明,火势渐歇,人已不见。 溪始觉如梦,奔塘边,但见池水干涸,莲叶皆枯,塘中鲤亦不知所踪。 自始至终,未辨眉目,只记襟上层迭莲华,其色魅惑,似血着泪。 后有青岩居士闻之,叹曰:魑祟动情,必作灰飞。犹蛾之投火耳,非愚,乃命数也。 ————《锦鲤抄》

【linux下Arthas学习与使用】


Arthas服务监控以及内存分析

阿尔萨斯(Y)(巫妖王N)

 

关于服务器模块性能监控

目前接触最多的性能监测工具
  • glowroot

  • arthas

     

关于arthas
安装
-- 下载jar包
wget https://alibaba.github.io/arthas/arthas-boot.jar
-- 启动arthas
java -jar arthas-boot.jar
-- 选择jar服务进行监控
-- 停止监控
stop

 

使用

arthas命令主要分为三类:System Info(系统),Class/Method (类/方法), Method invocation (方法调用)

不过总结起来无需分类,按照实用程度记录即可:

  • 全局JVM运行时监控,CPU,线程,内存,堆栈信息等

  • 接口无反应或调用耗时过长排查

  • CPU飙高排查

  • 发版后没有理想的效果,怀疑发版所用是不是旧代码,,未pull成功等

  • 线上可以进行热部署,无需重新发版

 

JVM监控信息:dashboard,thread等
1、进程:输入dashboard,
仪表盘持续打印当前进程相关信息
如下图,可以看到nonheap 和 metaspace(非堆),metaspace是java8新出现的概念
(堆)Heap分为3个区:
Young即新生代(分为Eden区、From Survivor、To Survivor三个区域,默认比例是8:1:1),
OldGen即老生代。
Young保存刚实例化的对象。当该区被填满时,GC会将对象移到Old区。
Permanent区则负责保存反射对象。
## 注意:java8的时候去除PermGen,将其中的方法区移到non-heap中的Metaspac,Metaspace与PermGen之间最大的区别在于:Metaspace并不在虚拟机内存中,而是使用本地内存
(非堆)MetaSpace:全称是MetaSpace,即方法区。用于存放Class和Meta信息,Class在被Load的时候被放入该区域。

## 去除PermGen的好处
将字符串常量池从PermGen分离出来,与类的元数据分开,提升类的元数据的独立性
将类的元数据从PermGen剥离出来到Metaspace,可以提升对元数据的管理同时提升GC效率


2、[thread 线程id] 查看占用CPU最高的线程,总线程数,跟线程状态对应的数量
## 查看具体线程信息使用 ,或者查看CPU使用率前N(N=3)的线程: thread -n 3                    

 

 

方法级别监控信息: tt、watch 、trace、stack、monitor等
1、tt 
## 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测,比如监控某类下的特定方法(selectList):
[arthas@7426]$ tt -t com.wang.library.api.controller.v1.FileManageController selectList
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 235 ms, listenerId: 2
INDEX     TIMESTAMP                 COST(ms)     IS-RET     IS-EXP     OBJECT             CLASS                                   METHOD                                
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1000       2022-09-11 17:48:50       158.319126   true       false     0x44035c0e         FileManageController                   selectList                            
1001       2022-09-11 17:49:09       108.755058   true       false     0x44035c0e         FileManageController                   selectList        

2、watch
## watch className methodName '{params, returnObj,throwExp}' -n 5 -x 3
## watch 类所在路径 所检测方法名 '参数, 返回值, 异常信息(如果有的话)' 抓5次,参数层级(深度)设置为三级
## 例子:
[arthas@7426]$ watch com.wang.library.app.service.Impl.FileManageServiceImpl queryList '{params, returnObj,throwExp}' -n 5 -x 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 74 ms, listenerId: 3
method=com.wang.library.app.service.Impl.FileManageServiceImpl.queryList location=AtExit
ts=2022-09-12 10:44:45; [cost=304.375791ms] result=@ArrayList[
  @Object[][isEmpty=true;size=0],
  @Page[
      @FileInfo[
           FIELD_FILE_ID=@String[fileId],
           FIELD_FILE_NAME=@String[fileName],
           FIELD_FILE_TYPE=@String[fileType],
           FIELD_FILE_Size=@String[fileSize],
           FIELD_FILE_URL=@String[fileUrl],
           FIELD_ATTRIBUTE1=@String[attribute1],
           FIELD_ATTRIBUTE2=@String[attribute2],
           FIELD_ATTRIBUTE3=@String[attribute3],
           FIELD_ATTRIBUTE4=@String[attribute4],
           FIELD_ATTRIBUTE5=@String[attribute5],
           FIELD_USER_NAME=@String[userName],
           fileId=@Long[104],
           fileName=@String[视频类型测试.mp4],
           fileType=@String[.mp4],
           fileSize=@String[4359952],
           fileUrl=@String[/zoey/upload/视频类型测试.mp4],
           attribute1=@String[猫猫测试],
           attribute2=@String[2022-07-31 11:00:26],
           attribute3=null,
           attribute4=null,
           attribute5=null,
           userName=@String[ljc],
      ],
      @FileInfo[
           FIELD_FILE_ID=@String[fileId],
           FIELD_FILE_NAME=@String[fileName],
           FIELD_FILE_TYPE=@String[fileType],
           FIELD_FILE_Size=@String[fileSize],
           FIELD_FILE_URL=@String[fileUrl],
           FIELD_ATTRIBUTE1=@String[attribute1],
           FIELD_ATTRIBUTE2=@String[attribute2],
           FIELD_ATTRIBUTE3=@String[attribute3],
           FIELD_ATTRIBUTE4=@String[attribute4],
           FIELD_ATTRIBUTE5=@String[attribute5],
           FIELD_USER_NAME=@String[userName],
           fileId=@Long[106],
           fileName=@String[31d51448bfb8c7c42eda05f6a2940d131e96ddc2bd76a20afcb78d34c28ede33.jpg],
           fileType=@String[.jpg],
           fileSize=@String[187697],
           fileUrl=@String[/zoey/upload/31d51448bfb8c7c42eda05f6a2940d131e96ddc2bd76a20afcb78d34c28ede33.jpg],
           attribute1=@String[],
           attribute2=@String[2022-07-31 12:50:25],
           attribute3=null,
           attribute4=null,
           attribute5=null,
           userName=@String[ljc],
      ],
      @FileInfo[
           FIELD_FILE_ID=@String[fileId],
           FIELD_FILE_NAME=@String[fileName],
           FIELD_FILE_TYPE=@String[fileType],
           FIELD_FILE_Size=@String[fileSize],
           FIELD_FILE_URL=@String[fileUrl],
           FIELD_ATTRIBUTE1=@String[attribute1],
           FIELD_ATTRIBUTE2=@String[attribute2],
           FIELD_ATTRIBUTE3=@String[attribute3],
           FIELD_ATTRIBUTE4=@String[attribute4],
           FIELD_ATTRIBUTE5=@String[attribute5],
           FIELD_USER_NAME=@String[userName],
           fileId=@Long[107],
           fileName=@String[微信图片_20220802164244.jpg],
           fileType=@String[.jpg],
           fileSize=@String[121521],
           fileUrl=@String[/zoey/upload/微信图片_20220802164244.jpg],
           attribute1=@String[color pic test],
           attribute2=@String[2022-08-02 16:43:34],
           attribute3=null,
           attribute4=null,
           attribute5=null,
           userName=@String[gy],
      ],
      @FileInfo[
           FIELD_FILE_ID=@String[fileId],
           FIELD_FILE_NAME=@String[fileName],
           FIELD_FILE_TYPE=@String[fileType],
           FIELD_FILE_Size=@String[fileSize],
           FIELD_FILE_URL=@String[fileUrl],
           FIELD_ATTRIBUTE1=@String[attribute1],
           FIELD_ATTRIBUTE2=@String[attribute2],
           FIELD_ATTRIBUTE3=@String[attribute3],
           FIELD_ATTRIBUTE4=@String[attribute4],
           FIELD_ATTRIBUTE5=@String[attribute5],
           FIELD_USER_NAME=@String[userName],
           fileId=@Long[108],
           fileName=@String[微信图片_20220802164254.jpg],
           fileType=@String[.jpg],
           fileSize=@String[152146],
           fileUrl=@String[/zoey/upload/微信图片_20220802164254.jpg],
           attribute1=@String[color pic test],
           attribute2=@String[2022-08-02 16:43:34],
           attribute3=null,
           attribute4=null,
           attribute5=null,
           userName=@String[gy],
      ],
      @FileInfo[
           FIELD_FILE_ID=@String[fileId],
           FIELD_FILE_NAME=@String[fileName],
           FIELD_FILE_TYPE=@String[fileType],
           FIELD_FILE_Size=@String[fileSize],
           FIELD_FILE_URL=@String[fileUrl],
           FIELD_ATTRIBUTE1=@String[attribute1],
           FIELD_ATTRIBUTE2=@String[attribute2],
           FIELD_ATTRIBUTE3=@String[attribute3],
           FIELD_ATTRIBUTE4=@String[attribute4],
           FIELD_ATTRIBUTE5=@String[attribute5],
           FIELD_USER_NAME=@String[userName],
           fileId=@Long[109],
           fileName=@String[微信图片_20220802164300.jpg],
           fileType=@String[.jpg],
           fileSize=@String[241151],
           fileUrl=@String[/zoey/upload/微信图片_20220802164300.jpg],
           attribute1=@String[color pic test],
           attribute2=@String[2022-08-02 16:43:34],
           attribute3=null,
           attribute4=null,
           attribute5=null,
           userName=@String[gy],
      ],
      @FileInfo[
           FIELD_FILE_ID=@String[fileId],
           FIELD_FILE_NAME=@String[fileName],
           FIELD_FILE_TYPE=@String[fileType],
           FIELD_FILE_Size=@String[fileSize],
           FIELD_FILE_URL=@String[fileUrl],
           FIELD_ATTRIBUTE1=@String[attribute1],
           FIELD_ATTRIBUTE2=@String[attribute2],
           FIELD_ATTRIBUTE3=@String[attribute3],
           FIELD_ATTRIBUTE4=@String[attribute4],
           FIELD_ATTRIBUTE5=@String[attribute5],
           FIELD_USER_NAME=@String[userName],
           fileId=@Long[110],
           fileName=@String[震惊猫.jpg],
           fileType=@String[.jpg],
           fileSize=@String[16038],
           fileUrl=@String[/zoey/upload/震惊猫.jpg],
           attribute1=@String[震惊猫],
           attribute2=@String[2022-09-07 17:20:58],
           attribute3=null,
           attribute4=null,
           attribute5=null,
           userName=@String[ljc],
      ],
  ],
  null,
]

## 可以添加过滤信息,比如cost耗时,单位是毫秒
[arthas@7426]$ watch com.wang.library.app.service.Impl.FileManageServiceImpl queryList '{params, returnObj,throwExp}' '#cost>50' -n 5 -x 3


## 由于参数 -n 5,所以检测5次调用后结束,显示如下:
## Command execution times exceed limit: 5, so command will exit. You can set it with -n option.

## 关于参数x :表示追踪深度,看下层级2和3的区别
[arthas@7426]$ watch com.wang.library.app.service.Impl.FileManageServiceImpl queryList '{params, returnObj,throwExp}' '#cost>5' -n 1 -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 108 ms, listenerId: 6
method=com.wang.library.app.service.Impl.FileManageServiceImpl.queryList location=AtExit
ts=2022-09-12 11:01:31; [cost=81.139959ms] result=@ArrayList[
  @Object[][isEmpty=true;size=0],
  @Page[
      @FileInfo[FileInfo(fileId=104, fileName=视频类型测试.mp4, fileType=.mp4, fileSize=4359952, fileUrl=/zoey/upload/视频类型测试.mp4, attribute1=猫猫测试, attribute2=2022-07-31 11:00:26, attribute3=null, attribute4=null, attribute5=null, userName=ljc)],
      @FileInfo[FileInfo(fileId=106, fileName=31d51448bfb8c7c42eda05f6a2940d131e96ddc2bd76a20afcb78d34c28ede33.jpg, fileType=.jpg, fileSize=187697, fileUrl=/zoey/upload/31d51448bfb8c7c42eda05f6a2940d131e96ddc2bd76a20afcb78d34c28ede33.jpg, attribute1=, attribute2=2022-07-31 12:50:25, attribute3=null, attribute4=null, attribute5=null, userName=ljc)],
      @FileInfo[FileInfo(fileId=107, fileName=微信图片_20220802164244.jpg, fileType=.jpg, fileSize=121521, fileUrl=/zoey/upload/微信图片_20220802164244.jpg, attribute1=color pic test, attribute2=2022-08-02 16:43:34, attribute3=null, attribute4=null, attribute5=null, userName=gy)],
      @FileInfo[FileInfo(fileId=108, fileName=微信图片_20220802164254.jpg, fileType=.jpg, fileSize=152146, fileUrl=/zoey/upload/微信图片_20220802164254.jpg, attribute1=color pic test, attribute2=2022-08-02 16:43:34, attribute3=null, attribute4=null, attribute5=null, userName=gy)],
      @FileInfo[FileInfo(fileId=109, fileName=微信图片_20220802164300.jpg, fileType=.jpg, fileSize=241151, fileUrl=/zoey/upload/微信图片_20220802164300.jpg, attribute1=color pic test, attribute2=2022-08-02 16:43:34, attribute3=null, attribute4=null, attribute5=null, userName=gy)],
      @FileInfo[FileInfo(fileId=110, fileName=震惊猫.jpg, fileType=.jpg, fileSize=16038, fileUrl=/zoey/upload/震惊猫.jpg, attribute1=震惊猫, attribute2=2022-09-07 17:20:58, attribute3=null, attribute4=null, attribute5=null, userName=ljc)],
  ],
  null,
]
## 可以看到,-x 2 时,出参并没有展示数据类型

3、trace 追溯操作可以提供所监控方法内部子方法的各个耗时(我的例子里只有一个方法),并对耗时最长的时间进行标红显示:

[arthas@7426]$ trace com.wang.library.app.service.Impl.FileManageServiceImpl queryList -n 3 --skipJDKMethod false
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 130 ms, listenerId: 7
`---ts=2022-09-12 11:10:38;thread_name=http-nio-8087-exec-8;id=16;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@4de4b452
   `---[219.514217ms] com.wang.library.app.service.Impl.FileManageServiceImpl:queryList()
       `---[99.95% 219.398794ms ] com.wang.library.infra.mapper.FileManageMapper:queryList() #184

`---ts=2022-09-12 11:10:41;thread_name=http-nio-8087-exec-9;id=17;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@4de4b452
   `---[85.570788ms] com.wang.library.app.service.Impl.FileManageServiceImpl:queryList()
       `---[99.96% 85.533344ms ] com.wang.library.infra.mapper.FileManageMapper:queryList() #184

`---ts=2022-09-12 11:10:44;thread_name=http-nio-8087-exec-1;id=f;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@4de4b452
   `---[100.438208ms] com.wang.library.app.service.Impl.FileManageServiceImpl:queryList()
       `---[99.96% 100.401052ms ] com.wang.library.infra.mapper.FileManageMapper:queryList() #184

Command execution times exceed limit: 3, so command will exit. You can set it with -n option.
[arthas@7426]$


4、stack 输出当前方法被调用的调用路径,主要监控方法在何处被调用

[arthas@7426]$ stack com.wang.library.app.service.Impl.FileManageServiceImpl queryList -n 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 99 ms, listenerId: 8
ts=2022-09-12 11:15:45;thread_name=http-nio-8087-exec-2;id=10;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@4de4b452
  @com.wang.library.app.service.Impl.FileManageServiceImpl.queryList()
      at com.wang.library.api.controller.v1.FileManageController.selectList(FileManageController.java:190)
      at sun.reflect.GeneratedMethodAccessor75.invoke(null:-1)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
      at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
      at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
      at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
      at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
      at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1060)
      at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:962)
      at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
      at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:626)
      at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
      at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
      at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449)
      at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365)
      at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90)
      at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83)
      at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:387)
      at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362)
      at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
      at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
      at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162)
      at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
      at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
      at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:346)
      at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
      at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
      at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:887)
      at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1684)
      at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
      at java.lang.Thread.run(Thread.java:750)
## 说实话我看着不太舒服,可能是因为日志报错信息也经常是这样打印栈信息的,(浑身一激灵)

5、monitor 方法执行监控

[arthas@7426]$ monitor com.wang.library.app.service.Impl.FileManageServiceImpl queryList -n 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 84 ms, listenerId: 9
timestamp                 class                                   method           total       success       fail         avg-rt(ms)   fail-rate  
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2022-09-12 11:22:44       com.wang.library.app.service.Impl.File queryList           4            4             0            94.24        0.00%      
                          ManageServiceImpl
## 可以看到monitor是整体对方法进行一个检测,类似于上线前的压测,返回调用成功率,失败率以及平均耗时。                          
jad,反编译查看当前运行代码结构
[arthas@7426]$ jad
The argument 'class-pattern' is required, description: Class name pattern, use either '.' or '/' as separator
## 需要输入对应类的全路径,利用tab查看可输入的路径
[arthas@7426]$ jad
net.   com.   sun.   javax. ch.   io.   jdk.   org.   java.  
[arthas@7426]$ jad
net.   com.   sun.   javax. ch.   io.   jdk.   org.   java.  
[arthas@7426]$ jad com.wang.library.ap
com.wang.library.app. com.wang.library.api.
[arthas@7426]$ jad com.wang.library.app.service.FileManageService

ClassLoader:                                                                                                                                                              
+-org.springframework.boot.loader.LaunchedURLClassLoader@685f4c2e                                                                                                          
 +-sun.misc.Launcher$AppClassLoader@70dea4e                                                                                                                              
   +-sun.misc.Launcher$ExtClassLoader@4009e306                                                                                                                            

Location:                                                                                                                                                                  
file:/zoe/jar/zoey-alpha.jar!/BOOT-INF/classes!/                                                                                                                          

/*
* Decompiled with CFR.
*
* Could not load the following classes:
* com.wang.library.domain.entity.FileInfo
* javax.servlet.http.HttpServletRequest
* javax.servlet.http.HttpServletResponse
* org.apache.ibatis.annotations.Param
* org.springframework.web.multipart.MultipartFile
*/
package com.wang.library.app.service;

import com.wang.library.domain.entity.FileInfo;
import java.io.IOException;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.ibatis.annotations.Param;
import org.springframework.web.multipart.MultipartFile;

public interface FileManageService {
  public List<FileInfo> queryAllByLimit(int var1, int var2);

  public List<FileInfo> queryAllFiles();

  public FileInfo queryFileInfoById(@Param(value="fileId") int var1);

  public int deleteFileById(@Param(value="fileId") int var1);

  public List<FileInfo> queryFileByName(@Param(value="fileName") String var1);

  public void uploadFiles(MultipartFile[] var1, String var2, HttpServletRequest var3) throws IOException;

  public String downloadFile(String var1, HttpServletResponse var2) throws IOException;

  public List<FileInfo> queryList();

  public int updateFile(FileInfo var1);
}

Affect(row-cnt:1) cost in 672 ms.
[arthas@7426]$


trace示例:

 

 

 

关于jar包热部署不停服务替换文件:

VMTI(JVM Tool Interface)是 Java 虚拟机所提供的 native 编程接口,是 JVMPI(Java Virtual Machine Profiler Interface)和 JVMDI(Java Virtual Machine Debug Interface)的替代版本。

JVMTI可以用来开发并监控虚拟机,可以查看JVM内部的状态,并控制JVM应用程序的执行。可实现的功能包括但不限于:调试、监控、线程分析、覆盖率分析工具等。

Arthas 的热部署的实现就是使用了 JVMTI 中的 Instrument 接口,通过该接口可以实现字节码的动态替换。

其实linux本身也有类似的替换指令,注意这个替换是替换class文件,而不是替换整个jar包,是用的 jar 系列命令,arthas是retransform命令

### 关于arthas如何替换:
1、在本地编译好要替换的新文件,然后把对应的class文件上传到服务器
2、retransform src/main/java/com/xxx/demo/api/Controller.class
后面就是待替换的class所在路径
   
 
### 关于linux 用jar指令实现替换class文件
## 一、找到文件在jar包中的路径
# xxx.class为你要修改的类
jar -tvf XX.jar | grap xxx.class
# 然后获得路径 BOOT-INF/classes/application.yaml
[root@iZbp1hwh629hd4xz80i1z0Z jar]# jar -tvf zoey-alpha.jar |grep application.yaml
 1625 Sat Jul 30 18:15:02 CST 2022 BOOT-INF/classes/application.yaml


## 二、将找到的路径下的文件解压出来, inflated意为解压缩

# jar -xvf zoey-alpha.jar BOOT-INF/classes/application.yaml
[root@iZbp1hwh629hd4xz80i1z0Z jar]# jar -xvf zoey-alpha.jar BOOT-INF/classes/application.yaml
inflated: BOOT-INF/classes/application.yaml
[root@iZbp1hwh629hd4xz80i1z0Z jar]# ls
arthas-output BOOT-INF fox-test.jar logs zoey-alpha.jar
[root@iZbp1hwh629hd4xz80i1z0Z jar]# cd BOOT-INF/
[root@iZbp1hwh629hd4xz80i1z0Z BOOT-INF]# ls
classes
[root@iZbp1hwh629hd4xz80i1z0Z BOOT-INF]# cd classes/
[root@iZbp1hwh629hd4xz80i1z0Z classes]# ls
application.yaml
[root@iZbp1hwh629hd4xz80i1z0Z classes]#

## 三、用新文件替换刚刚查询的路径下的旧yml文件(cp或其他方式)
[root@iZbp1hwh629hd4xz80i1z0Z jar]# ls
application.yaml arthas-output BOOT-INF fox-test.jar logs zoey-alpha.jar
[root@iZbp1hwh629hd4xz80i1z0Z jar]# cp application.yaml BOOT-INF/classes/application.yaml
cp: overwrite ‘BOOT-INF/classes/application.yaml’? y
[root@iZbp1hwh629hd4xz80i1z0Z jar]#

## 四、将替换后的文件夹再压回jar包

[root@iZbp1hwh629hd4xz80i1z0Z jar]# jar -uvf zoey-alpha.jar BOOT-INF/classes/application.yaml
adding: BOOT-INF/classes/application.yaml(in = 1625) (out= 1017)(deflated 37%)
[root@iZbp1hwh629hd4xz80i1z0Z jar]#

相比来说linux的jar方式看似复杂,但是不需要安装arthas,对于一些安全限制级别强不让连接外网或者安装其他软件的服务器来说还是比较适合的。

 

 

关于内存分析:

 

 

 

jmap查看内存占用

#查看内存占用情况/内存溢出
#查询进程里面详细信息
jmap -heap 41843(你的jar服务对应进程号)

-Xmx3550m 堆最大容量(heap max size)

-Xms3550m 堆最小容量(heap min size)

-Xmn2g 年轻代大小(整个JVM内存大小=年轻代大小+年老代大小+持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小此值对系统性能影响较大,sun官方推荐配置为整个堆的3/8。)

-Xss256k 每个线程栈容量大小(stack size):

[root@192-168-17-127 jar]# jmap -heap 56923
Attaching to process ID 56923, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.281-b09

using thread-local object allocation.
Parallel GC with 8 thread(s)

Heap Configuration:
  MinHeapFreeRatio         = 0
  MaxHeapFreeRatio         = 100
  MaxHeapSize              = 1073741824 (1024.0MB)
  NewSize                  = 178782208 (170.5MB)
  MaxNewSize               = 357564416 (341.0MB)
  OldSize                  = 358088704 (341.5MB)
  NewRatio                 = 2
  SurvivorRatio            = 8
  MetaspaceSize            = 21807104 (20.796875MB)
  CompressedClassSpaceSize = 1073741824 (1024.0MB)
  MaxMetaspaceSize         = 17592186044415 MB
  G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
PS Young Generation
Eden Space:
  capacity = 124256256 (118.5MB)
  used     = 124256256 (118.5MB)
  free     = 0 (0.0MB)
  100.0% used
From Space:
  capacity = 116391936 (111.0MB)
  used     = 0 (0.0MB)
  free     = 116391936 (111.0MB)
  0.0% used
To Space:
  capacity = 111673344 (106.5MB)
  used     = 0 (0.0MB)
  free     = 111673344 (106.5MB)
  0.0% used
PS Old Generation
  capacity = 716177408 (683.0MB)
  used     = 715918144 (682.7527465820312MB)
  free     = 259264 (0.24725341796875MB)
  99.9637989139138% used

56982 interned Strings occupying 6679040 bytes.
[root@192-168-17-127 jar]#

#查看linux服务器内存情况
free -h

关于年轻代与年老代

年轻代和老年代的划分是为了更好的内存分派及回收。提高效率。 堆是垃圾回收机制的重点区域。垃圾回收机制有三种,minor gc,major gc 和full gc。针对于堆的就是前两种。年轻代的叫 minor gc,老年代的叫major gc。

OOM(内存溢出)

  • 年轻代主要存储对象,而经历了多次垃圾回收后依然存活的对象会被移到年老代,年轻代主要是生命周期短的对象,当频繁创建对象,或者创建过多对象导致资源都忙于回收操作,无法进行其余操作,此时可能出现OOM(比如上面的例子)。

  • 从数据库中取出大量数据造成的内存溢出,没有分页等处理,单次查询可能OOM

  • 存在死循环或者过多的重复对象实体,也会导致OOM,尽量用完就让其释放回收掉,比如一个事务内声明对象不要太多,尤其当这个操作是在循环内,我们可以循环一次提交一次。

  •  
posted @ 2022-09-15 10:40  哒布溜  阅读(479)  评论(0编辑  收藏  举报