我正在参加「掘金·启航计划」
目前IDEA上有一些在用的插件,个人觉得还不错。在一定场景下提升了开发项目过程中的开发效率。
1. RestfulToolkit-fix
一款辅助restful接口的功能插件
1.1. 查找网页链接
场景:通常前端反馈某一个接口时,我们往往是通过接口的地址找到对应的controller,在找到对应的方法,再逐步去定位问题。安装插件后,我们只需要按下快捷键ctrl+
可以快速定位到对应的方法上。
可以直接快速的跳转到对应的方法上,非常方便快捷。
1.2. 文件接口和发起restful请求
可以直接通过菜单栏找到restful的接口,同时直接发起请求。插件同步会跟你组装好接口上的参数,就不需要我们手动一个一个输入参数名称来编写接口。
1.3. 复制接口上的地址和参数
在接口上,可以直接获得请求JSON(压缩和不压缩),不带端口的地址,带端口的完整URL地址。方便我们放到apipost,postman等http工具中进行调试。
2. Alibaba Cloud Toolkit
虽然我这边没有阿里云的服务器,仅仅对于Host的发布和上传就已经非常好用了。在小型项目上可以直接跳过jenkins这个繁琐且麻烦的工具。直接将本地能跑起来的代码部署到远程服务器上。(且支持批量上传到多个服务器中)。整个工具集还带了非常多的工具(codeup-类gitee带代码评审,微服务-目前还没有体验到等等)。
2.1. 服务器端上传
可以点击右边的Add Host添加对应的服务器,填写服务器的登录密码。
- 选取本地需要上传的jar包
- 填写需要上传到远程服务器的绝对地址
- 上传过后需要执行重启命令(这里使用docker部署,所以直接用docker启动即可)
2.2. 一键上传
在使用上传功能时,显然还不够完美,我们想让代码编译好后直接同步到服务器上,真正做到一键上传。这个就需要在配置中心中添加Deploy to Host。
这样就可以实现代码编译成功后,直接打包项目代码到远程服务器。对于小项目,非常省心。
2.3. 应用热部署
目前这个场景还没有用到,但是我之前文章使用arthas可以实现类似功能。看来alibaba这个插件应该也是借鉴了arthas的能力。可以直接将本地的java转换成class,再加载到远程服务器内存中。
2.4. 远端文件&诊断
- 远端文件就比较简单了,可以直接像ssh一样连接到服务器上,点击右键就可以下载文件到本地来。可以彻底抛弃sftp等之前的工具了。结合前面使用的上传功能,xshell就可以彻底告别了。
- 远程诊断也是利用的arthas的远端调试能力,直接远程调试代码,简直无敌。
- 可以直接查看dashboard,thread等常用命令,非常高效。
3. MybatisX
一款辅助mybatis开发的插件,目前我主要使用的时mapper和xml直接跳转,代码自动生成这两个功能。
3.1. Mapper和Xml直接跳转
会识别mapper文件,我们可以直接点击这个小鸟图案跳转到xml中去。
相应的我们也可以在xml中点击另外一个颜色的小鸟跳转到mapper文件中去。
3.2. 自动生成mybatis模板代码
在database菜单中,直接点击MybatisX-Generator
可以根据需要修改基础包名,实体的包名,类名
选择Mybatis-Plus3的注解,模版。这样就会自动生成xml文件,mapper文件,service接口,service实现。这样我们只需要编写controller和一些基本的代码即可。大部分常规的方法都已经替我们包装好了,我们直接使用即可。
4. arthas idea
其实上面提到的alibaba cloud toolkit插件,其中的一部分功能就是使用arthas来进行的实现。这样我们就可以配合这个插件,提取我们想要的命令到上面的诊断窗口中进行调试。实现我们远程对服务器运行状态,性能等各个维度指标的查看。
arthas虽然很好用,但是如果需要用到的时候,往往都需要去官网去查询对应的命令,自己组装。这个时候就非常的慢。可以使用这个工具,快速的知道命令。
4.1. 方法耗时
可以清晰的知道每一个方法的耗时,通过分析得出需要优化改进的方法。通过上述示例图可以看到所有耗时都是在下面这个方法,这个时候就需要我们进行下一步的分析了。
+---[92.75% 33.08474ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor:doFilter() #83
上面的trace有一个缺陷,只能trace到子一层就会停止。arthas其实也提供了到下面多层的方法。我们可以通过在开一个窗口,trace下子方法,就可以监听到多层的耗时了。
`---ts=2023-06-26 00:46:18;thread_name=http-nio-8096-exec-7;id=2b;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@7161d8d1
`---[11.615455ms] cn.mucheen.server.config.interceptor.ConfigInterceptor:doFilter()
+---[0.03% 0.003268ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:<init>() #32
`---[99.76% 11.587622ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter() #32
`---[99.90% 11.575701ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter()
+---[0.02% 0.002033ms ] java.util.List:size() #67
+---[0.01% 0.001718ms ] java.util.List:get() #69
`---[99.87% 11.560321ms ] cn.mucheen.server.config.interceptor.ConfigFilter:doFilter() #70
`---[99.89% 11.547664ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter()
+---[0.01% 0.001272ms ] java.util.List:size() #67
+---[0.01% 0.001289ms ] java.util.List:get() #69
`---[99.91% 11.536704ms ] cn.mucheen.server.config.interceptor.ConfigFilter:doFilter() #70
`---[99.55% 11.48487ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter()
+---[0.01% 0.00131ms ] java.util.List:size() #67
+---[0.01% 0.001336ms ] java.util.List:get() #69
`---[99.90% 11.473729ms ] cn.mucheen.server.config.interceptor.ConfigFilter:doFilter() #70
`---[99.92% 11.464255ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter()
+---[0.01% 0.001234ms ] java.util.List:size() #67
+---[0.01% 0.001302ms ] java.util.List:get() #69
`---[99.91% 11.45349ms ] cn.mucheen.server.config.interceptor.ConfigFilter:doFilter() #70
`---[99.77% 11.426692ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter()
+---[0.01% 0.001209ms ] java.util.List:size() #67
+---[0.01% 0.001317ms ] java.util.List:get() #69
`---[99.91% 11.416116ms ] cn.mucheen.server.config.interceptor.ConfigFilter:doFilter() #70
`---[99.63% 11.374002ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter()
+---[0.02% 0.002172ms ] java.util.List:size() #67
+---[0.02% 0.00193ms ] java.util.List:get() #69
`---[99.87% 11.358747ms ] cn.mucheen.server.config.interceptor.ConfigFilter:doFilter() #70
`---[99.79% 11.335174ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter()
+---[0.02% 0.002018ms ] java.util.List:size() #67
+---[0.02% 0.001784ms ] java.util.List:get() #69
`---[99.83% 11.316416ms ] cn.mucheen.server.config.interceptor.ConfigFilter:doFilter() #70
`---[99.67% 11.278507ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter()
+---[0.02% 0.002009ms ] java.util.List:size() #67
+---[0.02% 0.002076ms ] java.util.List:get() #69
`---[99.86% 11.26263ms ] cn.mucheen.server.config.interceptor.ConfigFilter:doFilter() #70
`---[0.28% 0.031459ms ] cn.mucheen.server.config.interceptor.ConfigInterceptor$SdkConfigFilterChain:doFilter()
+---[9.74% 0.003063ms ] java.util.List:size() #67
+---[5.52% 0.001735ms ] java.util.List:get() #69
`---[9.93% 0.003124ms ] cn.mucheen.server.config.interceptor.ConfigFilter:doFilter() #70
由于我这里方法全套的层数有点多,所以需要逐步去拆解,针对特定的类,逐步去分析每个类的调用情况。同步监听了一个包下面的所有类的同一方法。
定位到了一个问题耗时方法。这个方法耗时占比非常高。
可以看到这是一个redis的操作,下一步就是如何优化代码,降低这一部分耗时。提高整个请求的qps了。