Log4J2 2.11.0 -> Log4J2 2.17.1 升级 - percona 5.7 的 mariaDB JDBC 驱动程序的 appender 损坏 - 格式错误的数据包 - maven - 已解决

Log4J2 2.11.0 -> Log4J2 2.17.1 upgrade - appender broken for mariaDB JDBC driver to Percona 5.7 - malformed packets - maven - solved

我正在尝试按照上面的详细说明进行升级。从 Log4J 2.11.0 到 2.17.1 完全破坏了我的运行时 Log4J 数据库附加程序设置,在尝试将日志条目写入 Percona 5.7 / MySQL 5.7.[=18 时破坏了底层 MariaDB JDBC 驱动程序=]

2.11.0 运行良好并且已经在这个应用程序中运行了非常非常长的时间。

正在尝试通过 MariaDB JDBC 驱动程序登录到 Percona 5.7 (MySQL 5.7)。

将我的 pom.xml 从

更改为 Log4J2
       <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.11.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.11.0</version>
        </dependency>

       <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.17.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.17.1</version>
        </dependency>

我的 log4j2.xml(在 2.11.0 上工作正常 - 是否必须针对 2.17.1 进行更改?):

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %c{1} - %m %n" />
        </Console> 
        <File name="MyFile" fileName="my.log" immediateFlush="true" append="true">
            <PatternLayout pattern=" %d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %c{1} - %m %n"/>
        </File>
        <JDBC name="MyDB" tableName="db.log">
            <ConnectionFactory class="log4J2.utils.Log4J2GetConnection" method="getDatabaseConnection"/>
            <Column name="DATED" isEventTimestamp="true" isUnicode="false"/>            
            <Column name="LOGGER" pattern="%logger" isUnicode="false"/>
            <Column name="LEVEL" pattern="%level" isUnicode="false"/>
            <Column name="MESSAGE" pattern="%message" isUnicode="false"/>
            <Column name="THROWABLE" pattern="%ex{full}" isUnicode="false" />
        </JDBC>                       
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
            <!--<AppenderRef ref="MyFile"/>-->
            <AppenderRef ref="MyDB"/>
        </Root>
    </Loggers>
</Configuration>

我的连接工厂:

package log4J2.utils;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;
import AppSettings;

/**
 *
 * @author sv
 */
public class Log4J2GetConnection {

    private static interface Singleton {

        final Log4J2GetConnection INSTANCE = new Log4J2GetConnection();
    }

    private final DataSource dataSource;

    private Log4J2GetConnection() {
        if (AppSettings.getMySQLDataSource() == null) {
            AppSettings.resetMySQLDataSource();
        }

        Properties properties = new Properties();
        properties.setProperty("user", AppSettings.getMysqlUser());
        properties.setProperty("password", AppSettings.getMysqlPassword());

        String connectionString = "jdbc:mariadb://" + AppSettings.getMysqlServer() + ":" + AppSettings.getMysqlPort() + "/" + AppSettings.getMysqlDatabase();

        GenericObjectPool pool = new GenericObjectPool();
        DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(connectionString, properties);
        new PoolableConnectionFactory(connectionFactory, pool, null, "SELECT 1", 3, false, false, Connection.TRANSACTION_READ_COMMITTED);

        this.dataSource = new PoolingDataSource(pool);
    }

    public static Connection getDatabaseConnection() throws SQLException {
        return Singleton.INSTANCE.dataSource.getConnection();
    }
}

重新编译正常。

每当我现在尝试在 2.17.1 下创建日志条目时,我都会收到如下详述的异常。 2.11.0 不会发生,只有 2.17.1:

