达达集团技术

业务数据精准上报与排查工具实践

  • 一.业务系统面临的挑战

  • 二.横向产品调研

    • 2.1 分布式链路追踪系统

    • 2.2 传统ELK日志系统

  • 三.设计思路

  • 四.使用流程

  • 五. 常见问题答疑

一.业务系统面临的挑战

到店导购频道页系统底层借助多个中台能力,随着系统支持的场景越来越丰富,业务逻辑变得越来越复杂,导致系统复杂度也随之快速提升。随着业务流量逐步增加,研发侧运维时间也随之增长,如何在短时间内解决问题,还原第一现场,成为我们面临的挑战。
基于以上面临的两个问题,业务数据精准追踪及快速排查将成为关键。通过工具化希望记录业务执行整个过程,从而还原第一现场,基于业务逻辑执行情况分析和问题定位,成为整个研发运维过程中很重要的一环。

二.横向产品调研

目前主流的业务追踪实现方式有两种,分为:分布式链路追踪系统(SkyWalking,Pinpoint)、基于日志的ELK。

以下讲解下使用场景和弊端:

2.1 分布式链路追踪系统

分布式链路追踪系统核心原理是在每一次调用栈中,使用同一个TraceId将不同的server进行串联;以下展示一个系统间调用案例:
摘 录 《Dap per》
基于上述一个完整的调用链,一个用户请求应用A,应用A需要请求应用B和应用C,而应用C需要请求应用D和应用E,形成一个有向无环图;
摘录《Dap per》
分布式链路追踪系统首先将各个日志收集点按照一定的采样率将日志写进数据文件,然后通过管道将这些日志文件按照一定的traceId排定输出到BigTable中去。如果一个系统完成了上面阐述的架构,基本可以构成一个简单的Trace系统。同时分布式调用链路追踪覆盖了单个请求流经的所有服务、服务器等信息,不仅包含当前业务系统,还包含了多个下游服务,覆盖所有逻辑方法,实现单链路数据无差别上报。但该方案也存在以下痛点:
  • 日志数据量大 :随着系统复杂度增加,数据信息不断增多占用了大量的磁盘资源,增加服务器磁盘成本,其中涉及的关键节点数据可能仅占用了一小部分。

  • 维护性成本高 :现有的成型产品接入成本本高,后期维护成困难,学习成本大,功能迭代自主性低,适配场景化业务困难。

综上所述,分布式链路追踪可以实现完整的链路监控,但是学习成本高,维护成本高,扩展性低无法适配后期功能迭代优化,以及现有业务系统的快速支持。

2.2 传统ELK日志系统

传统的ELK方案需要开发者在编写代码时尽可能全地打印日志,再通过关键字段从ES中搜集筛选出与业务逻辑相关的日志数据,进而拼凑出业务执行的现场信息。然而该方案存在如下的痛点:
  • 环境搭建复杂 :Elasticsearch、Logstash、Kibana、Filebeat等多个服务需要分别部署与运维,运维成本与服务器成本较高。

  • 日志搜集繁琐 :虽然ES提供了日志检索的能力,但是日志数据往往是缺乏结构性的文本段,很难快速完整地搜集到全部相关的日志。

  • 日志筛选困难 :不同业务场景、业务逻辑之间存在重叠,重叠逻辑打印的业务日志可能相互干扰,难以从中筛选出正确的关联日志,无法清晰观察一种业务场景的调用链路。

  • 日志分析耗时 :搜集到的日志只是一条条离散的数据,只能阅读代码,再结合逻辑,由人工对日志进行串联分析,尽可能地还原出现场。

综上所述,随着业务逻辑和系统复杂度的攀升,传统的ELK方案在日志搜集、日志筛选和日志分析方面愈加的耗时耗力,很难快速实现对业务的追踪。
因此,无论是分布式追踪系统还是基于日志文件ELK都存在各自的不足,无法快速支持现有业务。所以,本系统借鉴了以上方案的设计思想,结合到店系统实际业务场景,汇总用户系统使用现场日志,通过时间戳+唯一链路标识,解决筛选困难问题,通过业务属性信息实现精准筛选,解决分析耗时筛选繁琐等问题,从而搭建一套简单易用且符到店场景的业务数据精准上报与排查工具,降低系统运维成本提供快速定位问题能力;
下文重点介绍设计思路和使用流程,同时结合实际使用业务系统举例说明。

三.设计思路

  • 业务系统稳定性高 :提供独立的线程池,任务挤压采用直接丢弃策略。提供异步上报能力,借助MQ中间件实现消息异步消费。

  • 业务系统接入成本低 :提供SDK工具包,集成独立线程池、消息发送功能。提供注解、切面、手动上报方式简化接入流程。

  • 提供链路追踪能力 :借助京东pfinder能力实现全链路标识集成,简化复杂筛选;

  • 可视化与数据隔离 :借助微应用能力快速生成可视化应用,为接入的应用提供独立应用以及定制化页面,实现业务链路数据可视化操作,并且通过业务身份实现关键数据逻辑隔离;

  • 即时通知能力 :借助京me即时消息能力,结合微应用人员设置能力,实现关键信息即时推送。

整体业务架构图:

基于以上的设计,在业务系统与中台系统串联过程中,实现精准数据上报。同时提供独立于业务系统的SDK工具包,降低研发接入成本;提供多种集成方式,降低对业务系统的侵入性,提升系统的稳定性;借助微应用能力,通过配置化的方式实现业务日志系统的一键生成,降低系统使用难度,同时支持根据具体的场景诉求实现条件的动态配置,从而提升精准定位问题的效率。

四.使用流程

整体使用流程:

