logback dbappender非常慢

时间:2018-03-08 23:02:07

标签: performance logback

我有一个自定义DB Appender,它扩展了logback DBAppender。我的应用程序有100个并行线程。这些线程还在处理请求时通过自定义db appender将事件记录到数据库中。

日志记录的性能非常慢,如果禁用日志,则执行将在20分钟内完成。在启用日志的情况下,由于我的日志记录是同步的,因此大部分时间都需要花费大约5个小时来等待写入日志以继续下一步。

起初我认为性能缓慢可能是由于logback appender的同步doAppend方法。但是,后来我注意到DB appender扩展了

UnsynchronizedAppenderBase(public abstract class DBAppenderBase<E> /* */ extends UnsynchronizedAppenderBase<E>).

任何人都可以帮助我理解这种糟糕表现的原因是什么?

我的数据库附加器:

package com.test;

import java.io.StringReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import org.omg.CORBA.TRANSACTION_UNAVAILABLE;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.db.DBAppender;
import ch.qos.logback.classic.spi.ILoggingEvent;

public class CustomDBAppender extends DBAppender {

    final static Logger logger = LoggerFactory.getLogger("com.test");

    protected String insertPropertiesSQL;
    protected String insertExceptionSQL;
    protected String insertSQL;

    private CustomDBNameResolver dbNameResolver;

    // default constructor
    public CustomDBAppender() {
        logger.debug("DB Appender instantiated");
    }

    // set dbNameResolver for getting table information
    public void setCsiDbNameResolver(CustomDBNameResolver dbNameResolver) {
        this.dbNameResolver = dbNameResolver;
    }

    @Override
    public void start() {

        super.start();
        if (dbNameResolver == null)
            dbNameResolver = new CustomDBNameResolver();
        insertSQL = CustomSQLBuilder.buildInsertSQL(dbNameResolver);

    }

    @Override
    protected void subAppend(ILoggingEvent event, Connection connection, PreparedStatement insertStatement)
            throws Throwable {

        logEvents(insertStatement, event);
        // System.out.println("=== INSERT STATEMENT === " +
        // insertStatement.toString());

        int updateCount = -1;
        try {
            updateCount = insertStatement.executeUpdate();
        } catch (Exception e) {
            logger.error(" ERROR   ");
            e.printStackTrace();
        }

        logger.info(" updateCount = " + updateCount);

        if (updateCount != 1) {
            logger.error(" ERROR  IT IS ");
            addWarn("Failed to insert loggingEvent");
        }
    }

    protected void secondarySubAppend(ILoggingEvent event, Connection connection, long eventId) throws Throwable {

    }

    // @override
    private void logEvents(PreparedStatement stmt, ILoggingEvent event) throws SQLException {

        logData(event, stmt);

    }

    private void logData(ILoggingEvent event, PreparedStatement stmt) throws SQLException {

        try {

            if (null != event && null != logMsgArgs && (event.getLoggerName().indexOf("com.test.beans.") != -1)) {
                payload = null == logMsgArgs[0] ? "NA"
                        : (logMsgArgs[0].toString()).substring(0,
                                (logMsgArgs[0].toString().length() >= 4000 ? 3999 : logMsgArgs[0].toString().length()));
                msgHeader = null == logMsgArgs[1] ? "NA"
                        : (logMsgArgs[1].toString()).substring(0,
                                (logMsgArgs[1].toString().length() >= 4000 ? 3999 : logMsgArgs[1].toString().length()));
                currentStage = null == logMsgArgs[2] ? -1 : Integer.parseInt(logMsgArgs[2].toString());
                currentEvent = null == logMsgArgs[3] ? null : logMsgArgs[3].toString();
                trxId = null == logMsgArgs[4] ? null : logMsgArgs[4].toString();
                batchId = null == logMsgArgs[5] ? null : logMsgArgs[5].toString();
                headerId = null == logMsgArgs[6] ? null : logMsgArgs[6].toString();
            }

            stmt.setString(1, logLevel);
            stmt.setObject(2, trxId);
            stmt.setString(3, logMessage);
            stmt.setDate(4, getSqlDate());
            stmt.setString(5, event.getLoggerName());
            stmt.setString(6, event.getThreadName());
            stmt.setString(7, event.getLoggerContextVO().getName());
            stmt.setString(8, logMessage.substring(0, logMessageLength));
            stmt.setString(9, payload);
            stmt.setString(10, msgHeader);
            stmt.setInt(11, currentStage);
            stmt.setString(12, currentEvent);
            stmt.setString(13, batchId);
            stmt.setString(14, headerId);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            System.out.println("Exception while printing log:" + e.getMessage());
            e.printStackTrace();
        } finally {

        }

    }

    private Object nvl(Object input) {
        if (null == input) {
            return null;
        }
        return input;
    }

    private java.sql.Date getSqlDate() {
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSX");
        String nowDateStr = sdf.format(now);
        logger.info("nowDateStr = " + nowDateStr);

        java.sql.Date toDB = null;
        try {
            toDB = new java.sql.Date(sdf.parse(nowDateStr).getTime());
            logger.info("toDB = " + toDB);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return toDB;
    }

    @Override
    protected String getInsertSQL() {
        return insertSQL;
    }

    protected void insertProperties(Map<String, String> mergedMap, Connection connection, long eventId)
            throws SQLException {

    }
}

/ * appender结束* /

0 个答案:

没有答案