欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot如何動(dòng)態(tài)改變?nèi)罩炯?jí)別

 更新時(shí)間:2020年12月17日 09:37:55   作者:ksfzhaohui  
這篇文章主要介紹了SpringBoot如何動(dòng)態(tài)改變?nèi)罩炯?jí)別,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下

前言

關(guān)于日志級(jí)別,大部分項(xiàng)目可能都設(shè)置為info級(jí)別,當(dāng)然也可能有一些追求性能或者說(shuō)包含很多敏感信息的項(xiàng)目直接將級(jí)別設(shè)置為warn或者error;這時(shí)候如果項(xiàng)目中出現(xiàn)一些未知異常,需要用到很詳細(xì)的日志信息,此時(shí)如果項(xiàng)目中沒(méi)有動(dòng)態(tài)改變?nèi)罩炯?jí)別的機(jī)制,排查問(wèn)題將很棘手。

日志系統(tǒng)

我們常用的一些日志系統(tǒng)包括:Log4j2、Logback、Java Util Logging;我們想動(dòng)態(tài)改變?nèi)罩镜募?jí)別,前提是這些日志系統(tǒng)都支持我們直接設(shè)置日志等級(jí),當(dāng)然這些系統(tǒng)提供了很簡(jiǎn)單的接口;

  • Log4j2
LoggerContext loggerContext = (LoggerContext) LogManager.getContext(false);
LoggerConfig loggerConfig = loggerContext.getConfiguration().getLoggers().get("root");
loggerConfig.setLevel(level);
  • Logback
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
Logger logger = loggerContext.getLogger("root");
((ch.qos.logback.classic.Logger) logger).setLevel(level);
  • Java Util Logging
Logger logger = Logger.getLogger("root");
logger.setLevel(level);

當(dāng)然除了上面直接設(shè)置日志級(jí)別的方式,也有可以動(dòng)態(tài)加載配置文件的方式,同樣也可以在配置文件中動(dòng)態(tài)改變?nèi)罩炯?jí)別,以logback為例:

LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
File externalConfigFile = new File("logback.xml");
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(lc);
lc.reset();      
configurator.doConfigure(externalConfigFileLocation);

上面簡(jiǎn)單介紹了一下每種日志系統(tǒng)都是如何去設(shè)置日志級(jí)別的,最關(guān)鍵的是設(shè)置完之后,可以實(shí)時(shí)生效,立馬可以看到我們想要的日志;有了這些下面其實(shí)就是通過(guò)何種方式去改變?nèi)罩炯?jí)別的問(wèn)題了;

如何動(dòng)態(tài)改變級(jí)別

如何去動(dòng)態(tài)改變級(jí)別,最簡(jiǎn)單的方式就是對(duì)外提供一個(gè)接口,給定一個(gè)日志級(jí)別作為參數(shù)實(shí)時(shí)變更;或者通過(guò)配置中心的方式;另外其實(shí)像SpringBoot這些主流的框架本身也提供了動(dòng)態(tài)修改的功能;下面可以具體看一下是如何實(shí)現(xiàn)的,以logback為例;

自定義接口

自定義一個(gè)給定日志級(jí)別的接口,外部直接通過(guò)調(diào)用接口來(lái)改變級(jí)別:

@RequestMapping(value = "logLevel/{logLevel}")
public String changeLogLevel(@PathVariable("logLevel") String logLevel) {
  try {
    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    Logger logger = loggerContext.getLogger("root");
    ((ch.qos.logback.classic.Logger) logger).setLevel(Level.valueOf(logLevel));
  } catch (Exception e) {
    logger.error("changeLogLevel error", e);
    return "fail";
  }
  return "success";
}

想要改變?nèi)罩炯?jí)別直接請(qǐng)求如下地址即可,設(shè)置一個(gè)debug的級(jí)別:

http://[ip]:[port]/logLevel/debug

這種方式雖然比較簡(jiǎn)單,但是如果節(jié)點(diǎn)很多的話(huà),操作起來(lái)就很麻煩,當(dāng)然也可以匯總所有節(jié)點(diǎn)路徑,一次操作觸發(fā)所有節(jié)點(diǎn)的請(qǐng)求;其實(shí)最好的辦法應(yīng)該是類(lèi)似發(fā)布訂閱的方式,發(fā)布者會(huì)給所有訂閱者都發(fā)送一個(gè)更改日志級(jí)別的通知,有新的節(jié)點(diǎn)只要成為訂閱者即可,這種方式其實(shí)就是現(xiàn)在主流的配置中心的方式。

配置中心

配置中心的目的其實(shí)就是把一些會(huì)經(jīng)常變動(dòng)的參數(shù)集中保存起來(lái),某個(gè)系統(tǒng)啟動(dòng)時(shí)去配置中心獲取相關(guān)的參數(shù),同時(shí)會(huì)對(duì)這些參數(shù)進(jìn)行監(jiān)聽(tīng),后面在配置中心里面改變參數(shù)的值會(huì)實(shí)時(shí)推送給相關(guān)系統(tǒng);這樣系統(tǒng)就可以在不重啟的情況下就更新了配置;
利用現(xiàn)有的一些中間件我們就能很快實(shí)現(xiàn)一個(gè)配置中心,比如Zookeeper提供了對(duì)某個(gè)Node進(jìn)行監(jiān)聽(tīng)的功能,MQ和Redis都有發(fā)布訂閱的功能,所以用來(lái)實(shí)時(shí)推送變更再好不過(guò)了;

  • Zookeeper方式