2022-01-18 10:16:31,243 main ERROR Unable to write to database [JdbcManager{name=MyDB, bufferSize=0, tableName=db.log, columnConfigs=[{ name=DATED, layout=null, literal=null, timestamp=true }, { name=LOGGER, layout=%logger, literal=null, timestamp=false }, { name=LEVEL, layout=%level, literal=null, timestamp=false }, { name=MESSAGE, layout=%message, literal=null, timestamp=false }, { name=THROWABLE, layout=%ex{full}, literal=null, timestamp=false }], columnMappings=[]}] for appender [MyDB]. org.apache.logging.log4j.core.appender.db.DbAppenderLoggingException: Failed to insert record for log event in JDBC manager: java.sql.SQLException: Malformed communication packet. [columnConfigs=[{ name=DATED, layout=null, literal=null, timestamp=true }, { name=LOGGER, layout=%logger, literal=null, timestamp=false }, { name=LEVEL, layout=%level, literal=null, timestamp=false }, { name=MESSAGE, layout=%message, literal=null, timestamp=false }, { name=THROWABLE, layout=%ex{full}, literal=null, timestamp=false }], sqlStatement=insert into asteriskcdrdb.application_log (DATED,LOGGER,LEVEL,MESSAGE,THROWABLE) values (?,?,?,?,?), factoryData=FactoryData [connectionSource=factory{ public static java.sql.Connection log4J2.utils.Log4J2GetConnection.getDatabaseConnection() }, tableName=asteriskcdrdb.application_log, columnConfigs=[{ name=DATED, layout=null, literal=null, timestamp=true }, { name=LOGGER, layout=%logger, literal=null, timestamp=false }, { name=LEVEL, layout=%level, literal=null, timestamp=false }, { name=MESSAGE, layout=%message, literal=null, timestamp=false }, { name=THROWABLE, layout=%ex{full}, literal=null, timestamp=false }], columnMappings=[], immediateFail=false, retry=true, reconnectIntervalMillis=5000, truncateStrings=true], connection=jdbc:mysql://172.16.1.13:3306/asteriskcdrdb, UserName=asteriskcdruser, mariadb-jdbc, statement=sql : 'insert into asteriskcdrdb.application_log (DATED,LOGGER,LEVEL,MESSAGE,THROWABLE) values (?,?,?,?,?)', parameters : ['2022-01-18 10:15:59.319','webServer.WebHost','INFO','1iemp3w272hi - WebHost class - Starting jetty...',''], reconnector=null, isBatchSupported=true, columnMetaData={MESSAGE=ColumnMetaData [schemaName=, catalogName=asteriskcdrdb, tableName=application_log, name=MESSAGE, nameKey=MESSAGE, label=MESSAGE, displaySize=65535, type=12, typeName=VARCHAR, className=java.lang.String, precision=196605, scale=0, isStringType=true], LOGGER=ColumnMetaData [schemaName=, catalogName=asteriskcdrdb, tableName=application_log, name=LOGGER, nameKey=LOGGER, label=LOGGER, displaySize=255, type=12, typeName=VARCHAR, className=java.lang.String, precision=765, scale=0, isStringType=true], DATED=ColumnMetaData [schemaName=, catalogName=asteriskcdrdb, tableName=application_log, name=DATED, nameKey=DATED, label=DATED, displaySize=19, type=93, typeName=DATETIME, className=java.sql.Timestamp, precision=19, scale=0, isStringType=false], LEVEL=ColumnMetaData [schemaName=, catalogName=asteriskcdrdb, tableName=application_log, name=LEVEL, nameKey=LEVEL, label=LEVEL, displaySize=10, type=12, typeName=VARCHAR, className=java.lang.String, precision=30, scale=0, isStringType=true], THROWABLE=ColumnMetaData [schemaName=, catalogName=asteriskcdrdb, tableName=application_log, name=THROWABLE, nameKey=THROWABLE, label=THROWABLE, displaySize=65535, type=12, typeName=VARCHAR, className=java.lang.String, precision=196605, scale=0, isStringType=true]}]
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.writeInternal(JdbcDatabaseManager.java:871)
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.writeThrough(JdbcDatabaseManager.java:898)
    at org.apache.logging.log4j.core.appender.db.AbstractDatabaseManager.write(AbstractDatabaseManager.java:264)
    at org.apache.logging.log4j.core.appender.db.AbstractDatabaseAppender.append(AbstractDatabaseAppender.java:110)
    at org.apache.logging.log4j.core.config.AppenderControl.tryCallAppender(AppenderControl.java:161)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender0(AppenderControl.java:134)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppenderPreventRecursion(AppenderControl.java:125)
    at org.apache.logging.log4j.core.config.AppenderControl.callAppender(AppenderControl.java:89)
    at org.apache.logging.log4j.core.config.LoggerConfig.callAppenders(LoggerConfig.java:542)
    at org.apache.logging.log4j.core.config.LoggerConfig.processLogEvent(LoggerConfig.java:500)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:483)
    at org.apache.logging.log4j.core.config.LoggerConfig.log(LoggerConfig.java:417)
    at org.apache.logging.log4j.core.config.AwaitCompletionReliabilityStrategy.log(AwaitCompletionReliabilityStrategy.java:82)
    at org.apache.logging.log4j.core.Logger.log(Logger.java:161)
    at org.apache.logging.log4j.spi.AbstractLogger.tryLogMessage(AbstractLogger.java:2205)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageTrackRecursion(AbstractLogger.java:2159)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessageSafely(AbstractLogger.java:2142)
    at org.apache.logging.log4j.spi.AbstractLogger.logMessage(AbstractLogger.java:2017)
    at org.apache.logging.log4j.spi.AbstractLogger.logIfEnabled(AbstractLogger.java:1983)
    at org.apache.logging.log4j.spi.AbstractLogger.info(AbstractLogger.java:1320)
    at webServer.WebHost.<init>(WebHost.java:58)
    at App.main(App.java:255)
