当前位置: 首页 > news >正文

聊聊rocketmq的FileAppender

为什么80%的码农都做不了架构师?>>>   hot3.png

本文主要研究一下rocketmq的FileAppender

WriterAppender

org/apache/rocketmq/logging/inner/LoggingBuilder.java

   public static class WriterAppender extends Appender {


        protected boolean immediateFlush = true;

        protected String encoding;


        protected QuietWriter qw;

        public WriterAppender() {

        }

        public void setImmediateFlush(boolean value) {
            immediateFlush = value;
        }


        public boolean getImmediateFlush() {
            return immediateFlush;
        }

        public void activateOptions() {
        }


        public void append(LoggingEvent event) {
            if (!checkEntryConditions()) {
                return;
            }
            subAppend(event);
        }

        protected boolean checkEntryConditions() {
            if (this.closed) {
                SysLogger.warn("Not allowed to write to a closed appender.");
                return false;
            }

            if (this.qw == null) {
                handleError("No output stream or file set for the appender named [" +
                    name + "].");
                return false;
            }

            if (this.layout == null) {
                handleError("No layout set for the appender named [" + name + "].");
                return false;
            }
            return true;
        }

        public synchronized void close() {
            if (this.closed) {
                return;
            }
            this.closed = true;
            writeFooter();
            reset();
        }

        protected void closeWriter() {
            if (qw != null) {
                try {
                    qw.close();
                } catch (IOException e) {
                    handleError("Could not close " + qw, e, CODE_CLOSE_FAILURE);
                }
            }
        }

        protected OutputStreamWriter createWriter(OutputStream os) {
            OutputStreamWriter retval = null;

            String enc = getEncoding();
            if (enc != null) {
                try {
                    retval = new OutputStreamWriter(os, enc);
                } catch (IOException e) {
                    SysLogger.warn("Error initializing output writer.");
                    SysLogger.warn("Unsupported encoding?");
                }
            }
            if (retval == null) {
                retval = new OutputStreamWriter(os);
            }
            return retval;
        }

        public String getEncoding() {
            return encoding;
        }

        public void setEncoding(String value) {
            encoding = value;
        }


        public synchronized void setWriter(Writer writer) {
            reset();
            this.qw = new QuietWriter(writer, this);
            writeHeader();
        }

        protected void subAppend(LoggingEvent event) {
            this.qw.write(this.layout.format(event));

            if (layout.ignoresThrowable()) {
                String[] s = event.getThrowableStr();
                if (s != null) {
                    for (String s1 : s) {
                        this.qw.write(s1);
                        this.qw.write(LINE_SEP);
                    }
                }
            }

            if (shouldFlush(event)) {
                this.qw.flush();
            }
        }

        protected void reset() {
            closeWriter();
            this.qw = null;
        }

        protected void writeFooter() {
            if (layout != null) {
                String f = layout.getFooter();
                if (f != null && this.qw != null) {
                    this.qw.write(f);
                    this.qw.flush();
                }
            }
        }

        protected void writeHeader() {
            if (layout != null) {
                String h = layout.getHeader();
                if (h != null && this.qw != null) {
                    this.qw.write(h);
                }
            }
        }

        protected boolean shouldFlush(final LoggingEvent event) {
            return event != null && immediateFlush;
        }
    }
  • 这个接口定义了writeHeader、writeFooter、append等方法
  • append方法这里参数是LoggingEvent,内部委托给subAppend
  • subAppend方法调用layout进行格式化event,然后如果需要flush,则会直接对qw进行flush

FileAppender

