为什么logger.warn()之前要使用logger.isWarnEnabled()?

典型回答 很多人在读源码的时候,经常可以看到以下代码: Spring中: Dubbo中: 也就是说,很多框架,在执行warn()、debug()等方法前,都会额外的调用一下isWarnEnabled()和isDebugEnabled()等方法,这是为什么呢? isWarnEnabled、isDebugEnabled等方法,其实是判断当前日志级别是否开启的,如果开启则返回true,否则返回false。 其实,之所以要提前调用一次isWarnEnabled,主要是为了提升性能的,因为在记录日志时,生成日志消息的过程可能会涉及方法的执行、字符串的拼接、对象的序列化等操作。而这些操作都是比较耗费时间的。 如果一段日志,不需要输出,那么这些步骤其实是可以省略的。 比如我们有以下日志要输出: 1 2 3 4 5 public void login(LoginRequest loginRequest){ if (logger.isWarnEnabled()) { logger.warn("This is a message with: " + JSON.toJSONString(loginRequest)); } } 通过logger.isWarnEnabled做一次前置判断,那么就可以在warn级别不生效时,能避免 JSON.toJSONString(loginRequest)方法的执行,也能避免"This is a message with: " + JSON.toJSONString(loginRequest)这个字符串拼接操作的执行。 所以,使用logger.isXxxEnabled()用于检查日志Xxx级别是否启用,可以在需要时避免不必要的开销,提高应用程序的性能。这种做法特别在记录频繁的日志消息时,尤为重要。

March 22, 2026 · 1 min · santu

为什么不能直接使用Log4j、Logback中的 API?

典型回答 在Java生态体系中,围绕着日志,有很多成熟的解决方案。关于日志输出,主要有两类工具。 一类是日志框架(Log4j、Logback),主要用来进行日志的输出的,比如输出到哪个文件,日志格式如何等。 另外一类是日志门面(slf4j,commons-logging),主要一套通用的API,用来屏蔽各个日志框架之间的差异的。 对于Java工程师来说,关于日志工具的使用,最佳实践就是在应用中使用如Log4j + SLF4J 这样的组合来进行日志输出。 这样做的最大好处,就是业务层的开发不需要关心底层日志框架的实现及细节,在编码的时候也不需要考虑日后更换框架所带来的成本。这也是门面模式所带来的好处。 扩展知识 常用日志框架 j.u.l j.u.l是java.util.logging包的简称,是JDK在1.4版本中引入的Java原生日志框架。Java Logging API提供了七个日志级别用来控制输出。这七个级别分别是:SEVERE、WARNING、INFO、CONFIG、FINE、FINER、FINEST。 Log4j Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。 Log4j也有七种日志级别:OFF、FATAL、ERROR、WARN、INFO、DEBUG和TRACE。 LogBack LogBack也是一个很成熟的日志框架,其实LogBack和Log4j出自一个人之手,这个人就是Ceki Gülcü。 logback当前分成三个模块:logback-core,logback- classic和logback-access。logback-core是其它两个模块的基础模块。logback-classic是Log4j的一个改良版本。此外logback-classic完整实现SLF4J API使你可以很方便地更换成其它日记系统如Log4j或j.u.l。logback-access访问模块与Servlet容器集成提供通过Http来访问日记的功能。 Log4j2 前面介绍过Log4j,这里要单独介绍一下Log4j2,之所以要单独拿出来说,而没有和Log4j放在一起介绍,是因为作者认为,Log4j2已经不仅仅是Log4j的一个升级版本了,而是从头到尾被重写的,这可以认为这其实就是完全不同的两个框架。 关于Log4j2解决了Log4j的哪些问题,Log4j2相比较于Log4j、j.u.l和logback有哪些优势,我们在后续的文章中介绍。 前面介绍了四种日志框架,也就是说,我们想要在应用中打印日志的时候,可以使用以上四种类库中的任意一种。比如想要使用Log4j,那么只要依赖Log4j的jar包,配置好配置文件并且在代码中使用其API打印日志就可以了。 不知道有多少人看过《阿里巴巴Java开发手册》,其中有一条规范做了『强制』要求: 说好了以上四种常用的日志框架是给Java应用提供的方便进行记录日志的,那为什么又不让在应用中直接使用其API呢?这里面推崇使用的SLF4J是什么呢?所谓的门面模式又是什么东西呢? 什么是日志门面 日志门面,是门面模式的一个典型的应用。 门面模式(Facade Pattern),也称之为外观模式,其核心为:外部与一个子系统的通信必须通过一个统一的外观对象进行,使得子系统更易于使用。 就像前面介绍的几种日志框架一样,每一种日志框架都有自己单独的API,要使用对应的框架就要使用其对应的API,这就大大的增加应用程序代码对于日志框架的耦合性。 为了解决这个问题,就是在日志框架和应用程序之间架设一个沟通的桥梁,对于应用程序来说,无论底层的日志框架如何变,都不需要有任何感知。只要门面服务做的足够好,随意换另外一个日志框架,应用程序不需要修改任意一行代码,就可以直接上线。 在软件开发领域有这样一句话:计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决。而门面模式就是对于这句话的典型实践。 为什么需要日志门面 前面提到过一个重要的原因,就是为了在应用中屏蔽掉底层日志框架的具体实现。这样的话,即使有一天要更换代码的日志框架,只需要修改jar包,最多再改改日志输出相关的配置文件就可以了。这就是解除了应用和日志框架之间的耦合。 有人或许会问了,如果我换了日志框架了,应用是不需要改了,那日志门面不还是需要改的吗? 要回答这个问题,我们先来举一个例子,再把门面模式揉碎了重新解释一遍。 日志门面就像饭店的服务员,而日志框架就像是后厨的厨师。对于顾客这个应用来说,我到饭店点菜,我只需要告诉服务员我要一盘番茄炒蛋即可,我不关心后厨的所有事情。因为虽然主厨从把这道菜称之为『番茄炒蛋』A厨师换成了把这道菜称之为『西红柿炒鸡蛋』的B厨师。但是,顾客不需要关心,他只要下达『番茄炒蛋』的命令给到服务员,由服务员再去翻译给厨师就可以了。 所以,对于一个了解了"番茄炒蛋的多种叫法"的服务员来说,无论后厨如何换厨师,他都能准确的帮用户下单。 同理,对于一个设计的全面、完善的日志门面来说,他也应该是天然就兼容了多种日志框架的。所以,底层框架的更换,日志门面几乎不需要改动。 以上,就是日志门面的一个比较重要的好处——解耦。 常用日志门面 介绍过了日志门面的概念和好处之后,我们看看Java生态体系中有哪些好的日志门面的实现可供选择。 SLF4J Java简易日志门面(Simple Logging Facade for Java,缩写SLF4J),是一套包装Logging 框架的界面程式,以外观模式实现。可以在软件部署的时候决定要使用的 Logging 框架,目前主要支援的有Java Logging API、Log4j及logback等框架。以MIT 授权方式发布。 SLF4J 的作者就是 Log4j 的作者 Ceki Gülcü,他宣称 SLF4J 比 Log4j 更有效率,而且比 Apache Commons Logging (JCL) 简单、稳定。 ...