Caused by: java.sql.SQLException: Malformed communication packet.
    at org.mariadb.jdbc.internal.SQLExceptionMapper.get(SQLExceptionMapper.java:149)
    at org.mariadb.jdbc.internal.SQLExceptionMapper.throwException(SQLExceptionMapper.java:106)
    at org.mariadb.jdbc.MySQLStatement.executeQueryEpilog(MySQLStatement.java:268)
    at org.mariadb.jdbc.MySQLStatement.execute(MySQLStatement.java:296)
    at org.mariadb.jdbc.MySQLStatement.executeUpdate(MySQLStatement.java:325)
    at org.mariadb.jdbc.MySQLPreparedStatement.executeUpdate(MySQLPreparedStatement.java:159)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
    at org.apache.logging.log4j.core.appender.db.jdbc.JdbcDatabaseManager.writeInternal(JdbcDatabaseManager.java:862)
    ... 21 more
Caused by: org.mariadb.jdbc.internal.common.QueryException: Malformed communication packet.
    at org.mariadb.jdbc.internal.mysql.MySQLProtocol.getResult(MySQLProtocol.java:982)
    at org.mariadb.jdbc.internal.mysql.MySQLProtocol.executeQuery(MySQLProtocol.java:1042)
    at org.mariadb.jdbc.MySQLStatement.execute(MySQLStatement.java:289)
    ... 26 more

我的 MariaDB JDBC 我的神器 pom.xml:

        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
            <version>1.1.8</version>
        </dependency>

E. G。 Percona 5.7 中 Log4J 2.17.1 版的所有日志记录尝试均失败,并在

的 MariaDB JDBC 驱动程序中出现错误
org.apache.logging.log4j.core.appender.db.DbAppenderLoggingException: Failed to insert record for log event in JDBC manager: java.sql.SQLException: Malformed communication packet.

当我在 pom.xml 中切换回 Log4J 2.11.0 时,MariaDB JDBC 驱动程序向 Percona 5.7 发出的通信数据包不再被视为“格式错误”。

