首页 > 其他分享 >是谁的请求导致我的系统一直抛异常?

是谁的请求导致我的系统一直抛异常?

时间:2022-11-10 18:33:47浏览次数:73  
标签:导致 异常 请求 洞察 demo mse com alibabacloud

作者:屿山、十眠

在线上环境中,请求错综复杂,如果有某个请求出现了不符合预期的情况,我们往往会先需要确定这个请求在实际环境中是由哪个 Controller 来处理的。通常情况下,我们需要去查阅文档或是代码,这个过程往往比较繁琐,并且不一定是准确的,可能由于一些问题会导致我们的请求没有被预期的 Controller 处理。而借助微服务洞察的能力,能够快速地定位特定的请求在真实环境中是由哪个 Controller 处理的。

流程分析

本文的 demo 包含 log-demo-spring-cloud-zuul、log-demo-spring-cloud-a、log-demo-spring-cloud-b、log-demo-spring-cloud-c 四个应用,采用最简单的 Spring Cloud 标准用法依次调用,可以直接在项目上查看源码。https://github.com/aliyun/alibabacloud-microservice-demo/tree/master/mse-simple-demo

以 SpringCloud 为例,请求到达后会由 org.springframework.web.servlet.DispatcherServlet#doDispatch 方法处理请求的整体流程。


  protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

    try {
      ModelAndView mv = null;
      Exception dispatchException = null;

      try {
        processedRequest = checkMultipart(request);
        multipartRequestParsed = (processedRequest != request);

        // Determine handler for the current request.
        mappedHandler = getHandler(processedRequest);
        if (mappedHandler == null) {
          noHandlerFound(processedRequest, response);
          return;
        }

        // Determine handler adapter for the current request.
        HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

        // Process last-modified header, if supported by the handler.
        ……
        // Actually invoke the handler.
        ……
        
      }
    }
  }

可以看到决定由哪个 handler 来处理请求的功能由 org.springframework.web.servlet.DispatcherServlet#getHandler 方法负责。该方法所返回的 org.springframework.web.servlet.HandlerExecutionChain 类的实例,就是最后实际处理该请求的 handler。也就是说我们只需要借助微服务洞察的能力观测这个方法的返回值即可。

微服务洞察

首先,简单介绍一下要使用的微服洞察能力,该能力基于规则的模型,以动态增强的方式为我们获取真实的现场信息。它的规则模型如下图所示:

1.png

Target:

  • ResourceTarget: 目标接口,支持 Web、Rpc、SQL 以及任意的自定义方法
  • WorkloadTarget: 目标实例,可以选择所有机器或指定机器 IP
  • TrafficCondition: 是否仅针对异常、慢调用、全链路灰度标签

Action:

  • 相关上下文诊断信息的收集,参数、返回值、线程上下文、Target 对象、类加载器信息等
  • 后续链路是否日志打印
  • 流量染色、限流降级等治理动作

在本文的场景中,我们需要将 org.springframework.web.servlet.DispatcherServlet#getHandler 设为我们的 Target,目标实例为默认的全部,不添加流量过滤条件。

2.png

随后,我们选择想要打印的内容,在这个场景中我们所需要是该方法的返回值,其他的内容可以根据需要选择。

3.png

在开启规则之后,我们可以在控制台中看到如图的调用链展示,可以看到/a 这个请求在 log-demo-spring-cloud-a 中的调用栈在基础的框架记录中新增了我们所选择的方法 org.springframework.web.servlet.DispatcherServlet#getHandler 的相关记录,从右侧的 Attributes 中的 mse.return 字段中可以看到该请求会由 java.lang.String com.alibabacloud.mse.demo.AApplication$AController.a 来处理。

4.png

辅助异常分析

线上的请求出现了异常,在定位问题的过程中,我们往往会需要知道调用的堆栈信息,进而去排查堆栈上的方法。借助微服务洞察的能力,我们也可以很方便的进行这些操作。

本场景在前文的 Demo 中增加了对数据库的访问,使用了 Druid 作为连接池组件。

当发现某个 url 的请求部分报错,但我们并没有预先编写能够记录有效信息的日志,这时我们就可以通过一条规则来打印现场的堆栈信息,以获取我们需要排查的方法列表,再进一步对逐个方法进行分析。假设是/sql 的请求出现了部分报错,我们选择/sql 作为 Target,如果不知道具体的接口,也可以选择全部。

5.png

由于我们只需要分析错误的请求,所以在过滤规则条件中开启异常过滤,在打印内容中选中调用堆栈,其他的内容可以根据需要选择。

6.png

开启该规则后,可以在控制台看到堆栈信息。

7.png

at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:989)
  at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeQuery(DruidPooledPreparedStatement.java:213)
  at com.alibabacloud.mse.demo.service.DruidCon.doCommond(DruidCon.java:57)
  at com.alibabacloud.mse.demo.service.DruidService.query(DruidService.java:15)
  at com.alibabacloud.mse.demo.BApplication$AController.sql(BApplication.java:89)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

