天天看點

Spring Boot Logging Level設定為off時Bug

發博詞

阿裡雲的KAFA有一個特性就是會主動關閉空閑的連結,這樣導緻的問題就是用戶端程式會不停的報如下的異常資訊:

java.io.IOException: 遠端主機強迫關閉了一個現有的連接配接。
  at sun.nio.ch.SocketDispatcher.write0(Native Method) ~[na:1.8.0_112]
  at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51) ~[na:1.8.0_112]
  at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93) ~[na:1.8.0_112]
  at sun.nio.ch.IOUtil.write(IOUtil.java:65) ~[na:1.8.0_112]
  at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471) ~[na:1.8.0_112]
  at org.apache.kafka.common.network.SslTransportLayer.flush(SslTransportLayer.java:195) ~[kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.common.network.SslTransportLayer.close(SslTransportLayer.java:163) ~[kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.common.utils.Utils.closeAll(Utils.java:731) [kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.common.network.KafkaChannel.close(KafkaChannel.java:54) [kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.common.network.Selector.doClose(Selector.java:540) [kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.common.network.Selector.close(Selector.java:531) [kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.common.network.Selector.pollSelectionKeys(Selector.java:378) [kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.common.network.Selector.poll(Selector.java:303) [kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.clients.NetworkClient.poll(NetworkClient.java:349) [kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.clients.consumer.internals.ConsumerNetworkClient.poll(ConsumerNetworkClient.java:226) [kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.clients.consumer.KafkaConsumer.pollOnce(KafkaConsumer.java:1048) [kafka-clients-0.10.2.0.jar:na]
  at org.apache.kafka.clients.consumer.KafkaConsumer.poll(KafkaConsumer.java:995) [kafka-clients-0.10.2.0.jar:na]
  at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:558) [spring-kafka-1.1.6.RELEASE.jar:na]
  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_112]
  at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_112]
  at java.lang.Thread.run(Thread.java:745) [na:1.8.0_112]      

而這個異常資訊,其實意義不大,而且會一直出,是以就有了需求想要關閉kafka這個包的日志。

臨時解決方法

Spring Boot Logging将LogLevel抽象為6個級别,還有一個OFF,是配置關閉日志:

/**
 * Logging levels supported by a {@link LoggingSystem}.
 *
 * @author Phillip Webb
 */
public enum LogLevel {

  TRACE, DEBUG, INFO, WARN, ERROR, FATAL, OFF

}      

但是将某個包的日志級别設定為OFF時,控制台會報如下的資訊:

2017-08-24 13:52:12.882 ERROR 12672 --- [           main] o.s.cloud.logging.LoggingRebinder        : Cannot set level: false for 'org.apache.kafka'      

定位到LoggingRebinder#setLogLevel方法:

private void setLogLevel(LoggingSystem system, Environment environment, String name,
      String level) {
    try {
      if (name.equalsIgnoreCase("root")) {
        name = null;
      }
      level = environment.resolvePlaceholders(level);
      system.setLogLevel(name, LogLevel.valueOf(level.toUpperCase()));
    }
    catch (RuntimeException ex) {
      this.logger.error("Cannot set level: " + level + " for '" + name + "'");
    }
  }      

此時 RuntimeException ex的異常資訊如下

java.lang.IllegalArgumentException: No enum constant org.springframework.boot.logging.LogLevel.FALSE      

檢視level = environment.resolvePlaceholders(level)的值,确實是字元串false而不是off,是以LogLevel.valueOf(level.toUpperCase())在解析的時候就報錯了。