以上是对使用的整体流程释义。主要分为五个步骤,其中标 蓝色部分 为业务系统操作部分, 红色部分 为微应用系统能力部分,接下来我们对整体步骤进行拆解说明:

步骤一:微应用系统创建应用,并获取应用唯一身份agentId;

  • (1)应用创建(为数据隔离以及可视化页面搭建独立应用)
  • (2)agentId获取(为数据隔离提供业务身份)

步骤二:引入上报工具SDK:

  • 找到项目的pom.xml并引入SDK的maven包

  • 替换tools.version 当前版本为2.0.0-SNASHOT

<dependency>    <groupId>com.jd.tools.log</groupId>    <artifactId>tools-api</artifactId>    <version>${tools.version}</version></dependency>

步骤三:添加基础配置:

  • 配置上报数据系统身份标识,即:在微应用系统创建的业务身份(步骤一中确定的身份)

  • 可配到*.properties文件或*.yml文件中(根据实际工程配置一处即可)

*.properties文件

lc.systemCode= ${agentId}

*.yml文件

lc:  systemCode: ${agentId}

步骤四:根据实际情况完成业务数据精准上报:目前上报方式分为三种:

上报方式

优点

缺点

使用场景

注解 灵活、无代码、简单 关键方法手动添加、私有方法不支持、上报数据格式单一 新系统、方法拆分粒度较细、不考虑内部关键点
API 灵活、上报格式可控、通用性高、无公私有方法限制 编码量、代码侵入 新老系统通用、需要上报私有方法或方法内逻辑关键点数据
切面 基于路径拦截、配置简单、覆盖范围广 私有方法不支持、上报数据格式单一、无法识别关键点 不需要考虑系统上报关键点、需要全域上报数据
综上所述:数据上报是后续工作的基础,所以对上报的业务数据质量需要使用者结合实际场景分析,可通过多种上报方式组合提升业务数据上报的质量,为后续工作提升效率;

以下详细讲解使用方式:

(1)注解方式:通过在指定的目标方法上添加注解完成指定方法出入参上报;

  • 引入注解@SysLog填写方法分类 module模块信息、action动作描述、description功能描述
    // 注解上报    @SysLog(module = "前台类目tab", action = "查询", description = "查询前台类目tab")    public APIResult<List<CategoryMappingResp>> getCategoryMapping(Map<String, Object> params) {        try{            //......            return categoryMappingService.getCategoryMapping(baseRequest);        } catch (Exception e){            //......            return APIResult.systemError("系统错误");        }    }

(2)API上报:通过SDK中提供的service完成方法内关键节点的数据上报;

  • 引入LogReportService类,完善logReportHadJSON方法
    //注入手动上报服务类    @Resource    private LogReportService logReportService;    @Override    public HomeModuleDO<HotWordData> getData(HomeEventContext event) {          //......        // API上报关键点        logReportService.logReportHadJSON(new SysOperateLog("热词查询","首页直出", JsonHelper.toJSONString(event),"热词楼层Handler",                 JSONObject.toJSONString(res),this.getClass().getName(),"getData", EmChannelOriginType.COLOR));        return .....;    }

(3)切面上报:通过业务系统自主编写切面类并配置上报路径,同时注入SDK中提供的的服务,实现数据上报;

  • 编写以下样例代码,配置切面@Pointcut(xxxx)
    //主要上报服务类    @Resource    private LogReportService reportService;    //根据路径切面    @Pointcut("execution(public * xxxx..*.*(..)) || execution(public * xxxxxx..*.*(..))")    public void logPointCut() {    }    @AfterReturning(returning = "ret", pointcut = "logPointCut()")    public void doAfter(JoinPoint joinPoint, Object ret) {        try {            reportService.selfLogReport(joinPoint,ret);        }catch (Exception e) {            //可忽略        }    }

步骤五:登陆微应用系统查看上报情况:

下面根据实际上报的报文进行介绍,主要包含系统自定义信息、业务系统上报信息,其中account、channelOrigin、className、createdDate、methodName、module都是业务系统通过注解其他方式传入值,systemCode是通过读取业务系统配置,traceId目前是集成pfinder获取,其他部分为业务关键数据。

主要分为三部分:

  • 上报入参内容:operateParam;

  • 上报返回内容:responseContent;

  • 以及系统关键内容:链路信息、用户信息、时间、上报系统身份标识、日志级别等;

通过对报文解析,结合微应用内页面设计器能力以及服务中心能力,实现系统可视化生成;

后续规划:

  • 并行链路追踪能力 :通过链路上报的traceId以及时间完成请求的链路数据串联,目前对并行链路串联支持不友好,针对这方面能力也在规划完善中;

  • 定制化数据分析能力 :后续能力提升通过上报服务作为mapping关联预设报文,实现对数据业务场景定制化解析告警;

  • 多维度看板能力 :后续通过数据解析能力,实现上报应用内所有服务接口的系统级看板,针对不同服务周期性错误或相同错误进行分类汇总生成数据看板,方便用户进行总结观察发现系统薄弱点;

  • 探针动态切入能力 :进一步提升系统集成效率,降低系统侵入性,提升系统执行效率;

五.常见问题答疑

1、集成会不会对系统的性能影响很大?

  • 答:考虑到对系统的影响降到最低,我们采用了独立的线程池+mq异步上报,任务打满时采用直接丢弃策略,从而降低对系统的性能影响;

2、如何快速查询某用户某时段哪条链路节点出现问题?

  • 答:可根据时间+用户的pin快速定位当前时段的数据,再通过traceId完成整体链路的串联,从而排查上报的那个关键节点出现问题。