分布式日志治理:Log4j2自定義Appender寫日志到RocketMQ

🧑 博主簡介:CSDN博客專家歷代文學網(PC端可以訪問:https://literature.sinhy.com/#/?__c=1000,移動端可微信小程序搜索“歷代文學”)總架構師,15年工作經驗,精通Java編程高并發設計Springboot和微服務,熟悉LinuxESXI虛擬化以及云原生Docker和K8s,熱衷于探索科技的邊界,并將理論知識轉化為實際應用。保持對新技術的好奇心,樂于分享所學,希望通過我的實踐經歷和見解,啟發他人的創新思維。在這里,我希望能與志同道合的朋友交流探討,共同進步,一起在技術的世界里不斷學習成長。
技術合作請加本人wx(注明來自csdn):foreast_sea

在這里插入圖片描述

在這里插入圖片描述


文章目錄

  • Log4j2自定義Appender寫日志到RocketMQ
      • 引言:分布式系統下的日志治理新范式——基于Log4j2與RocketMQ的高效實踐
      • 1. 添加Maven依賴
      • 2. 實現自定義Appender
      • 3. 配置log4j2.xml
      • 4. 關鍵點說明
      • 5. 注意事項

Log4j2自定義Appender寫日志到RocketMQ

引言:分布式系統下的日志治理新范式——基于Log4j2與RocketMQ的高效實踐

在云原生與微服務架構大行其道的今天,日志管理已從簡單的本地文件存儲演化為支撐系統可觀測性的核心支柱。傳統日志處理方式在面對日均TB級的日志量、跨地域服務調用鏈追蹤、實時異常檢測等場景時,往往陷入存儲碎片化、檢索效率低下、處理延遲高的困境。尤其在金融交易、物聯網、在線教育等高并發領域,日志數據不僅是問題排查的"黑匣子",更是業務洞察的"數據金礦",亟需一種能夠兼顧實時性、可靠性和可擴展性的新型日志處理方案。

Apache RocketMQ作為阿里巴巴開源的高性能分布式消息中間件,憑借其毫秒級消息投遞、萬億級消息堆積能力和完善的事務機制,為日志數據的異步化處理提供了理想通道。而Log4j2作為Java生態中最主流的日志框架,其插件化架構和異步日志特性,使得開發者能夠通過自定義Appender將日志生產與傳輸邏輯解耦。二者的結合,不僅實現了日志從"被動記錄"到"主動流轉"的范式升級,更構建起日志采集、傳輸、存儲、分析的全鏈路解決方案。

本文深入探討如何基于Log4j2最新架構擴展日志輸出能力,通過構建自定義RocketMQAppender實現日志數據的實時投遞。該方案突破傳統日志文件的物理邊界,使日志數據可無縫對接ElasticsearchFlinkSpark等大數據處理平臺,為實時監控、安全審計、用戶行為分析等場景提供高時效數據源。

本文從Maven依賴配置、Appender線程模型設計、RocketMQ生產者最佳實踐等維度展開,詳細解析如何在高并發場景下保障日志傳輸的可靠性與性能平衡,并針對消息壓縮、失敗重試、資源監控等關鍵問題給出工程級解決方案。通過此實踐,開發者可將日志系統的吞吐量提升1-2個數量級,同時顯著降低日志丟失風險,為構建企業級可觀測性平臺奠定堅實基礎。

以下是基于Java Log4j2自定義Appender將日志寫入RocketMQ的步驟:

1. 添加Maven依賴

<!-- Log4j2 核心依賴 -->
<dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.23.1</version>
</dependency><!-- RocketMQ客戶端 -->
<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>5.1.4</version>
</dependency>

2. 實現自定義Appender

import org.apache.logging.log4j.core.*;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.config.Property;
import org.apache.logging.log4j.core.config.plugins.*;
import org.apache.rocketmq.client.apis.*;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.ProducerBuilder;
import org.apache.rocketmq.client.apis.producer.SendResult;import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;@Plugin(name = "RocketMQAppender",category = Core.CATEGORY_NAME,elementType = Appender.ELEMENT_TYPE,printObject = true
)
public final class RocketMQAppender extends AbstractAppender {private Producer producer;private final String namesrvAddr;private final String topic;private final String producerGroup;private final int sendTimeout;protected RocketMQAppender(String name, Filter filter, Layout<? extends Serializable> layout,String namesrvAddr, String topic, String producerGroup, int sendTimeout) {super(name, filter, layout, true, Property.EMPTY_ARRAY);this.namesrvAddr = namesrvAddr;this.topic = topic;this.producerGroup = producerGroup;this.sendTimeout = sendTimeout;}@Overridepublic void start() {try {final ClientServiceProvider provider = ClientServiceProvider.loadService();ClientConfigurationBuilder builder = ClientConfiguration.newBuilder().setEndpoints(namesrvAddr);ProducerBuilder producerBuilder = provider.newProducerBuilder().setClientConfiguration(builder.build()).setTopics(topic);if (producerGroup != null) {producerBuilder.setProducerGroup(producerGroup);}producer = producerBuilder.build();} catch (ClientException e) {LOGGER.error("Initialize RocketMQ Producer failed", e);}super.start();}@Overridepublic void append(LogEvent event) {if (producer == null) return;try {byte[] body = getLayout().toByteArray(event);String messageBody = new String(body, StandardCharsets.UTF_8);final ClientServiceProvider provider = ClientServiceProvider.loadService();Message message = provider.newMessageBuilder().setTopic(topic).setBody(body).build();SendResult sendResult = producer.send(message);// 可添加發送結果處理邏輯} catch (Exception e) {LOGGER.error("Send log to RocketMQ failed", e);}}@Overridepublic void stop() {super.stop();if (producer != null) {try {producer.close();} catch (Exception e) {LOGGER.error("Close RocketMQ Producer failed", e);}}}@PluginFactorypublic static RocketMQAppender createAppender(@PluginAttribute("name") String name,@PluginElement("Filter") Filter filter,@PluginElement("Layout") Layout<? extends Serializable> layout,@PluginAttribute("namesrvAddr") String namesrvAddr,@PluginAttribute("topic") String topic,@PluginAttribute(value = "producerGroup", defaultString = "LogProducerGroup") String producerGroup,@PluginAttribute(value = "sendTimeout", defaultInt = 3000) int sendTimeout) {if (name == null) {LOGGER.error("No name provided for RocketMQAppender");return null;}return new RocketMQAppender(name, filter, layout, namesrvAddr, topic, producerGroup, sendTimeout);}
}

3. 配置log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN"><Appenders><RocketMQAppender name="RocketMQ"namesrvAddr="localhost:8081"topic="LOG_TOPIC"producerGroup="LOG_PRODUCER_GROUP"sendTimeout="5000"><PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n"/></RocketMQAppender></Appenders><Loggers><Root level="info"><AppenderRef ref="RocketMQ"/></Root></Loggers>
</Configuration>

4. 關鍵點說明

  1. 線程安全設計

    • RocketMQ Producer是線程安全的,可以復用實例
    • 在start()中初始化,stop()中銷毀
  2. 異常處理

    • 在send方法中添加try-catch防止日志記錄阻塞主線程
    • 建議添加失敗重試機制(示例未展示)
  3. 性能優化建議

    // 可添加批量發送支持
    producer.send(List<Message> messages, SendReceipt sendReceipt);// 或使用異步發送
    CompletableFuture<SendResult> future = producer.sendAsync(message);
    
  4. 擴展功能建議

    • 添加消息Tag支持
    • 支持自定義Key/Value屬性
    • 添加消息壓縮功能
    • 支持同步/異步發送模式切換

5. 注意事項

  1. 版本兼容性

    • RocketMQ 5.x+ 使用新的客戶端API
    • 舊版本(4.x)需要調整客戶端實現
  2. 資源管理

    • 確保Producer在JVM關閉時正確關閉
    • 建議添加發送隊列積壓監控
  3. 安全配置

    // 如果需要認證
    ClientConfigurationBuilder builder = ClientConfiguration.newBuilder().setEndpoints(namesrvAddr).setCredentialProvider(new StaticSessionTokenCredentialProvider("accessKey", "secretKey"));
    
  4. 日志格式化

    • 建議使用JSON格式方便后續處理
    • 可添加TraceID等全鏈路追蹤信息

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/76730.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/76730.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/76730.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【HTML】html文件

HTML文件全解析&#xff1a;搭建網頁的基石 在互聯網的廣袤世界里&#xff0c;每一個絢麗多彩、功能各異的網頁背后&#xff0c;都離不開HTML文件的默默支撐。HTML&#xff0c;即超文本標記語言&#xff08;HyperText Markup Language&#xff09;&#xff0c;作為網頁創建的基…

oracle命令上下左右鍵無法使用如何解決?

1、問題如圖 2、解決辦法 (1) 安裝readline yum -y install readline* &#xff08;2&#xff09;安裝 rlwrap ##下載 wget http://files.cnblogs.com/files/killkill/rlwrap-0.30.tar.gz.zip ##解壓 tar -xzvf rlwrap-0.30.tar.gz.zip ##編譯安裝 ./configure make &&…

vue事假機制都有哪些

Vue 的事件機制主要包含以下幾種類型和方式&#xff0c;可以分為組件內部事件、父子組件通信事件、原生 DOM 事件封裝、修飾符增強等&#xff0c;下面詳細分類介紹&#xff1a; 一、DOM 事件綁定&#xff08;最基礎的事件&#xff09; 使用 v-on&#xff08;或簡寫 &#xff0…

系統編程2(消息隊列)

? 消息隊列概念 Linux系統中消息隊列&#xff08;Message Queue&#xff09;是進程間通信的一種方式&#xff0c;這種通信機制的好處是可以傳輸指定類型(用戶可以自行定義)的數據&#xff0c;相同類型的數據根據到達順序在隊列中進行排隊。 當然&#xff0c;不同類型的數據不…

Pytorch深度學習框架60天進階學習計劃 - 第41天:生成對抗網絡進階(二)

Pytorch深度學習框架60天進階學習計劃 - 第41天&#xff1a;生成對抗網絡進階&#xff08;二&#xff09; 7. 實現條件WGAN-GP # 訓練條件WGAN-GP def train_conditional_wgan_gp():# 用于記錄損失d_losses []g_losses []# 用于記錄生成樣本的多樣性&#xff08;通過類別分…

python 微博爬蟲 01

起因&#xff0c; 目的: ?下載單個視頻&#xff0c;完成。? 獲取某用戶的視頻列表&#xff0c;完成。剩下的就是&#xff0c; 根據視頻列表&#xff0c;逐個下載視頻&#xff0c;我沒做&#xff0c;沒意思。獲取視頻的評論&#xff0c;以后再說。 關鍵點記錄: 1. 對一個視…

Servlet、HTTP與Spring Boot Web全面解析與整合指南

目錄 第一部分&#xff1a;HTTP協議與Servlet基礎 1. HTTP協議核心知識 2. Servlet核心機制 第二部分&#xff1a;Spring Boot Web深度整合 1. Spring Boot Web架構 2. 創建Spring Boot Web應用 3. 控制器開發實踐 4. 請求與響應處理 第三部分&#xff1a;高級特性與最…

vue中根據html動態渲染內容2.0

上次使用的是p標簽用的contenteditable代替的可編輯的input&#xff0c;最后實現還是選擇了用el-input的textarea方式。 一開始考慮的是需要根據用戶輸入自動撐開輸入框&#xff0c;所以選擇了p標簽可編輯。 最后發現還是el-input會更好一點&#xff0c;只不過需要處理輸入框撐…

CentOS 系統磁盤擴容并掛載到根目錄(/)的詳細步驟

在使用 CentOS 系統時&#xff0c;經常會遇到需要擴展磁盤空間的情況。例如&#xff0c;當虛擬機的磁盤空間不足時&#xff0c;可以通過增加磁盤容量并將其掛載到根目錄&#xff08;/&#xff09;來解決。以下是一個完整的操作流程&#xff0c;詳細介紹了如何將新增的 10G 磁盤…

LINUX基礎 [二] - Linux常見指令

目錄 &#x1f4bb;前言 &#x1f4bb;指令 &#x1f3ae;ls指令 &#x1f3ae;pwd指令 &#x1f3ae;whoami指令 &#x1f3ae;cd指令 &#x1f3ae;clear指令 &#x1f3ae;touch指令 &#x1f3ae;mkdir指令 &#x1f3ae;rmdir指令 &#x1f3ae;rm指令 &#…

基于php的成績分析和預警與預測網站(源碼+lw+部署文檔+講解),源碼可白嫖!

摘要 人類現已邁入二十一世紀&#xff0c;科學技術日新月異&#xff0c;經濟、資訊等各方面都有了非常大的進步&#xff0c;尤其是資訊與網絡技術的飛速發展&#xff0c;對政治、經濟、軍事、文化、教育等各方面都有了極大的影響。 利用電腦網絡的這些便利&#xff0c;發展一套…

《從底層邏輯剖析:分布式軟總線與傳統計算機硬件總線的深度對話》

在科技飛速發展的當下&#xff0c;我們正見證著計算機技術領域的深刻變革。計算機總線作為信息傳輸的關鍵樞紐&#xff0c;其發展歷程承載著技術演進的脈絡。從傳統計算機硬件總線到如今備受矚目的分布式軟總線&#xff0c;每一次的變革都為計算機系統性能與應用拓展帶來了質的…

Spring Boot 3.5新特性解析:自動配置再升級,微服務開發更高效

&#x1f4dd; 摘要 Spring Boot 3.5作為Spring生態的最新版本&#xff0c;帶來了多項令人振奮的改進。本文將深入解析其中最核心的自動配置增強特性&#xff0c;以及它們如何顯著提升微服務開發效率。通過詳細的代碼示例和通俗易懂的講解&#xff0c;您將全面了解這些新特性在…

【前端】webpack一本通

今日更新完畢&#xff0c;不定期補充&#xff0c;建議關注收藏點贊。 目錄 簡介Loader和Plugin的不同&#xff1f;&#xff08;必會&#xff09; 使用webpack默認只能處理js文件 ->引入加載器對JS語法降級&#xff0c;兼容低版本語法合并文件再次打包進階 工作原理Webpack 的…

leetcode 264. Ugly Number II

動態規劃解決。 關鍵是理解如何生成新的丑數。這道題和經典的斐波那契數列問題其實是一樣的。求第n個數&#xff0c;需要用第n個數前面的數來求。不同的是&#xff0c;斐波那契數列不會重復。而本題的丑數&#xff0c;會重復出現。 class Solution { public:int nthUglyNumbe…

深入理解 HTML5 語義元素:提升網頁結構與可訪問性

引言 在構建網頁的過程中&#xff0c;合理的結構與清晰的語義對于網頁的質量、可維護性以及搜索引擎優化&#xff08;SEO&#xff09;都至關重要。HTML5 引入了一系列語義元素&#xff0c;為開發者提供了更精準描述網頁內容的工具。本文將深入探討 HTML5 語義元素的作用、使用…

PyCharm顯示主菜單和工具欄

顯示主菜單 新版 PyCharm 是不顯示主菜單的&#xff0c;要想顯示主菜單和工具欄&#xff0c;則通過 “視圖” → “外觀” &#xff0c;勾選 “在單獨的工具欄中顯示主菜單” 和 “工具欄” 即可。 設置工具欄 此時工具欄里并沒有什么工具&#xff0c;因此我們需要自定義工具…

CyclicBarrier 基本用法

CyclicBarrier 基本用法 簡介 CyclicBarrier 是 Java 并發包&#xff08;java.util.concurrent&#xff09;中的一個同步輔助類。它允許一組線程相互等待&#xff0c;直到到達某個公共屏障點&#xff08;common barrier point&#xff09;。只有當所有參與的線程都到達屏障點…

[特殊字符] 手機連接車機熱點并使用 `iperf3` 測試網絡性能

好的&#xff0c;以下是根據你的描述整理出來的步驟及解釋&#xff1a; &#x1f4f6; 手機連接車機熱點并使用 iperf3 測試網絡性能 本文將通過 iperf3 來測試手機和車機之間的網絡連接性能。我們會讓車機作為服務端&#xff0c;手機作為客戶端&#xff0c;進行 UDP 流量傳輸…

FPGA上實現SD卡連續多塊讀的命令

在FPGA上實現SD卡連續多塊讀的命令 CMD17命令一次只能讀取1個塊 CMD18命令一次可以連續讀取多個塊&#xff0c;直到停止命令CMD12 CMD18命令讀的塊數程序可任意設置 目錄 前言 一、SD卡多塊讀命令CMD18 二、停止讀命令CMD12 三、SD卡初始化SD卡連續塊讀操作的verilog代碼 …