reactor-logback的AsyncAppender执行流程源码解读

 更新时间:2023年12月18日 09:54:52   作者:codecraft  
这篇文章主要为大家介绍了reactor-logback的AsyncAppender执行流程源码解读,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下reactor-logback的AsyncAppender

AsyncAppender

reactor-logback/src/main/java/reactor/logback/AsyncAppender.java

public class AsyncAppender extends ContextAwareBase
        implements Appender<ILoggingEvent>, AppenderAttachable<ILoggingEvent>,
                   CoreSubscriber<ILoggingEvent> {
    private final AppenderAttachableImpl<ILoggingEvent>    aai      =
            new AppenderAttachableImpl<ILoggingEvent>();
    private final FilterAttachableImpl<ILoggingEvent>      fai      =
            new FilterAttachableImpl<ILoggingEvent>();
    private final AtomicReference<Appender<ILoggingEvent>> delegate =
            new AtomicReference<Appender<ILoggingEvent>>();
    private String                            name;
    private WorkQueueProcessor<ILoggingEvent> processor;
    private int     backlog           = 1024 * 1024;
    private boolean includeCallerData = false;
    private boolean started           = false;
    //......
}
AsyncAppender继承了ContextAwareBase,同时实现了Appender、AppenderAttachable、CoreSubscriber接口

CoreSubscriber

reactor/core/CoreSubscriber.java

public interface CoreSubscriber<T> extends Subscriber<T> {
    /**
     * Request a {@link Context} from dependent components which can include downstream
     * operators during subscribing or a terminal {@link org.reactivestreams.Subscriber}.
     *
     * @return a resolved context or {@link Context#empty()}
     */
    default Context currentContext(){
        return Context.empty();
    }
    /**
     * Implementors should initialize any state used by {@link #onNext(Object)} before
     * calling {@link Subscription#request(long)}. Should further {@code onNext} related
     * state modification occur, thread-safety will be required.
     * <p>
     *    Note that an invalid request {@code <= 0} will not produce an onError and
     *    will simply be ignored or reported through a debug-enabled
     *    {@link reactor.util.Logger}.
     *
     * {@inheritDoc}
     */
    @Override
    void onSubscribe(Subscription s);
}
CoreSubscriber继承了Subscriber接口,Subscriber接口定义了onSubscribe(Subscription s)、onNext、onError、onComplete方法

onSubscribe

public void onSubscribe(Subscription s) {
        try {
            doStart();
        }
        catch (Throwable t) {
            addError(t.getMessage(), t);
        }
        finally {
            started = true;
            s.request(Long.MAX_VALUE);
        }
    }
    protected void doStart() {
    }
onSubscribe方法执行doStart,标记started为true,同时触发s.request(Long.MAX_VALUE)

onNext

public void onNext(ILoggingEvent iLoggingEvent) {
        aai.appendLoopOnAppenders(iLoggingEvent);
    }
onNext调用AppenderAttachableImpl的appendLoopOnAppenders方法

onError

public void onError(Throwable t) {
        addError(t.getMessage(), t);
    }
onError主要是添加错误信息到logback的status

onComplete

public void onComplete() {
        try {
            Appender<ILoggingEvent> appender = delegate.getAndSet(null);
            if (appender != null){
                doStop();
                appender.stop();
                aai.detachAndStopAllAppenders();
            }
        }
        catch (Throwable t) {
            addError(t.getMessage(), t);
        }
        finally {
            started = false;
        }
    }
    protected void doStop() {
    }
onComplete则执行doStop、appender.stop()、aai.detachAndStopAllAppenders(),最后标记started为false

Appender.doAppend

public void doAppend(ILoggingEvent evt) throws LogbackException {
        if (getFilterChainDecision(evt) == FilterReply.DENY) {
            return;
        }
        evt.prepareForDeferredProcessing();
        if (includeCallerData) {
            evt.getCallerData();
        }
        try {
            queueLoggingEvent(evt);
        }
        catch (Throwable t) {
            addError(t.getMessage(), t);
        }
    }

    protected void queueLoggingEvent(ILoggingEvent evt) {
        if (null != delegate.get()) {
            processor.onNext(evt);
        }
    }
doAppend方法先判断是否需要DENY,是则直接返回,之后主要执行queueLoggingEvent,它在delegate不为null时执行processor.onNext(evt)

