前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >logback避坑指南:AsyncAppender配置避坑

logback避坑指南:AsyncAppender配置避坑

作者头像
崔认知
发布2023-06-19 16:50:39
发布2023-06-19 16:50:39
2.3K00
代码可运行
举报
文章被收录于专栏:nobodynobody
运行总次数:0
代码可运行

AsyncAppender可能出现OOM问题


AsyncAppender会使用BlockingQueue缓存事件,默认缓存大小为256。

代码语言:javascript
代码运行次数:0
运行
复制
 /**
     * The default buffer size.
     */
    public static final int DEFAULT_QUEUE_SIZE = 256;
    int queueSize = DEFAULT_QUEUE_SIZE;
代码语言:javascript
代码运行次数:0
运行
复制
blockingQueue = new ArrayBlockingQueue<E>(queueSize);

如果设置了过大的queueSize可能会导致OOM的发生

同时我们也要设置合适的discardingThreshold。

代码语言:javascript
代码运行次数:0
运行
复制
 static final int UNDEFINED = -1;
 int discardingThreshold = UNDEFINED;

discardingThreshold的默认值为queueSize的 1/5。

代码语言:javascript
代码运行次数:0
运行
复制
 if (discardingThreshold == UNDEFINED)
            discardingThreshold = queueSize / 5;

discardingThreshold的作用就是当缓存BlockingQueue所剩余的空间不足discardingThreshold值时,会丢弃日志级别为TRACE, DEBUG 及 INFO的事件。

代码语言:javascript
代码运行次数:0
运行
复制
@Override
    protected void append(E eventObject) {
        if (isQueueBelowDiscardingThreshold() && isDiscardable(eventObject)) {
            return;
        }
        preprocess(eventObject);
        put(eventObject);
    }

    private boolean isQueueBelowDiscardingThreshold() {
        return (blockingQueue.remainingCapacity() < discardingThreshold);
    }
代码语言:javascript
代码运行次数:0
运行
复制
/**
     * Events of level TRACE, DEBUG and INFO are deemed to be discardable.
     * @param event
     * @return true if the event is of level TRACE, DEBUG or INFO false otherwise.
     */
    protected boolean isDiscardable(ILoggingEvent event) {
        Level level = event.getLevel();
        return level.toInt() <= Level.INFO_INT;
    }

LOSSY BY DEFAULT IF 80% FULL AsyncAppender buffers events in a BlockingQueue. A worker thread created byAsyncAppender takes events from the head of the queue, and dispatches them to the single appender attached toAsyncAppender. Note that by default, AsyncAppender will drop events of level TRACE, DEBUG and INFO if its queue is 80% full. This strategy has an amazingly favorable effect on performance at the cost of event loss.

https://logback.qos.ch/manual/appenders.html

AsyncAppender可能出现丢失日志的问题


上述上谈到了discardingThreshold值的作用,及会丢弃日志级别为TRACE, DEBUG 及 INFO的事件。

如果BlockingQueue队列的大小设置的比较小(默认值就很小了已经),且discardingThreshold设置的值大于0或者默认值,就很容易丢弃丢弃日志级别为TRACE, DEBUG 及 INFO的事件。

如果不想日志丢失,设置discardingThreshold值为0,而且最好把BlockingQueue队列的大小queueSize值设置的大一点。

AsyncAppender可能出现阻塞的问题


AsyncAppender的异步机制的出现本来就是优化日志阻塞问题的,但是使用不当还是出现阻塞问题。

代码语言:javascript
代码运行次数:0
运行
复制
 private void put(E eventObject) {
        if (neverBlock) {
            blockingQueue.offer(eventObject);
        } else {
            putUninterruptibly(eventObject);
        }
    }
代码语言:javascript
代码运行次数:0
运行
复制
  private void putUninterruptibly(E eventObject) {
        boolean interrupted = false;
        try {
            while (true) {
                try {
                    blockingQueue.put(eventObject);
                    break;
                } catch (InterruptedException e) {
                    interrupted = true;
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }

neverBlockd的默认值为false,会调用BlockingQueue的阻塞方法put。

代码语言:javascript
代码运行次数:0
运行
复制
boolean neverBlock = false;

那么当BlockingQueue队列满的时候或剩余容量达到阈值discardingThreshold就会出现阻塞问题。

设置neverBlock为true,永不阻塞,但可能丢失日志。如果希望兼顾性能和丢日志问题,根据AsyncAppender可能出现丢失日志的问题,设置discardingThreshold值为0,而且把BlockingQueue队列的大小queueSize值设置的大一点。

小结


AsyncAppender配置避坑指南:

1、OOM问题;

2、丢失日志问题;

3、阻塞问题;


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-06-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 认知科技技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档