Log4J 2.17.1 以某种方式影响 MariaDB JDBC 驱动程序 1.1.8,以至于我的 Percona 5.7 实例拒绝它从 JDBC 接收的所有 SQL 通信数据包驱动程序,如果所述 SQL 插入查询的来源是 Log4J 2.17.1... WTF

如果 SQL 查询的来源不再是 Log4J 2.17.1 而是 2.11.0,根据 Percona 5.7,通信包不再是格式错误的并且它愉快地执行通过来自 Log4J 2.11.0.

的 MariaDB JDBC 驱动程序

关于如何解决此问题的任何指示?

谢谢!

斯蒂芬

上面post的解决办法好像是先把MariaDB JDBC Java客户端更新到当前的稳定版。在 Maven 的 pom.xml 中:

        <dependency>
            <groupId>org.mariadb.jdbc</groupId>
            <artifactId>mariadb-java-client</artifactId>
            <!--<version>1.1.8</version>-->
            <version>2.7.4</version>
        </dependency>

MariaDB-java-客户端的 2.7.4 截至 2022 年 1 月 18 日是稳定的。

然后添加 commons-dbcp 版本 1.4 以允许我的连接工厂代码正常工作。在 pom.xml:

        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
            <type>jar</type>
        </dependency>

然后最后把log4j 2.11.0 升级到2.17.1。在 pom.xml:

        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <!--<version>2.11.0</version>-->
            <version>2.17.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <!--<version>2.11.0</version>-->
            <version>2.17.1</version>
        </dependency>

完成以上操作后异常

db.DbAppenderLoggingException: Failed to insert record for log event in JDBC manager: java.sql.SQLException: Malformed communication packet.

消失了,Log4J 2.17.1 现在通过 MariaDb Java 客户端 2.7.4 和 commons-dbcp 1.4 成功登录到 Percona (MySQL) 5.7 以创建上述 Log4J 连接工厂代码工作。

--

编辑:这是一个替代连接工厂class,用于使用 Apache DBCP2 而不是 DBCP1 通过 MariaDB Java 客户端 2.7.4 到 Percona 5.7 获取 Log4J2 的连接:

package verishare.log4J2.utils;

import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.PoolableConnection;
import org.apache.commons.pool2.ObjectPool;
import AppSettings;

/**
 *
 * @author sv
 */
public class Log4J2GetConnection {

    private static interface Singleton {

        final Log4J2GetConnection INSTANCE = new Log4J2GetConnection();
    }

    private final DataSource dataSource;

    private Log4J2GetConnection() {
        if (AppSettings.getMySQLDataSource() == null) {
            AppSettings.resetMySQLDataSource();
        }

        String connectionString = "jdbc:mariadb://" + AppSettings.getMysqlServer() + ":" + AppSettings.getMysqlPort() + "/" + AppSettings.getMysqlDatabase();

        org.apache.commons.dbcp2.PoolingDataSource<PoolableConnection> workDataSource = null;

        try {
            org.apache.commons.dbcp2.ConnectionFactory factory = new org.apache.commons.dbcp2.DriverManagerConnectionFactory(connectionString,
                    AppSettings.getMysqlUser(), AppSettings.getMysqlPassword());
            org.apache.commons.dbcp2.PoolableConnectionFactory poolFactory = new org.apache.commons.dbcp2.PoolableConnectionFactory(factory, null);
            ObjectPool<PoolableConnection> connectionPool = new org.apache.commons.pool2.impl.GenericObjectPool<>(poolFactory);
            poolFactory.setPool(connectionPool);
            workDataSource = new org.apache.commons.dbcp2.PoolingDataSource<>(connectionPool);
        } catch (Exception ex) {
            System.out.println(("Exception in getPoolForConnection:" + ex.toString()));
        } finally {
            this.dataSource = workDataSource;
        }
    }

    public static Connection getDatabaseConnection() throws SQLException {
        return Singleton.INSTANCE.dataSource.getConnection();
    }
}

仅供参考,Log4J 漏洞从 2.12.0

开始