写点什么

java 高并发系列 - 第 28 天:实战篇,微服务日志的伤痛

  • 2022 年 5 月 16 日
  • 本文字数:1936 字

    阅读完需:约 6 分钟

return?new?TraceRunnable(target);


}


}


需要用线程池执行的任务使用TraceRunnable封装一下就可以了。


TraceUtil 代码:


public?class?TraceUtil?{


public?static?final?String?REQUEST_HEADER_TRACE_ID?=?"com.ms.header.trace.id";


public?static?final?String?MDC_TRACE_ID?=?"trace_id";


private?static?InheritableThreadLocal<String>?inheritableThreadLocal?=?new?InheritableThreadLocal<>();


/**


*?获取 traceid



    *?@return


    */


    public?static?String?get()?{


    String?traceId?=?inheritableThreadLocal.get();


    if?(traceId?==?null)?{


    traceId?=?IDUtil.getId();


    inheritableThreadLocal.set(traceId);


    }


    return?traceId;


    }


    public?static?void?set(String?trace_id)?{


    inheritableThreadLocal.set(trace_id);


    }


    public?static?void?remove()?{


    inheritableThreadLocal.remove();


    }


    }


    日志输出中携带上 trace_id,这样最终我们就可以通过 trace_id 找到一个请求的完整日志了。

    方便快速检索日志

    日志分散在不同的机器上,如果要快速检索,需要将所有服务产生的日志汇集到一个地方。


    关于检索日志的,列一下需求:


    1. 我们将收集日志发送到消息中间件中(可以是 kafka、rocketmq),消息中间件这块不介绍,选择玩的比较溜的就可以了

    2. 系统产生日志尽量不要影响接口的效率

    3. 带宽有限的情况下,发送日志也尽量不要去影响业务

    4. 日志尽量低延次,产生的日志,尽量在生成之后 1 分钟后可以检索到

    5. 检索日志功能要能够快速响应


    关于上面几点,我们需要做的:日志发送的地方进行改造,引入消息中间件,将日志异步发送到消息中间件中,查询的地方采用 elasticsearch,日志系统需要订阅消息中间件中的日志,然后丢给 elasticsearch 建索引,方便快速检索,咱们来一点点的介绍。


    日志发送端的改造


    日志是有业务系统产生的,一个请求过来的时候会产生很多日志,日志产生时,我们尽量减少日志输出对业务耗时的影响,我们的过程如下:


    1. 业务系统内部引用一个线程池来异步处理日志,线程池内部可以使用一个容量稍微大一点的阻塞队列

    2. 业务系统将日志丢给线程池进行处理

    3. 线程池中将需要处理的日志先压缩一下,然后发送至 mq


    线程池的使用可以参考:[JAVA 线程池,这一篇就够了](()


    引入 mq 存储日志


    业务系统将日志先发送到 mq 中,后面由其他消费者订阅进行消费。日志量比较大的,对 mq 的要求也比较高,可以选择 kafka,业务量小的,也可以选取 activemq。


    使用 elasticsearch 来检索日志


    elasticsearch(以下简称 es)是一个全文检索工具,具体详情可以参考其官网相关文档。使用它来检索数据效率非常高。日志系统中需要我们开发一个消费端来拉取 mq 中的消息,将其存储到 es 中方便快速检索,关于这块有几点说一下:


    1. 建议按天在 es 中建立数据库,日质量非常大的,也可以按小时建立数据库。查询的时候,时间就是必选条件了,这样可以快速让 es 定位到日志库进行检索,提升检索效率

    2. 日志常见的需要收集的信息:trace_id、时间、日志级别、类、方法、url、调用的接口开始时间、调用接口的结束时间、接口耗时、接口状态码、异常信息、日志信息等等,可以按照这些在 es 中建立索引,方便检索。

    日志监控报警

    日志监控报警是非常重要的,这个必须要有,日志系统中需要开发监控报警功能,这块我们可以做成通过页面配置的方式,支持报警规则的配置,如日志中产生了某些异常、接口响应时间大于多少、接口返回状态码 404 等异常信息的时候能够报警,具体的报警可以是语音电话、短信通知、钉钉机器人报警等等,这些也做成可以配置的。


    日志监控模块从 mq 中拉取日志,然后去匹配我们启用的一些规则进行报警。

    结构图如下


    关于搭建日志中遇到的一些痛点,可以加我微信 itsoku 交流。


    构建日志系统需要用到的知识点




    1. [java 中线程池的使用](()

    2. [ThreadLocal、InheritableThreadLocal(通俗易懂)](()

    3. elasticsearch,可以参考其官方文档

    4. mq


    java 高并发系列目录




    1. [第 1 天:必须知道的几个概念](()

    2. [第 2 天:并发级别](()

    3. [第 3 天:有关并行的两个重要定律](()

    4. [第 4 天:JMM 相关的一些概念](()

    5. [第 5 天:深入理解进程和线程](()

    6. [第 6 天:线程的基本操作](()

    7. [第 7 天:volatile 与 Java 内存模型](()

    8. [第 8 天:线程组](()

    9. [第 9 天:用户线程和守护线程](()

    10. [第 10 天:线程安全和 synchronized 关键字](()

    11. [第 11 天:线程中断的几种方式](()

    12. [第 12 天 JUC:ReentrantLock 重入锁](()

    13. [第 13 天:JUC 中的 Condition 对象](()

    14. [第 14 天:JUC 中的 LockSupport 工具类,必备技能](()

    15. [第 15 天:JUC 中的 Semaphore(信号量)](()

    16. [第 16 天:JUC 中等待多线程完成的工具类 CountDownLatch,必备技能](()

    17. [第 17 天:JUC 中的循环栅栏 CyclicBarrier 的 6 种使用场景](()

    18. [第 18 天:JAVA 线程池,这一篇就够了](()

    19. [第 19 天:JUC 中的 Executor 框架详解 1](()

    20. [第 20 天:JUC 中的 Executor 框架详解 2](()

    21. [第 21 天:java 中的 CAS,你需要知道的东西](()

    22. [第 22 天:JUC 底层工具类 Unsafe,高手必须要了解](()

    用户头像

    还未添加个人签名 2022.04.13 加入

    还未添加个人简介

    评论

    发布
    暂无评论
    java高并发系列 - 第28天:实战篇,微服务日志的伤痛_Java_爱好编程进阶_InfoQ写作社区