March 22, 2026 · 1 min · santu

什么是分布式日志系统?

典型回答 现在,很多应用都是集群部署的,一次请求会因为负载均衡而被路由到不同的服务器上面,这就导致一个应用的日志会分散在不同的服务器上面。 当我们要想通过日志做数据分析,问题排查的时候,就需要分别到每台机器上去查看日志,这样就太麻烦了。 于是就有了分布式日志系统,他可以做分布式系统中的日志的统一收集、存储及管理。并且提供好的可用性、扩展性。 一个好的分布式日志系统,应该具备数据采集、数据加工、查询分析、监控报警、日志审计等功能。有了分布式日志系统,我们就可以做集中化的日志管理,(准)实时性的做日志查询及分析,快速的做问题排查,更好的做数据分析及挖掘。 比较主流的这类日志管理系统有ELK、Graylog、Apache Flume,还有很多类似的云产品,如阿里云的SLS。 一般来说,如果资金够就上SLS,不够就自建ELK。 扩展知识 ELK ELK是三个开源软件的缩写,分别表示:Elasticsearch , Logstash, Kibana。 Elasticsearch是个开源分布式搜索引擎,提供分析、存储数据等功能。 Logstash主要是用来日志的搜集、分析、过滤日志的工具,支持大量的数据获取方式。 Kibana也是一个开源和免费的工具,Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助汇总、分析和搜索重要数据日志。 所以,通常是使用Logstash做日志的采集与过滤,ES做分析和查询,Kibana做图形化界面。

March 22, 2026 · 1 min · santu

记录日志影响性能怎么办?

典型回答 很多时候,日志的记录都经常被大家忽略,因为对于性能要求不高的场景中,记录日志确实是可以忽略的。 但是在很多核心业务链路中,1-2ms的影响都很大,所以就会考虑对写日志环节进行性能优化。希望这个技术大家都能用的上,哈哈哈哈。 解决日志慢的问题,主要有两种方案,一个是异步,一个是降级。 因为日志写入操作通常是一个相对耗时的IO操作,如果每次日志记录都同步写入磁盘,可能会导致主线程阻塞,影响应用程序的性能。通过使用异步日志,主线程可以继续执行其他任务,而日志写入操作则由后台线程负责处理,提高了应用程序的响应性和吞吐量。 目前常用的日志框架,如Log4j2、Logback等都是支持异步日志的。都提供了AsyncAppender来实现异步的日志写入。 如logback中做如下配置即可实现异步日志: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>application.log</file> <encoder> <pattern>%logger{35} - %m%n</pattern> </encoder> </appender> <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> <appender-ref ref="FILE" /> <queueSize>512</queueSize> <discardingThreshold>0</discardingThreshold> <neverBlock>true</neverBlock> </appender> <root level="DEBUG"> <appender-ref ref="ASYNC" /> </root> </configuration> 其中queueSize为BlockingQueue的最大容量,默认大小为256,如果请求量大的话,可以适当调大这个queue的size。 ...

March 22, 2026 · 1 min · santu

留言给博主