技术学习总结

73 阅读4分钟

常用框架原理

SpringBoot

IOC:依赖注入,控制反转

关于ioc以springboot举例,可以理解为框架定义了一整套流程,将bean全部创建好,放入一个map容器中,当开发者后续需要使用时,直接从该容器中获取,不需要去手动创建,而关于这定义好的一整套流程主要体现在AbstractApplicationContext的refresh方法中,可以归纳为以下几步。

  1. 加载yaml等配置文件,配置web、容器环境

  2. 配置beanFactory,加载、注册beanFactory的后置处理器

  3. 利用beanFactory的后置处理器,加载所有的bean definitions

  4. 注册bean的后置处理器

  5. 初始化一些资源(如国际化配置),创建、启动tomcat

  6. 创建bean(doCreateBean),其中创建bean又主要分为三个步骤

    • 实例化bean(instanceBean)

      • 后置过滤器执行实例化前方法
      • 利用反射实例化bean
      • 后置过滤器执行实例化bean方法
    • 属性注入(populateBean)

      • 解决循环依赖问题
    • 初始化bean(initializerBean)

      • 后置过滤器执行初始化前方法
      • 初始化bean:先会执行afterPropertiesSet方法,再执行init-method方法
      • 后置过滤器执行初始化bean方法

在上述的refresh方法,也就是启动过程中可以看到对模板方法(父类定义流程,子类具体实现)、继承、多态、接口多实现的经典使用,基于此我们可以在后续写复杂的业务代码时充分学习此类操作,做到将复杂业务简单化、流程清晰化,保证任何人看到该代码都能清晰的意识到其作用,主要做了哪几件事,另外在发生异常时可以更快的定位问题。

AOP:面向切面编程

经典问题示例

页面加载数据异常问题定位

问题现象:页面出现空白、一直转圈加载不出来、提示异常提示语

定位步骤

  1. F12或鼠标右键打开控制台,查看请求信息

    • 若控制台(console)有明显报错信息或控制台(Network)未请求后端接口,则为前端页面js报错
    • 若请求了后端接口,则进入下一步,查询业务服务日志
  2. 查看业务服务日志

    • 若业务日志中有明显报错,则查看代码分析问题 (多实例需每台示例日志均查看)
    • 若业务日志中无明显报错,则查看网关(gateway)中是否有有该请求记录日志
  3. 查看网关(gateway)日志

    • 若网关(gateway)中有明显报错,则分析报错日志定位问题
    • 若网关(gateway)中无明显报错,且有该请求的访问记录(说明请求是到达了网关,且转发到了对应业务服务),则查看nacos或其他注册中心的业务服务注册实例情况,是否存在异常的实例注册到了该环境上
    • 若网关(gateway)无该请求的访问记录,则需查看nginx日志
  4. 查看nginx日志(nginx安装目录下的access.log或error.log)

    • nginx的error.log中是否有报错信息,若有则排查问题,若没有则查看access.log
    • nginx的access.log中若有该请求记录,则查看配置的网关(gateway)地址是否正确
    • nginx的access.log中若没有该请求记录,则可能是前端请求环境不对,如测试环境web端,请求到了预发环境服务端

OOM&FullGC问题

问题现象:日志中频繁出行fullGc、outOfMemory内存溢出

原因分析

  1. 频繁创建过多对象,如死循环、一次性查找数据库数据过多、匿名对象
  2. 大对象一直未被回收,转移到老年代中

复现步骤

  1. 添加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
    
  2. 准备示例代码(以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;
              }
          }
        }
        
    }
    
  3. 借助mat工具分析dump文件

    1. 下载mat文件、运行

    Snipaste_2022-01-25_15-37-08.png

    1. 在上述jvm配置参数的地方导入对应的dump文件

    Snipaste_2022-01-25_15-42-47.png

    1. 根据上图中的饼图可以看到主要问题为java.lang.Thread @ 0xff4a3f30 main ,点击Details,可以查看详细信息,可以看到主要对象为一个很大的StringBuilder对象,即字符串、char数组

    2. 问题已经找到,可切换一个视图,查看堆栈信息(如步骤2图片中的See stacktrace),可以看到问题在GcMock.java的28行

      Snipaste_2022-01-25_16-19-08.png

    至此,问题已定位到代码中,分析、修改对应代码即可。

注意点

  1. FullGC一天超过一次则不正常,需要排查