可以直接使用PathChildrenCache用來(lái)監(jiān)聽(tīng)子節(jié)點(diǎn)的CHILD_ADDED,CHILD_UPDATED,CHILD_REMOVED事件;這樣如果在Zookeeper服務(wù)端對(duì)節(jié)點(diǎn)的值就行更新,客戶(hù)端會(huì)觸發(fā)以上三個(gè)事件:

private void watcherPath(String path) {
  PathChildrenCache cache = new PathChildrenCache(client, path, true);
  cache.start(StartMode.POST_INITIALIZED_EVENT);
  cache.getListenable().addListener(new PathChildrenCacheListener() {
    @Override
    public void childEvent(CuratorFramework client, PathChildrenCacheEvent event) throws Exception {
      switch (event.getType()) {
      case CHILD_ADDED:
        break;
      case CHILD_UPDATED:
        String logLevel = new String(event.getData().getData());
         //日志級(jí)別更新處理
        break;
      case CHILD_REMOVED:
        break;
      default:
        break;
      }
    }
  });
}
  • MQ方式

MQ一般都有Queue和Topic方式,Topic方式其實(shí)就是訂閱發(fā)布模式,所有的集群節(jié)點(diǎn)可以訂閱某個(gè)Topic,這樣發(fā)布端發(fā)送更新日志級(jí)別的消息,其他訂閱節(jié)點(diǎn)都能收到:

//日志等級(jí)Topic
private final String TOPIC = "LOGLEVEL";
 
private void watcherPaths() throws JMSException {
  Topic topic = session.createTopic(TOPIC);
  MessageConsumer consumer = session.createConsumer(topic);
  consumer.setMessageListener(new MessageListener() {
    @Override
    public void onMessage(Message message) {
      TextMessage tm = (TextMessage) message;
      String logLevel = tm.getText();
      //日志級(jí)別更新處理
    }
  });
}
  • Redis方式

Redis其實(shí)除了緩存的功能,也提供了類(lèi)似MQ的發(fā)布訂閱的模式;集群節(jié)點(diǎn)通過(guò)訂閱一個(gè)channel,發(fā)布端通過(guò)此channel來(lái)發(fā)布消息:

private void watcherPaths() throws JMSException {
  jedis.subscribe(new JedisPubSub() {
    @Override
    public void onMessage(String channel, String message) {
       String logLevel = message;
       //日志級(jí)別更新處理
    }
  },"LOGLEVEL");
}

SpringBoot內(nèi)置

SpringBoot2.0之后可以通過(guò)actuator動(dòng)態(tài)調(diào)整日志級(jí)別,主要是通過(guò)暴露loggers這個(gè)endpoint來(lái)實(shí)現(xiàn),具體步驟如下:

  • 需要引入actuator
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
  • 暴露loggers

在application.properties中添加如下配置:

management.endpoints.web.exposure.include=loggers
  • 查看日志級(jí)別

啟動(dòng)服務(wù)可以通過(guò):

http://[ip]:[port]/actuator/loggers

查看當(dāng)前項(xiàng)目每個(gè)包的日志級(jí)別:

{
levels: [
  "OFF","ERROR","WARN","INFO","DEBUG","TRACE"
],
loggers: {
  ROOT: {
   configuredLevel: "INFO",
   effectiveLevel: "INFO"
  },
...
}
  • 動(dòng)態(tài)修改日志級(jí)別

發(fā)送POST請(qǐng)求到:

http://[ip]:[port]/actuator/loggers/[包路徑]

需要在body中指定configuredLevel參數(shù);
比如修改整個(gè)項(xiàng)目日志級(jí)別為error:

http://[ip]:[port]/actuator/loggers/root

關(guān)于SpringBoot內(nèi)部是如何實(shí)現(xiàn)動(dòng)態(tài)改變?nèi)罩炯?jí)別的,可以查看其實(shí)現(xiàn)核心類(lèi)LoggersEndpoint:

@Endpoint(id = "loggers")
public class LoggersEndpoint {
  private final LoggingSystem loggingSystem;
  @WriteOperation
  public void configureLogLevel(@Selector String name, @Nullable LogLevel configuredLevel) {
    Assert.notNull(name, "Name must not be empty");
    this.loggingSystem.setLogLevel(name, configuredLevel);
  }
  ...
}

具體通過(guò)LoggingSystem來(lái)對(duì)日志系統(tǒng)動(dòng)態(tài)改變級(jí)別,上面也介紹了主流使用的日志系統(tǒng),SpringBoot也都支持這些系統(tǒng),這是一個(gè)抽象類(lèi),具體實(shí)現(xiàn)類(lèi):

  • JavaLoggingSystem
  • Log4J2LoggingSystem
  • LogbackLoggingSystem
  • NoOpLoggingSystem

分別對(duì)應(yīng)了幾種日志系統(tǒng),這幾個(gè)類(lèi)內(nèi)部其實(shí)也是調(diào)用上面介紹的方法去改變?nèi)罩炯?jí)別,當(dāng)然SpringBoot自動(dòng)會(huì)識(shí)別出當(dāng)前使用的是哪個(gè)日志系統(tǒng),然后使用哪個(gè)LoggingSystem;

總結(jié)

大部分公司其實(shí)更多的還是使用配置中心的方式來(lái)動(dòng)態(tài)改變?nèi)罩炯?jí)別,這種方式更加靈活,而且配置中心已經(jīng)成為很多公司的標(biāo)配組件,不光用來(lái)改變?nèi)罩炯?jí)別,所有有可能改變的參數(shù)都可以使用。

以上就是SpringBoot如何動(dòng)態(tài)改變?nèi)罩炯?jí)別的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot 動(dòng)態(tài)改變?nèi)罩炯?jí)別的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論