gateway 链路监控
现状:目前查找一个交易的详情,须要通过 portainer 进入申请所在的容器查找流水号对应的日志。因为申请很多,同一申请的日志可能不在一起,并且同一申请中有的日志无奈增加流水号。
目标:通过流水号对网关日志进行查问,可失去同一申请的所有日志。
原理图:
办法:
将 gateway 的同一申请的日志增加流水号:
- 申请进入时日志增加流水号
- 响应回来时日志增加流水号,因为申请和响应不是同一个线程解决
- 发送响应时删除日志流水号
- 异步操作传递流水号
通过 ELK 对网关日志进行收集,以 gateway-{date}归集一个 index,做为根底的服务日志。
Filebeat:换行的日志当作一条发送到 kafka
Logstash:解析 orderNo 当作 es 的一个字段
查问:
配置后端服务的日志收集地址,在查问交易日志时可通过 api 查到关联的上游日志
以 api-invoke-his 做为交易流水库,依据流水号,网关类型和日期到 gateway-{date}(昨今今天)查问具体 gateway 日志,依据 apiName 查到关联的上游日志 index,综合失去整条链路的日志
毛病:
- 代码侵入性比拟强,须要改变到处中央
- 被动配置的中央较多,须要配置交易的日志收集 index,即交易的链路。须要提前晓得交易的链路。比照 skywalking,引入 agent 即可打印链路的信息,然而无奈打印日志。
- 如果想监控 mysql、es,须要本人开发 agent
系统日志监控:
背景:
微服务中系统日志散落在各个机器中,无奈集中查看,目前通过 elk 可收集各个系统的日志在 kibana 查看。然而日志构造比拟涣散,出了问题排查艰难,须要当时找到机器。此外如果日志量大,难以查看报错日志的上下文。因而须要疾速找到一次申请链上的所有日志。因而须要一种疾速晓得哪里报错以及找到报错上下文日志的计划。
计划简述:
将同一申请 / 解决逻辑的日志增加雷同流水号,不便零碎异样时查到关联日志。其中所有服务的异样日志放入同一个 es 的 index,不便间接展现谬误日志。如果该日常蕴含流水号,可去相干服务查问具体日志。如果晓得申请通过的服务,能够查问链路的相干日志。谬误日志也放入 kafka 的 topic 中,便于监控零碎对接告警。
目标:
- 疾速找到报错的日志及流水号,便于查看系统启动时是否胜利
- 通过流水号找到对立申请的日志。(须要手动关联同一流水号的多个服务,无奈做到 api 级别的动静关联,如果查找所有 index 比拟消耗性能)
原理图:
流程:
- Filebeat 监听服务日志,定义 logtopic 放入 kafka 的 openapi_{logtopic}中
- Logstash 监听 openapi_{logtopic}的 topic,将数据格式化后输入至三个方向:
- 全量输入至{logtopic}_{date},即在 es 中按 logtopic 和日期为 index 进行保留
- 级别为 error 的日志一方面输入至 openapi_error_{date},即以 error 和日期为 index 进行保留,另一方面输入至 topic 为 openapi-error 的 kafka 中,供监控告警应用。
- 这些输入是并行的。
- Monitor 以 error_{date}为根底数据源进行查看,如果异样日志蕴含流水号,则可跳转至 {logtopic}-{date} 进行查看服务的日志。如果查看相干链路日志,须要联结 index 进行查问。
须要解决的问题:
- 流水号在服务外部传递
- 流水号在服务间传递
- 流水号在异步线程传递
- 服务在某个办法中传递
服务日志增加流水号的形式:
- request filter:web 申请到来时,如果此时线程中曾经设置过流水号,不必再设置。如果没有设置且 header 中蕴含 orderNo,则将其作为以后线程的 order,否则新生成 orderNo 并设置。确保 filter 是申请第一个进入的,防止一些 log 记录不到流水号。
- Feign intercepter:服务通过 feign 调用其余服务时,将以后线程的 orderNo 放入 header 中,保障上游服务能够取得 orderNo。如果有应用 hystrix,须要在 hystrix 线程池中传递 mdc
- 异步线程池:异步执行时,无奈传递流水号,因而须要应用特定的线程池,能够传递流水号
- 独自执行的办法:redis,mq 的监听,执行定时工作,由特定事件执行,而非 web 申请触发,通过 aop 在办法执行前设置 MDC,实现后革除
革新的中央:
- 异步执行应用特定线程池
- 独自执行的办法增加注解
- Filebeat 减少换行的配置,只传输 *All 的日志
- Logstash 减少 orderNo 的解析,log_level 为 error 的传入 es 及 kafka 中
问题:
如果不是 logger.info 或 logger.error 的日志,如果出现异常如 NullPointerException,尽管是同一个线程解决,但流水号无奈继承。须要有 GlobalExceptionAspect 捕捉全局异样
Async-threadpool:
- 提供一个能够间接应用的线程池,@Async 间接应用。使用方便,不必什么配置
- 提供获取线程池的静态方法,能够通过办法获取,通过 @Bean 注入,便于设置线程池参数。场景:有多个参数不同的线程池需要
- 提供线程池装璜器,自定义的线程池加上装璜器即可增加 mdc
Method-aspect:
有些代码的执行并不禁 web 申请触发,而是由定时工作,mq 的监听触发,执行某个办法。因而须要对办法进行 AOP 拦挡,执行前增加 MDC,执行完后删除。此外留神产生异样时也须要拦挡并删除 MDC。
异样如果不必 logger.error/info 记录,则无奈打印 MDC,主动抛出的异样(如除数为 0)尽管在一个线程解决但 mdc 为空。因而 AOP 须要拦挡异样并用 logger.error 进行记录。
此外,@PostConstruct 执行的办法无奈增加 MDC。
Feign-interceptor:
如果以后线程蕴含 MDC,则在 header 中设置,否则不做解决。因为有可能应用到 hystrix 进行限流熔断,须要对 hystrix 进行配置
Request-interceptor:
如果以后线程蕴含 MDC,不做解决;如果不蕴含,查看 header 是否含有 orderNo,如果蕴含,将 orderNo 作为流水号设为 MDC,否则生成新 orderNo 作为 MDC。
留神的几个点:
- Filebeat 同步的是 **All.log 日志,防止 error 呈现两次
- MDC put 后再 put,会革除
- Request filter 的 order;filter 在 interceptor 前,因而须要用 filter 且优先级最高,保障申请到来第一个进入
- Gateway 无奈应用 skywalking,因为是 nio,申请和响应是不同线程解决,响应无奈与申请的 mdc 保持一致
- 第三方 jar 包的类名最好加上服务名称,防止反复