在互联网设计架构过程中,日志异步落库,俨然已经是高并发环节中不可缺少的一环。为什么说是高并发环节中不可缺少的呢? 原因在于,如果直接用mq进行日志落库的时候,低并发下,生产端生产数据,然后由消费端异步落库,是没有什么问题的,而且性能也都是异常的好,估计tp99应该都在1ms以内。但是一旦并发增长起来,慢慢的你就发现生产端的tp99一直在增长,从1ms,变为2ms,4ms,直至send timeout。尤其在大促的时候,我司的系统就经历过这个情况,当时mq的发送耗时超过200ms,甚至一度有不少timeout产生。
考虑到这种情况在高并发的情况下才出现,所以今天我们就来探索更加可靠的方法来进行异步日志落库,保证所使用的方式不会因为过高的并发而出现接口ops持续下降甚至到不可用的情况。
方案一: 基于log4j的异步appender实现
此种方案,依赖于log4j。在log4j的异步appender中,通过mq进行生产消费入库。相当于在接口和mq之间建立了一个缓冲区,使得接口和mq的依赖分离,从而不让mq的操作影响接口的ops。
此种方案由于使用了异步方式,且由于异步的discard policy策略,当大量数据过来,缓冲区满了之后,会抛弃部分数据。此种方案适用于能够容忍数据丢失的业务场景,不适用于对数据完整有严格要求的业务场景。
来看看具体的实现方式:
首先,我们需要自定义一个Appender,继承自log4j的AppenderSkeleton类,实现方式如下:
public class AsyncJmqAppender extends AppenderSkeleton { @Resource(name = "messageProducer") private MessageProducer messageProducer; @Override protected void append(LoggingEvent loggingEvent) { asyncPushMessage(loggingEvent.getMessage()); } /** * 异步调用jmq输出日志 * @param message */ private void asyncPushMessage(Object message) { CompletableFuture.runAsync(() -> { Message messageConverted = (Message) message; try { messageProducer.send(messageConverted); } catch (JMQException e) { e.printStackTrace(); } }); } @Override public boolean requiresLayout() { return false; } @Override public void close() { } }然后在log4j.xml中,为此类进行配置:
<!--异步JMQ appender--><appender name="async_mq_appender" class="com.jd.limitbuy.common.util.AsyncJmqAppender"> <!-- 设置File参数:日志输出文件名 --> <param name="File" value="D:/export/Instances/order/server1/logs/order.async.jmq" /> <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 --> <param name="Append" value="true" /> <!-- 设置文件大小 --> <param name="MaxFileSize" value="10KB" /> <!-- 设置文件备份 --> <param name="MaxBackupIndex" value="10000" /> <!-- 设置输出文件项目和格式 --> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%m%n" /> </layout></appender><logger name="async_mq_appender_logger"> <appender-ref ref="async_mq_appender"/></logger>最后就可以按照如下的方式进行正常使用了:
private static Logger logger = LoggerFactory.getLogger("filelog_appender_logger");郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。