wecenter采集接口 2019独角兽企业重金招聘Python工程师标准(gt)(图)

优采云 发布时间: 2021-08-18 00:17

  wecenter采集接口 2019独角兽企业重金招聘Python工程师标准(gt)(图)

  2019年独角兽企业重磅Python工程师招聘标准>>>

  

  背景

  随着酒店业务的快速发展,我们为用户和企业提供的服务越来越精细,系统的服务化程度和复杂程度也逐渐提高。微服务虽然可以很好的解决问题,但也有副作用,比如问题定位。

  

  每次定位到问题,都需要找同事帮我从源头查日志。一个简单的例子:

  “这个详情页的价格是如何计算的?”

  一次访问用户的酒店空房页面(POI详情页面),流量最多需要经过73个服务节点。在排查问题的时候,我们需要找到4到5个关键节点的同学,帮助我们登录十多个不同节点的机器,查询具体的日志。沟通成本很高,效率很低。

  为了解决这个问题,基础架构同学提供了MTrace(详见技术博客:《分布式会话跟踪系统架构的设计与实践》)协助业务方排查长链接问题.

  但同时,也有许多不确定因素使故障排除过程变得更加困难,甚至徒劳无功:

  各个服务节点存储日志的时间长度不一致;一些服务节点,因为QPS太高,只能不打印或随机打印日志,最终查到问题时,会因为没有日志而导致线索断掉;一些服务节点使用异步逻辑(线程池、Hystrix、异步RPC等),导致日志中缺少trace ID,无法链接在一起;每个服务节点的采样率不同,链路数据的上报率也是随机的,线索很容易被破解; MTrace只有链接信息,没有与每个服务节点相关联的日志信息;动态扩展节点上的日志收缩后找不到了。

  总结如图:

  

  目标

  有两个核心需求:

  根据用户行为快速定位到具体的Trace ID,然后查询服务调用链路上所有节点的日志;实时查询必须准实时(以秒为单位输出),相关链接日志必须在独立的外部存储系统中存储半年以上。

  然后我们进一步拆分上诉:

  记录所有日志是不现实的。需要有选择地记录,记录日志中最有价值的部分;链路数据需要所有服务节点上传,避免链路数据因不同步等原因中断上传;访问方式尽量简单,避免所有服务节点都需要修改具体的服务代码才能访问。最好拦截日志,其他保持透明;日志格式化,部分字段(A*敏*感*词*ey、主机名、IP、时间戳等)不需要在业务RD中重复输入,自动填充;在不阻塞原有业务操作的情况下,准实时展示链接和日志;链路数据和日志数据的存储不依赖于每个业务节点,需要在独立的存储系统上存储半年以上。系统

  明确核心需求后,我们进行了大量针对性研究,最终确定了一个整体的系统设计方案。这就是已经上线、实践已久的“卫星系统”。

  接下来,我们将详细介绍系统,包括一些核心细节。

  架构

  如下图所示,卫星系统横向分为链路和日志两部分。

  

  图2 全链路日志系统整体架构

  链接部分基于MTrace,使用支持超时回退Trace信息传输的Hystrix-Trace插件覆盖所有场景,保证链接完整采集。

  日志部分在接入端有三个核心步骤。首先是基于日志拦截组件以零侵入业务代码的方式采集系统中所有的日志内容,然后按照统一的日志规范对日志进行格式化,最后通过logcenter实现日志到Kafka的传输——基于日志传输机制。

  从纵向来看,分为:

  业务接入层,根据策略采集Trace和业务日志;

  数据处理层,通过storm流处理日志信息;

  数据存储层,用于支持实时查询松鼠(美团点评Redis集群)和持久化存储ES(ElasticSearch),以及面向用户的展示层。

  日志抽样计划

  接入点是所有数据的来源,因此程序设计极为关键。需要解决的问题有:采集策略、链接完整性保护、日志拦截、日志格式化、日志传输。

  在一些业务中,单机日总日志量超过100G,很多业务因为QPS高,选择不正常打印日志,只在排查时通过动态日志级别调整临时输出。因此,我们在最初采集日志时必须进行权衡。经过分析发现,在大多数情况下,排查问题时,发起方都是自己的(RD、PM、Operations)。如果我们只记录这些人发起的链接日志,目标日志量会非常高。自然解决了日志量过大导致的缩减量大、存储时间短、查询时效性差的问题。

  所以我们开发了这个采集 策略:

  通过判断发起者在链接入口服务是否遇到特定人群(住宿业务部员工),决定是否登录采集,通过MTrace将采集标识传递给整个链接。这样可以保证链路上的所有节点都可以一致的选择是否上报日志,保证链路上日志的完整性。

  日志阻塞

  作为日志的核心元素,如何采集是个棘手的问题。强制业务端使用我们的接口进行日志输出会带来很多麻烦。一方面会影响业务端原有的日志输出策略;另一方面,系统原有的日志输出点众多,涉及的业务也是多种多样、变化多端的。一点很简单,但是如果一刀切的改变,很难保证不会有未知的影响。因此,有必要尽可能减少访问方代码的入侵。

  由于酒店的核心业务已经完全集成到log4j2中,经过研究,我们发现可以注册一个全局Filter来遍历系统的所有日志。这一发现使我们能够以零代码更改采集系统的所有日志。

  

  图3 基于log4j2过滤机制的日志采集策略

  日志格式

  业务系统输出的日志格式不同。比如有的不打印TraceID信息,有的不打印日志位置信息,定位困难。这主要带来两个问题。一方面不利于人为主导的调查分析工作,另一方面也不利于后续系统优化升级,如日志、告警的自动分析。

  针对这些问题,我们设计了统一的日志规范,框架完成了缺失内容的填充。同时,我们为业务端提供了标准化的日志接口。业务端可以通过该接口定义日志的元数据,为后续的自动化支持分析奠定基础。

  框架填充统一日志信息的过程利用了log4j2的Plugins机制,通过Properties、Lookups、ContextMap实现业务无感知操作。

  

  图4 通过Plugins机制支持格式化日志属性传输

  日志处理

  在最后的日志传输环节,我们利用日志中心的传输机制,利用日志中心的ScribeAppender实现日志传输到本地agent,再上报到远程Kafka。这种设计有几个优点:

  依托公司成熟的基础服务,相对更加可靠稳定,也无需搭建服务,保障服务安全;日志可以直接传输到日志中心ES进行持久化存储,同时支持快速灵活的数据检索;日志可通过Storm进行流式传输,支持灵活的系统扩展,如实时检索、基于日志的实时业务检查、告警等,为后续系统扩展升级奠定基础。

  我们的数据处理逻辑全部在Storm中处理,主要包括日志存储Squirrel(美团点评基于Redis Cluster开发的纯内存存储)、实时检索和Trace同步。

  目前日志中心ES可以保证分钟级的实时性,但对于RD排查来说还不够。它必须支持第二级的实时性能。因此,我们选择将特定目标用户的日志直接存储到 Squirrel 中。过期时间只有半小时。在查询日志的时候,结合ES和Squirrel,这样既满足了秒级的实时性,又保证了日志量不会太大。压力可以忽略不计。

  我们系统的核心数据有链接和日志。链接信息是通过MTrace服务获取的,但是MTrace服务对于链接数据的存储时间有限,不能满足我们的需求。因此,我们通过延迟队列从MTrace获取最近的链路信息并存储在地面上,从而实现数据的闭环,保证数据的完整性。

  链接完整性保证

  MTrace组件的trace传递功能基于ThreadLocal,酒店业务使用大量异步逻辑(线程池,Hystrix),会造成传输的信息丢失,破坏链路完整性。

  一方面,Sonar对关键环节进行检查和梳理,确保业务端使用transmittable-thread-local中类似于ExecutorServiceTtlWrapper.java和ExecutorTtlWrapper.java的包,将ThreadLocal中的Trace信息传输到异步线程(上面提到的MTrace也提供了这样的包)。

  另一方面,Hystrix 的线程池模式会导致线程变量丢失。为了解决这个问题,MTrace 提供了 Mtrace Hystrix Support Plugin 来实现跨线程调用时线程变量的传递。但是由于Hystrix有专门的定时器线程池用于超时回退调用,在超时的情况下会进入回退逻辑之后的链接。信息丢失。

  针对这个问题,我们对Hystrix机制进行了深入研究,最终结合Hystrix Command Execution Hook、Hystrix Concurrency Strategy、Hystrix Request Context实现了一个覆盖整个Hystrix-Trace插件场景,保证链接的完整性。

  HystrixPlugins.getInstance().registerCommandExecutionHook(new HystrixCommandExecutionHook() {

@Override

public void onStart(HystrixInvokable commandInstance) {

// 执行command之前将trace信息保存至hystrix上下文,实现超时子线程的trace传递

if (!HystrixRequestContext.isCurrentThreadInitialized()) {

HystrixRequestContext.initializeContext();

}

spanVariable.set(Tracer.getServerSpan());

}

@Override

public Exception onError(HystrixInvokable commandInstance, HystrixRuntimeException.FailureType failureType, Exception e) {

// 执行结束后清空hystrix上下文信息

HystrixRequestContext context = HystrixRequestContext.getContextForCurrentThread();

if (context != null) {

context.shutdown();

}

return e;

}

@Override

public void onSuccess(HystrixInvokable commandInstance) {

// 执行结束后清空hystrix上下文信息

HystrixRequestContext context = HystrixRequestContext.getContextForCurrentThread();

if (context != null) {

context.shutdown();

}

}

});