org/apache/rocketmq/logging/inner/LoggingBuilder.java

  public static class FileAppender extends WriterAppender {

        protected boolean fileAppend = true;

        protected String fileName = null;

        protected boolean bufferedIO = false;

        protected int bufferSize = 8 * 1024;

        public FileAppender() {
        }

        public FileAppender(Layout layout, String filename, boolean append)
            throws IOException {
            this.layout = layout;
            this.setFile(filename, append, false, bufferSize);
        }

        public void setFile(String file) {
            fileName = file.trim();
        }

        public boolean getAppend() {
            return fileAppend;
        }

        public String getFile() {
            return fileName;
        }

        public void activateOptions() {
            if (fileName != null) {
                try {
                    setFile(fileName, fileAppend, bufferedIO, bufferSize);
                } catch (IOException e) {
                    handleError("setFile(" + fileName + "," + fileAppend + ") call failed.",
                        e, CODE_FILE_OPEN_FAILURE);
                }
            } else {
                SysLogger.warn("File option not set for appender [" + name + "].");
                SysLogger.warn("Are you using FileAppender instead of ConsoleAppender?");
            }
        }

        protected void closeFile() {
            if (this.qw != null) {
                try {
                    this.qw.close();
                } catch (IOException e) {
                    if (e instanceof InterruptedIOException) {
                        Thread.currentThread().interrupt();
                    }
                    SysLogger.error("Could not close " + qw, e);
                }
            }
        }

        public boolean getBufferedIO() {
            return this.bufferedIO;
        }

        public int getBufferSize() {
            return this.bufferSize;
        }

        public void setAppend(boolean flag) {
            fileAppend = flag;
        }

        public void setBufferedIO(boolean bufferedIO) {
            this.bufferedIO = bufferedIO;
            if (bufferedIO) {
                immediateFlush = false;
            }
        }

        public void setBufferSize(int bufferSize) {
            this.bufferSize = bufferSize;
        }

        public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
            throws IOException {
            SysLogger.debug("setFile called: " + fileName + ", " + append);

            if (bufferedIO) {
                setImmediateFlush(false);
            }

            reset();
            FileOutputStream ostream;
            try {
                ostream = new FileOutputStream(fileName, append);
            } catch (FileNotFoundException ex) {
                String parentName = new File(fileName).getParent();
                if (parentName != null) {
                    File parentDir = new File(parentName);
                    if (!parentDir.exists() && parentDir.mkdirs()) {
                        ostream = new FileOutputStream(fileName, append);
                    } else {
                        throw ex;
                    }
                } else {
                    throw ex;
                }
            }
            Writer fw = createWriter(ostream);
            if (bufferedIO) {
                fw = new BufferedWriter(fw, bufferSize);
            }
            this.setQWForFiles(fw);
            this.fileName = fileName;
            this.fileAppend = append;
            this.bufferedIO = bufferedIO;
            this.bufferSize = bufferSize;
            writeHeader();
            SysLogger.debug("setFile ended");
        }

        protected void setQWForFiles(Writer writer) {
            this.qw = new QuietWriter(writer, this);
        }

        protected void reset() {
            closeFile();
            this.fileName = null;
            super.reset();
        }
    }
  • 写文件,这里定义了bufferSize为8 * 1024,如果开启bufferedIO,则创建的是BufferedWriter
  • setQWForFiles方法根据指定的writer创建了QuietWriter
  • setFile方法设置了qw之后,就直接writeHeader

QuietWriter

org/apache/rocketmq/logging/inner/LoggingBuilder.java

    private static class QuietWriter extends FilterWriter {

        protected Appender appender;

        public QuietWriter(Writer writer, Appender appender) {
            super(writer);
            this.appender = appender;
        }

        public void write(String string) {
            if (string != null) {
                try {
                    out.write(string);
                } catch (Exception e) {
                    appender.handleError("Failed to write [" + string + "].", e,
                        Appender.CODE_WRITE_FAILURE);
                }
            }
        }

        public void flush() {
            try {
                out.flush();
            } catch (Exception e) {
                appender.handleError("Failed to flush writer,", e,
                    Appender.CODE_FLUSH_FAILURE);
            }
        }
    }
  • QuietWriter继承自jdk的FilterWriter,实现了write(String)方法,重写了flush方法
  • FilterWriter实现了write(int c),write(char cbuf[], int off, int len),write(String str, int off, int len)方法,用于对字符串进行过滤

小结

rocketmq的FileAppender继承自WriterAppender,采取的是根据layout对LoggingEvent来格式化,然后写入QuietWriter,最后写入到文件。

doc

  • LoggingBuilder

转载于:https://my.oschina.net/go4it/blog/1924900

相关文章:

  • JS高级
  • MongoDB4.0构建分布式分片群集
  • (六)Hibernate的二级缓存
  • 用 PreparedStatement 向 SqlServer 中一次性插入多条记录
  • redis的高级特性
  • 新版ExTiX 诞生,基于 Ubuntu 的桌面 Linux 发行
  • 移动端测试===从安卓手机截图到桌面的几行代码
  • redis系列:通过日志案例学习string命令
  • Go 与 Scala
  • 互联网健康教育品牌百诺名医汇获深圳汇投资本3000万元Pre-A轮融资
  • 教你快速入门ES6
  • tranform知多少
  • Android酷炫实用的开源框架(UI框架)
  • Binder总结篇1-Binder原理
  • malloc()函数(Linux程序员手册)及函数的正确使用【转】
  • ESLint简单操作
  • Git 使用集
  • HTML5新特性总结
  • input实现文字超出省略号功能
  • Intervention/image 图片处理扩展包的安装和使用
  • Js基础知识(四) - js运行原理与机制
  • node 版本过低
  • OSS Web直传 (文件图片)
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • swift基础之_对象 实例方法 对象方法。
  • Webpack 4 学习01(基础配置)
  • webpack4 一点通
  • 阿里云应用高可用服务公测发布
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 关于Flux,Vuex,Redux的思考
  • 基于MaxCompute打造轻盈的人人车移动端数据平台
  • 七牛云假注销小指南
  • 前端工程化(Gulp、Webpack)-webpack
  • 入口文件开始,分析Vue源码实现
  • 湖北分布式智能数据采集方法有哪些?
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ​油烟净化器电源安全,保障健康餐饮生活
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • #WEB前端(HTML属性)
  • #数学建模# 线性规划问题的Matlab求解
  • (4.10~4.16)
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (算法)前K大的和
  • (原創) 如何優化ThinkPad X61開機速度? (NB) (ThinkPad) (X61) (OS) (Windows)
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .bat批处理(一):@echo off
  • .NET Core 通过 Ef Core 操作 Mysql
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET 事件模型教程(二)
  • .net6使用Sejil可视化日志
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • @font-face 用字体画图标