LifeCycle.start

public void start() {
        startDelegateAppender();
        processor = WorkQueueProcessor.<ILoggingEvent>builder().name("logger")
                                                               .bufferSize(backlog)
                                                               .autoCancel(false)
                                                               .build();
        processor.subscribe(this);
    }
    private void startDelegateAppender() {
        Appender<ILoggingEvent> delegateAppender = delegate.get();
        if (null != delegateAppender && !delegateAppender.isStarted()) {
            delegateAppender.start();
        }
    }
    public void addAppender(Appender<ILoggingEvent> newAppender) {
        if (delegate.compareAndSet(null, newAppender)) {
            aai.addAppender(newAppender);
        }
        else {
            throw new IllegalArgumentException(delegate.get() + " already attached.");
        }
    }
start方法执行startDelegateAppender,然后创建WorkQueueProcessor(默认bufferSize为1024 * 1024),并subscribe当前实例;addAppender方法会设置delegate,并往AppenderAttachableImpl添加appender

stop

public void stop() {
        processor.onComplete();
    }
stop方法执行processor.onComplete()

小结

reactor-logback基于WorkQueueProcessor提供了另外一种AsyncAppender,它不是基于BlockingQueue而是基于RingBuffer来实现的。其onSubscribe方法执行doStart,标记started为true,同时触发s.request(Long.MAX_VALUE);onNext调用AppenderAttachableImpl的appendLoopOnAppenders方法;onComplete则执行doStop、appender.stop()、aai.detachAndStopAllAppenders(),最后标记started为false;doAppend方法先判断是否需要DENY,是则直接返回,之后主要执行queueLoggingEvent,它在delegate不为null时执行processor.onNext(evt)。

以上就是reactor-logback的AsyncAppender执行流程源码解读的详细内容,更多关于reactor-logback AsyncAppender的资料请关注脚本之家其它相关文章!

相关文章

  • java中的接口能够被实例化吗

    java中的接口能够被实例化吗

    这篇文章主要介绍了java中的接口能够被实例化吗,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • 如何修改JSON字符串中的敏感信息

    如何修改JSON字符串中的敏感信息

    这篇文章主要介绍了如何修改JSON字符串中的敏感信息,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • SpringBoot日程管理Quartz与定时任务Task实现详解

    SpringBoot日程管理Quartz与定时任务Task实现详解

    定时任务是企业级开发中必不可少的组成部分,诸如长周期业务数据的计算,例如年度报表,诸如系统脏数据的处理,再比如系统性能监控报告,还有抢购类活动的商品上架,这些都离不开定时任务。本节将介绍两种不同的定时任务技术
    2022-09-09
  • MyBatis整合Redis实现二级缓存的示例代码

    MyBatis整合Redis实现二级缓存的示例代码

    这篇文章主要介绍了MyBatis整合Redis实现二级缓存的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • TreeSet判断重复元素解析及代码示例

    TreeSet判断重复元素解析及代码示例

    这篇文章主要介绍了TreeSet判断重复元素解析及代码示例,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • java中的内部类详细总结

    java中的内部类详细总结

    内部类不是很好理解,但说白了其实也就是一个类中还包含着另外一个类。如同一个人是由大脑、肢体、器官等身体结果组成,而内部类相当于其中的某个器官之一,例如心脏:它也有自己的属性和行为(血液、跳动)
    2013-10-10
  • Springmvc加ajax实现上传文件并页面局部刷新

    Springmvc加ajax实现上传文件并页面局部刷新

    这篇文章主要介绍了Springmvc加ajax实现上传文件并页面局部刷新,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • java在cmd中乱码的问题解决

    java在cmd中乱码的问题解决

    本文深入探讨了在使用Java命令行cmd时可能出现的中文乱码问题,并提供了两种解决方案,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-03-03
  • mybatis简介与配置_动力节点Java学院整理

    mybatis简介与配置_动力节点Java学院整理

    这篇文章主要介绍了mybatis简介与配置,介绍了MyBatis+Spring+MySql简单配置,有兴趣的可以了解一下
    2017-09-09
  • Java文件管理操作的知识点整理

    Java文件管理操作的知识点整理

    这篇文章主要为大家详细介绍了Java中文件管理操作的一些知识点和实现方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-09-09

最新评论