HystrixPlugins.getInstance().registerConcurrencyStrategy(new HystrixConcurrencyStrategy() {

@Override

public Callable wrapCallable(Callable callable) {

// 通过自定义callable保存trace信息

return WithTraceCallable.get(callable);

}

});

  业绩展示

  例如,以用户单击 POI 详细信息页面的 TraceID 为例进行故障排除:

  我们可以看到他在MTrace中的调用链接是这样的:

  

  在卫星系统中,显示如下效果:

  

  可以看出,系统在保存链路数据的基础上,还将所有链路节点日志聚合在一起,提高了调查效率。

  后续规划

  目前该系统还处于起步阶段,主要用于解决RD在排查中的两大痛点:不完整和过于分散的日志信息。这个需求现在已经得到满足。但是,全链接日志系统可以做的远不止这些。主要后续计划如下:

  支持多链接日志相关搜索,如列表页刷新和后续详情页展示,虽然有多个链接,但实际上是在一个相关的场景中。支持关联搜索,可以将日志调查对象从单个动作维度扩展到多个动作组成的场景维度。支持业务侧自定义策略规则,自动进行基于日志的业务正确性检查。如发现问题,可直接将详细信息通知相关人员,实现日志实时监控、问题实时发现、实时通知到位,省去人工和人工。有效的劳动。作者介绍

  雅辉,2015年加入美团点评,在后端研发团队工作。

  曾军,2013年加入美团点评,在后端研发团队工作。

  最后,我会发布一个广告。后端研发团队长期招聘Java后端及架构人才。有兴趣的同学可以把简历发到xuguanfei#。

  转载于:

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线