截取其中一部分可以发现 com.alibabacloud.mse.demo.service.DruidCon.doCommond 以及 com.alibabacloud.mse.demo.service.DruidService.query 都是我们自身的业务逻辑方法,也是我们需要关注的方法,我们可以继续借助微服务洞察的能力,去获取这些方法的现场信息,比如参数、返回值、类加载器等等。

这边以获取 com.alibabacloud.mse.demo.service.DruidCon.doCommond 方法的参数信息为例。同样只需要一条规则,类似前文,将该方法设为 Target,打开异常过滤标签,在打印内容中选中请求参数,开启规则后,便可以在控制台看到该方法的参数信息。

8.png

以上只是简单的例子,但是能够由此发现,微服务洞察的能力能够让我们在 Java 方法任意点位收集信息,将排查工作变成零代码且动态的,由于不需要在测试环境中重复增加日志代码并不断重启应用,能够大大减小某些难以在测试环境中复现的问题的排查难度。

在非预期的情况下,工作在最优解

微服务洞察能力提供了 Java 方法任意点位的可观测能力,本文通过该能力演示了:观测请求的匹配、观测异常场景下请求的上下文等场景,可以帮助我们在系统出现异常时进行问题定位,除了本文的场景还有很多微服务的场景能够借助微服务洞察能力来观测,将原本复杂且交织的微服务场景清晰地展现在我们面前。微服务洞察能力我们还在持续地打磨与完善,而发现并定位问题并不是目的,对于系统稳定来说只是迈出了第一步,我们还需要进一步结合治理能力才能够真正让系统稳定运行,比如本文的场景中可以针对异常的请求进行限流,或是快速地隔离故障,或是针对不稳定的服务进行容错降级等等,从而保护我们的系统。

在真实环境中,系统的不稳定性不仅仅来自于我们自身的业务逻辑错误,还有很多可能比如突发的大流量,上下游的不稳定等等。而这些问题都可以交给 MSE,使系统在非预期的情况下仍能工作在最优解。

9.png

标签:导致,异常,请求,洞察,demo,mse,com,alibabacloud
From: https://www.cnblogs.com/alisystemsoftware/p/16878018.html

相关文章

  • django跨站请求伪造csrf
    一、简介跨站点脚本(XSS)漏洞是指攻击者可以将脚本注入到你的服务器发送的页面中。浏览器将这些注入的脚本视为页面中的任何其他脚本。例如,如果http://www.yoursite.co......
  • AD域/OpenLDAP账号密码被修改或过期,802.1x认证自动重连导致账户被锁定,无法上网怎么办?
    搭建了微软ActiveDirectory(AD)或OpenLDAP的企业,通常会让员工使用AD域账号或OpenLDAP账号密码登录电脑终端、OA、VPN、VDI或进行网络接入802.1x认证。AD域/OpenLDAP......
  • django-05-请求和响应
    请求和响应defsomething(request):#request是一个对象,封装了用户发送过来的所有请求相关数据-1.[请求]获取请求方式GET/POSTprint(request.meth......
  • NETCORE 使用中间件获取请求头
    NETCORE使用中间件获取请求头创建项目:框架net6webapi:项目名称:NETCORE.RequestHead   1. 创建中间件 RequestHeaderVerificationMiddleware.csusingMic......
  • SpringBoot全局异常处理(三十)
    生活打了我们一巴掌,我们,一定要想办法再打回来上一章简单介绍了SpringBoot上传文件到远程服务器(二十九),如果没有看过,​​请观看上一章​​一.为什么要实现异常信息自定义......
  • spring mvc 请求异步处理,即时响应
    springmvc的controller,对于一个非常耗时的处理,让controller先异步返回响应给前端,后台继续慢慢执行完。@RequestMapping(value="refreshScore.do",method=Reque......
  • 记录一次springboot 集成 openfeign 实现模块间调用异常
    记录一次springboot集成openfeign实现模块间调用异常 问题背景product 服务作为服务端,提供了一个对外通信Fegin接口ProductClient,放在了com.imooc.product.clie......
  • K8s系列---【KubeSphere部署完mysql8.0再部署mysql5.0导致mysql5.0启动失败的问题】
    KubeSphere部署完mysql8.0再部署mysql5.0导致mysql5.0启动失败的问题1.报错InnoDB:Tableflagsare0inthedatadictionarybuttheflagsinfile./ibdata1are0x......
  • Java异常
    异常一、异常:就是程序出现不正常的情况。ThrowableErrorExceptionRuntimeException非RuntimeExceptionError:严重问题,不处理Exception:异常类,程序本身可......
  • Nginx基于请求头的分发
    前面介绍的分发方式适用于单个集群,而基于请求头分发适用于多个集群场景。基于请求头的分发1、基于host分发:适用于一个公司有多个网站,一个网站设置为一个集群#nginx分发......