常用框架原理
SpringBoot
IOC:依赖注入,控制反转
关于ioc以springboot举例,可以理解为框架定义了一整套流程,将bean全部创建好,放入一个map容器中,当开发者后续需要使用时,直接从该容器中获取,不需要去手动创建,而关于这定义好的一整套流程主要体现在AbstractApplicationContext的refresh方法中,可以归纳为以下几步。
-
加载yaml等配置文件,配置web、容器环境
-
配置beanFactory,加载、注册beanFactory的后置处理器
-
利用beanFactory的后置处理器,加载所有的bean definitions
-
注册bean的后置处理器
-
初始化一些资源(如国际化配置),创建、启动tomcat
-
创建bean(doCreateBean),其中创建bean又主要分为三个步骤
-
实例化bean(instanceBean)
- 后置过滤器执行实例化前方法
- 利用反射实例化bean
- 后置过滤器执行实例化bean方法
-
属性注入(populateBean)
- 解决循环依赖问题
-
初始化bean(initializerBean)
- 后置过滤器执行初始化前方法
- 初始化bean:先会执行afterPropertiesSet方法,再执行init-method方法
- 后置过滤器执行初始化bean方法
-
在上述的refresh方法,也就是启动过程中可以看到对模板方法(父类定义流程,子类具体实现)、继承、多态、接口多实现的经典使用,基于此我们可以在后续写复杂的业务代码时充分学习此类操作,做到将复杂业务简单化、流程清晰化,保证任何人看到该代码都能清晰的意识到其作用,主要做了哪几件事,另外在发生异常时可以更快的定位问题。
AOP:面向切面编程
经典问题示例
页面加载数据异常问题定位
问题现象:页面出现空白、一直转圈加载不出来、提示异常提示语
定位步骤:
-
F12或鼠标右键打开控制台,查看请求信息
- 若控制台(console)有明显报错信息或控制台(Network)未请求后端接口,则为前端页面js报错
- 若请求了后端接口,则进入下一步,查询业务服务日志
-
查看业务服务日志
- 若业务日志中有明显报错,则查看代码分析问题 (多实例需每台示例日志均查看)
- 若业务日志中无明显报错,则查看网关(gateway)中是否有有该请求记录日志
-
查看网关(gateway)日志
- 若网关(gateway)中有明显报错,则分析报错日志定位问题
- 若网关(gateway)中无明显报错,且有该请求的访问记录(说明请求是到达了网关,且转发到了对应业务服务),则查看nacos或其他注册中心的业务服务注册实例情况,是否存在异常的实例注册到了该环境上
- 若网关(gateway)无该请求的访问记录,则需查看nginx日志
-
查看nginx日志(nginx安装目录下的access.log或error.log)
- nginx的error.log中是否有报错信息,若有则排查问题,若没有则查看access.log
- nginx的access.log中若有该请求记录,则查看配置的网关(gateway)地址是否正确
- nginx的access.log中若没有该请求记录,则可能是前端请求环境不对,如测试环境web端,请求到了预发环境服务端
OOM&FullGC问题
问题现象:日志中频繁出行fullGc、outOfMemory内存溢出
原因分析:
- 频繁创建过多对象,如死循环、一次性查找数据库数据过多、匿名对象
- 大对象一直未被回收,转移到老年代中
复现步骤:
-
添加jvm启动参数
开发环境
-XX:+PrintGCDetails -XX:+UseConcMarkSweepGC -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC -XX:HeapDumpPath=D:\Project\demo\gc
正式环境
-XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpBeforeFullGC -XX:+HeapDumpAfterFullGC -XX:HeapDumpPath=../gc
-
准备示例代码(以oom举例),运行
import com.google.common.collect.Lists; import java.awt.font.FontRenderContext; import java.util.List; /** * oom&full 问题示例 */ public class GcMock { public static void main(String[] args) { List<OOMObject> oomList = Lists.newArrayList(); while (true) { oomList.add(new OOMObject()); } } static class OOMObject{ static String s = "dddddddddddddddddddddddddddddddddddddddddddd"; static { for (int i = 0; i < 10000; i++) { s += s; } } } }
-
借助mat工具分析dump文件
-
下载mat文件、运行
-
在上述jvm配置参数的地方导入对应的dump文件
-
根据上图中的饼图可以看到主要问题为java.lang.Thread @ 0xff4a3f30 main ,点击Details,可以查看详细信息,可以看到主要对象为一个很大的StringBuilder对象,即字符串、char数组
-
问题已经找到,可切换一个视图,查看堆栈信息(如步骤2图片中的See stacktrace),可以看到问题在GcMock.java的28行
至此,问题已定位到代码中,分析、修改对应代码即可。
-
注意点:
- FullGC一天超过一次则不正常,需要排查