免费国产精品自在自线-91精品国产色综合久久久浪潮-99热久久免费频精品-国产精品国模在线观看-久久亚洲国产精品成人?V秋霞-久久国产一级A片免费播放-亚洲国产欧洲综合97久久-久久国产白嫩美女呻吟高潮

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

Log4j2全局logId配置指南:從MDC到異步與微服務(wù)透傳

Log4j2全局logId配置指南:從MDC到異步與微服務(wù)透傳 1. 項(xiàng)目概述為什么我們需要一個(gè)貫穿始終的logId在分布式系統(tǒng)或者一個(gè)稍具規(guī)模的單體應(yīng)用中排查一個(gè)用戶請求的完整軌跡常常像在玩一個(gè)沒有地圖的尋寶游戲。你可能會在網(wǎng)關(guān)日志里看到請求A在業(yè)務(wù)服務(wù)B的日志里看到一段相關(guān)處理又在數(shù)據(jù)庫慢查詢?nèi)罩纠锇l(fā)現(xiàn)一條可疑記錄但你怎么能百分之百確定它們屬于同一次用戶操作傳統(tǒng)的日志記錄方式依賴時(shí)間戳和線程名在低并發(fā)下或許可行一旦流量上來各種異步處理、線程池復(fù)用日志就會混雜在一起難以梳理。這就是引入“l(fā)ogId”或稱為traceId、requestId的唯一標(biāo)識的價(jià)值所在。它的核心目標(biāo)是為同一次業(yè)務(wù)請求在所有涉及的系統(tǒng)、服務(wù)、線程中打上同一個(gè)“身份證號”。無論這個(gè)請求經(jīng)歷了多少層調(diào)用、跨了多少個(gè)服務(wù)、被多少個(gè)線程處理過只要日志中攜帶了這個(gè)logId我們就能像用一根線串起散落的珍珠一樣快速、準(zhǔn)確地還原出這次請求的完整生命周期和調(diào)用鏈路。最近的一些事件比如某些服務(wù)提示“請求過多”或“處理請求時(shí)遇到錯(cuò)誤”如果日志中沒有全局唯一的請求標(biāo)識開發(fā)人員定位問題就如同大海撈針無法快速判斷是用戶頻繁操作、網(wǎng)絡(luò)重試導(dǎo)致的重復(fù)請求還是服務(wù)內(nèi)部某個(gè)環(huán)節(jié)出了問題。配置Log4j2來自動生成和傳遞logId就是為了從根本上解決這種可觀測性的痛點(diǎn)讓日志從雜亂的信息記錄變成可追蹤、可分析的診斷工具。2. 核心設(shè)計(jì)思路與方案選型為請求配置唯一logId聽起來簡單但實(shí)現(xiàn)起來需要考慮整個(gè)請求生命周期的上下文管理。核心思路可以概括為“源頭生成全程攜帶日志集成”。2.1 方案對比ThreadLocal vs MDC在Java生態(tài)中實(shí)現(xiàn)請求上下文傳遞主要有兩大陣營ThreadLocal和 Log4j2自帶的ThreadContext通常通過其門面類MDC使用。ThreadLocal方案 這是最基礎(chǔ)也最靈活的方案。你可以在過濾器或攔截器中生成一個(gè)UUID存入一個(gè)自定義的ThreadLocal變量中。在任何需要的地方通過ThreadLocal.get()來獲取。它的優(yōu)點(diǎn)是概念清晰完全受控。但缺點(diǎn)也很明顯內(nèi)存泄漏風(fēng)險(xiǎn)如果使用不當(dāng)尤其是配合線程池時(shí)忘記在請求處理完畢后remove()會造成嚴(yán)重的內(nèi)存泄漏。上下文傳遞困難當(dāng)請求處理涉及異步操作如Async、CompletableFuture或切換到子線程時(shí)ThreadLocal的值不會自動繼承需要手動傳遞增加了代碼的復(fù)雜性和出錯(cuò)概率。MDCMapped Diagnostic Context方案 MDC是SLF4J提供、Log4j2實(shí)現(xiàn)的一個(gè)診斷上下文工具。它本質(zhì)上是一個(gè)與當(dāng)前線程綁定的Map。相比原生ThreadLocalMDC方案與日志框架天生集成是完成我們目標(biāo)的更優(yōu)選擇理由如下日志框架原生支持在Log4j2的PatternLayout中可以直接通過%X{key}來輸出MDC中存儲的值集成成本極低。設(shè)計(jì)更完善MDC內(nèi)部已經(jīng)考慮了線程池等場景的一些基礎(chǔ)處理盡管在異步場景下仍需額外處理但有現(xiàn)成的解決方案如ThreadContext的Stack和CloseableThreadContext。生態(tài)兼容性好作為SLF4J的標(biāo)準(zhǔn)各種中間件、監(jiān)控組件如SkyWalking, Zipkin都對其有良好支持便于未來擴(kuò)展。實(shí)操心得在幾年前我可能會為了極致控制而選擇ThreadLocal。但現(xiàn)在對于日志追蹤這個(gè)特定場景MDC是毫無疑問的首選。它減少了我們自己造輪子的風(fēng)險(xiǎn)并且能讓日志配置變得異常簡潔。除非有非常特殊的、MDC無法滿足的上下文管理需求否則都應(yīng)優(yōu)先采用MDC方案。2.2 整體架構(gòu)設(shè)計(jì)我們的目標(biāo)架構(gòu)非常清晰生成與注入在請求進(jìn)入應(yīng)用的第一時(shí)間通常是一個(gè)Servlet Filter或Spring Interceptor生成一個(gè)全局唯一的logId例如UUID并將其放入MDC或Log4j2的ThreadContext中。透傳與繼承確保在處理請求的整個(gè)過程中包括同步調(diào)用、異步方法、跨服務(wù)調(diào)用通過HTTP頭或RPC上下文這個(gè)logId都能被正確傳遞。日志輸出在Log4j2的日志輸出模式Pattern中配置一個(gè)占位符如%X{logId}讓每一條日志自動附帶這個(gè)logId。清理在請求處理結(jié)束時(shí)清理MDC中的logId避免污染后續(xù)請求特別是在使用線程池時(shí)。這個(gè)流程確保了從控制器、服務(wù)層、數(shù)據(jù)訪問層甚至到某個(gè)工具類中打的日志只要屬于同一個(gè)請求就會帶有相同的logId。3. 核心細(xì)節(jié)解析與實(shí)操要點(diǎn)3.1 LogId的生成策略與考量生成一個(gè)唯一ID聽起來用UUID.randomUUID().toString()就夠了但在高并發(fā)、分布式場景下我們還需要考慮更多。UUID最通用的選擇UUID.randomUUID()生成36位字符串含連字符全球唯一。優(yōu)點(diǎn)是無需中心化協(xié)調(diào)生成簡單。缺點(diǎn)是字符串較長存儲和傳輸有開銷且無序不利于數(shù)據(jù)庫索引。雪花算法Snowflake生成的是64位的長整型數(shù)字包含時(shí)間戳、工作機(jī)器ID、序列號等信息。優(yōu)點(diǎn)是趨勢遞增、數(shù)字類型存儲空間小、查詢效率高。缺點(diǎn)是需要配置機(jī)器ID在容器化動態(tài)伸縮環(huán)境中需要借助外部系統(tǒng)如Redis、ZooKeeper來管理機(jī)器ID。納秒時(shí)間戳隨機(jī)數(shù)/序列號可以自定義更短、更可讀的格式例如20250320143015987_abc12時(shí)間戳隨機(jī)串。可控性強(qiáng)但需自己保證集群內(nèi)的唯一性。對于絕大多數(shù)Web應(yīng)用如果logId主要用于日志串聯(lián)不直接作為數(shù)據(jù)庫主鍵使用UUID足矣。為了便于閱讀和傳輸通常會去掉連字符生成一個(gè)32位的字符串。import org.slf4j.MDC; import java.util.UUID; public class LogIdUtil { public static final String LOG_ID_KEY logId; /** * 生成一個(gè)簡化的UUID作為logId (32位十六進(jìn)制數(shù)字) */ public static String generateLogId() { return UUID.randomUUID().toString().replace(-, ); } /** * 將logId設(shè)置到MDC上下文中 */ public static void setLogId(String logId) { MDC.put(LOG_ID_KEY, logId); } /** * 從MDC獲取當(dāng)前l(fā)ogId */ public static String getLogId() { return MDC.get(LOG_ID_KEY); } /** * 清除MDC中的logId */ public static void clearLogId() { MDC.remove(LOG_ID_KEY); } }注意事項(xiàng)生成logId的時(shí)機(jī)要盡可能早最好是在網(wǎng)關(guān)或最外層的過濾器。如果應(yīng)用前面有Nginx等代理可以考慮從代理層傳入一個(gè)X-Request-ID頭部應(yīng)用層優(yōu)先使用它沒有則自己生成。這樣可以實(shí)現(xiàn)全鏈路的追蹤。3.2 使用Servlet Filter進(jìn)行攔截注入在基于Servlet的Java Web應(yīng)用中Filter是攔截請求的第一道關(guān)卡是放置logId注入邏輯的理想位置。import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.UUID; WebFilter(urlPatterns /*) // 攔截所有請求 public class LogIdFilter implements Filter { private static final String LOG_ID_HEADER X-Request-ID; private static final String LOG_ID_KEY logId; Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest (HttpServletRequest) request; String logId; // 1. 優(yōu)先嘗試從請求頭中獲取便于跨服務(wù)傳遞 logId httpRequest.getHeader(LOG_ID_HEADER); // 2. 如果請求頭中沒有則自己生成 if (logId null || logId.isBlank()) { logId UUID.randomUUID().toString().replace(-, ); } // 3. 將logId設(shè)置到MDC中 MDC.put(LOG_ID_KEY, logId); // 4. 可選將logId添加到響應(yīng)頭方便前端或下游服務(wù)查看 if (response instanceof HttpServletResponse) { ((HttpServletResponse) response).setHeader(LOG_ID_HEADER, logId); } try { // 5. 繼續(xù)執(zhí)行過濾器鏈 chain.doFilter(request, response); } finally { // 6. 【關(guān)鍵】請求處理完畢后務(wù)必清理MDC防止內(nèi)存泄漏和上下文污染 MDC.remove(LOG_ID_KEY); } } Override public void init(FilterConfig filterConfig) throws ServletException { // 初始化操作如果需要的話 } Override public void destroy() { // 銷毀操作如果需要的話 } }關(guān)鍵點(diǎn)解析try...finally塊這是保證MDC被清理的核心。無論請求處理過程中是正常返回還是拋出異常finally塊中的MDC.remove()都會執(zhí)行確保線程池中的線程在處理下一個(gè)請求時(shí)是“干凈”的。響應(yīng)頭設(shè)置將logId設(shè)置到響應(yīng)頭是一個(gè)好習(xí)慣。對于前端如果遇到錯(cuò)誤可以將這個(gè)ID反饋給用戶或技術(shù)支持便于后端快速定位日志。對于微服務(wù)調(diào)用鏈下游服務(wù)可以繼續(xù)傳遞這個(gè)ID。請求頭優(yōu)先檢查并優(yōu)先使用傳入的X-Request-ID這是實(shí)現(xiàn)跨服務(wù)鏈路追蹤的基礎(chǔ)。第一個(gè)收到請求的服務(wù)生成ID后續(xù)所有服務(wù)都透傳這個(gè)ID。3.3 在Spring Boot中通過Interceptor實(shí)現(xiàn)如果你使用的是Spring Boot使用HandlerInterceptor會更加Spring風(fēng)格并且可以更精細(xì)地控制攔截路徑如排除靜態(tài)資源。import org.slf4j.MDC; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.UUID; Component public class LogIdInterceptor implements HandlerInterceptor { private static final String LOG_ID_HEADER X-Request-ID; private static final String LOG_ID_KEY logId; Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String logId request.getHeader(LOG_ID_HEADER); if (logId null || logId.isBlank()) { logId UUID.randomUUID().toString().replace(-, ); } MDC.put(LOG_ID_KEY, logId); response.setHeader(LOG_ID_HEADER, logId); // 設(shè)置響應(yīng)頭 return true; // 繼續(xù)執(zhí)行 } Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { // 請求處理完成后清理MDC MDC.remove(LOG_ID_KEY); } }然后需要通過配置類將這個(gè)攔截器注冊到Spring MVC中import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; Configuration public class WebConfig implements WebMvcConfigurer { Autowired private LogIdInterceptor logIdInterceptor; Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(logIdInterceptor) .addPathPatterns(/**) // 攔截所有API路徑 .excludePathPatterns(/css/**, /js/**, /images/**); // 排除靜態(tài)資源 } }實(shí)操心得在Spring Boot中我更喜歡用Interceptor而非Filter。因?yàn)镮nterceptor能更自然地融入Spring生態(tài)方便獲取Spring管理的Bean也更容易通過excludePathPatterns排除一些不需要處理的請求如健康檢查端點(diǎn)/actuator/health避免產(chǎn)生不必要的日志ID。4. Log4j2配置詳解讓logId自動出現(xiàn)在每行日志前面我們成功將logId放入了MDC接下來就是配置Log4j2讓它自動將MDC中的logId打印出來。這是最關(guān)鍵的一步否則所有工作都白費(fèi)。4.1 基礎(chǔ)PatternLayout配置假設(shè)你使用的是log4j2.xml配置文件我們需要修改PatternLayout的pattern。?xml version1.0 encodingUTF-8? Configuration statusWARN Appenders !-- 控制臺輸出 -- Console nameConsole targetSYSTEM_OUT !-- 關(guān)鍵在pattern中添加 %X{logId} -- PatternLayout pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %c{1.} - [logId:%X{logId}] - %msg%n/ /Console !-- 文件輸出同樣加上logId -- RollingFile nameRollingFile fileNamelogs/app.log filePatternlogs/$${date:yyyy-MM}/app-%d{MM-dd-yyyy}-%i.log.gz PatternLayout pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %c{1.} - [logId:%X{logId}] - %msg%n/ Policies TimeBasedTriggeringPolicy / SizeBasedTriggeringPolicy size100 MB/ /Policies DefaultRolloverStrategy max10/ /RollingFile /Appenders Loggers Root levelinfo AppenderRef refConsole/ AppenderRef refRollingFile/ /Root /Loggers /Configuration配置解析%X{logId}這就是從MDC中取出key為logId的值的占位符。如果MDC中沒有l(wèi)ogId這里會輸出空。我們用方括號[]將它包裹起來使其在日志中更醒目。%d,%t,%level,%c,%msg是Log4j2常用的轉(zhuǎn)換符分別代表日期、線程、日志級別、Logger名和消息本身。這個(gè)配置會讓每一條日志行都自動附帶當(dāng)前的logId例如2023-10-27 14:30:25.123 [http-nio-8080-exec-1] INFO c.e.s.UserService - [logId:6b3a8c5f1d4e2a7b9c0f8e3d5a1b2c6] - 用戶登錄成功4.2 高級配置為異步日志配置ContextMap如果你的應(yīng)用使用了Log4j2的異步日志AsyncLogger或AsyncRoot需要特別注意。在異步記錄時(shí)日志事件可能是在另一個(gè)線程中被處理的。為了確保MDC上下文能正確地從生產(chǎn)日志的線程傳遞到消費(fèi)日志的線程我們需要在配置中啟用includeThreadContext。Configuration statusWARN Appenders Console nameConsole targetSYSTEM_OUT PatternLayout pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %c{1.} - [logId:%X{logId}] - %msg%n/ /Console /Appenders Loggers !-- 使用 AsyncLogger 并設(shè)置 includeThreadContexttrue -- AsyncLogger namecom.example levelinfo includeThreadContexttrue AppenderRef refConsole/ /AsyncLogger AsyncRoot levelinfo includeThreadContexttrue AppenderRef refConsole/ /AsyncRoot /Loggers /Configuration將includeThreadContext設(shè)置為true默認(rèn)就是true但顯式聲明是個(gè)好習(xí)慣Log4j2在將日志事件放入異步隊(duì)列時(shí)會捕獲當(dāng)前線程的MDC上下文快照并在異步線程中處理日志時(shí)恢復(fù)它。這樣即使在異步日志中%X{logId}也能正確輸出。4.3 配置logId的默認(rèn)值有時(shí)在一些非Web請求的上下文中如定時(shí)任務(wù)、消息隊(duì)列監(jiān)聽器MDC中可能沒有l(wèi)ogId這會導(dǎo)致日志中[logId:]后面為空不太美觀。我們可以通過Log4j2的MapLookup或自定義Lookup來設(shè)置一個(gè)默認(rèn)值但更簡單的方法是在Pattern中使用條件判斷。Log4j2的Pattern支持簡單的條件語法。我們可以這樣配置當(dāng)MDC中沒有l(wèi)ogId時(shí)輸出“N/A”或一個(gè)固定標(biāo)識PatternLayout pattern%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %c{1.} - [logId:%X{logId:-N/A}] - %msg%n/看就是在%X{logId}后面加了一個(gè):-N/A。這表示如果%X{logId}為空則默認(rèn)輸出“N/A”。這個(gè)語法非常實(shí)用。5. 處理異步與多線程場景下的logId傳遞這是實(shí)現(xiàn)全局logId最具挑戰(zhàn)性的部分。在Web請求的同步處理中MDC工作得很好因?yàn)檎麄€(gè)過程都在同一個(gè)線程。但一旦涉及異步編程線程切換會導(dǎo)致ThreadLocalMDC的底層實(shí)現(xiàn)存儲的上下文丟失。5.1 使用Spring的Async注解當(dāng)你在Service層的一個(gè)方法上標(biāo)注了AsyncSpring會使用一個(gè)線程池來執(zhí)行這個(gè)方法。此時(shí)執(zhí)行異步方法的線程與原請求線程不同MDC上下文不會自動傳遞。解決方案配置一個(gè)TaskDecoratorSpring的ThreadPoolTaskExecutor允許我們設(shè)置一個(gè)TaskDecorator它可以在任務(wù)執(zhí)行前后進(jìn)行裝飾我們可以在這里進(jìn)行MDC上下文的傳遞。import org.slf4j.MDC; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.TaskDecorator; import org.springframework.scheduling.annotation.AsyncConfigurerSupport; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.Map; import java.util.concurrent.Executor; Configuration EnableAsync public class AsyncConfig extends AsyncConfigurerSupport { Override Bean(name taskExecutor) public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(25); executor.setThreadNamePrefix(Async-); // 關(guān)鍵設(shè)置TaskDecorator來傳遞MDC上下文 executor.setTaskDecorator(new MdcTaskDecorator()); executor.initialize(); return executor; } /** * 任務(wù)裝飾器用于復(fù)制MDC上下文到異步線程 */ static class MdcTaskDecorator implements TaskDecorator { Override public Runnable decorate(Runnable runnable) { // 獲取當(dāng)前線程提交任務(wù)的線程的MDC上下文快照 MapString, String contextMap MDC.getCopyOfContextMap(); return () - { try { // 異步任務(wù)執(zhí)行前將MDC上下文設(shè)置到新線程中 if (contextMap ! null) { MDC.setContextMap(contextMap); } // 執(zhí)行原始任務(wù) runnable.run(); } finally { // 異步任務(wù)執(zhí)行后清理新線程的MDC上下文 MDC.clear(); } }; } } }這樣配置后所有通過Async執(zhí)行的異步方法其日志都會自動攜帶調(diào)用者線程的logId。5.2 使用CompletableFuture如果你直接使用CompletableFuture.supplyAsync()等靜態(tài)方法它使用的是ForkJoinPool公共池同樣需要手動傳遞上下文。import org.slf4j.MDC; import java.util.Map; import java.util.concurrent.CompletableFuture; public class SomeService { public CompletableFutureString asyncProcess() { // 1. 在調(diào)用異步方法前先獲取當(dāng)前MDC上下文 MapString, String contextMap MDC.getCopyOfContextMap(); // 2. 在異步任務(wù)中恢復(fù)上下文 return CompletableFuture.supplyAsync(() - { if (contextMap ! null) { MDC.setContextMap(contextMap); } try { // 你的異步業(yè)務(wù)邏輯 logger.info(在異步任務(wù)中處理...); // 這條日志會帶有l(wèi)ogId return 處理結(jié)果; } finally { MDC.clear(); } }); } }5.3 使用Log4j2的CloseableThreadContext推薦對于更復(fù)雜的場景或者不想深度耦合Spring的TaskDecoratorLog4j2自身提供了一個(gè)更優(yōu)雅的工具CloseableThreadContext。它不僅可以管理MDC還可以管理NDC嵌套診斷上下文。你可以在開啟異步任務(wù)的地方使用CloseableThreadContext來包裝任務(wù)import org.apache.logging.log4j.CloseableThreadContext; import org.apache.logging.log4j.ThreadContext; import java.util.concurrent.CompletableFuture; public class SomeService { public CompletableFutureString asyncProcessWithLog4j2() { // 獲取當(dāng)前所有的ThreadContext包括MDC數(shù)據(jù) // 注意這里使用Log4j2原生的ThreadContext而不是SLF4J的MDC // 因?yàn)镾LF4J的MDC底層就是由Log4j2的ThreadContext實(shí)現(xiàn)的所以數(shù)據(jù)是相通的 // 但為了保險(xiǎn)我們直接使用Log4j2的API來捕獲 MapString, String context ThreadContext.getImmutableContext(); return CompletableFuture.supplyAsync(() - { // 使用CloseableThreadContext.Instance將上下文注入新線程 // try-with-resources語法確保最后自動清理 try (CloseableThreadContext.Instance ctc CloseableThreadContext.putAll(context)) { // 此時(shí)新線程的ThreadContextMDC已經(jīng)包含了原線程的所有內(nèi)容 logger.info(使用CloseableThreadContext的異步任務(wù)...); return 處理結(jié)果; } // 離開try塊后上下文會自動被清理 }); } }CloseableThreadContext.putAll(context)方法會將傳入的Map中的所有鍵值對放入新線程的上下文中并且返回的CloseableThreadContext.Instance是一個(gè)AutoCloseable在try-with-resources塊結(jié)束時(shí)會自動清理它本次添加的所有上下文而不會影響其他可能存在的上下文非常安全。踩坑記錄曾經(jīng)在一個(gè)項(xiàng)目中我們混合使用了Async和手動CompletableFuture但沒有統(tǒng)一處理上下文傳遞導(dǎo)致日志中的logId時(shí)有時(shí)無排查問題極其痛苦。后來我們強(qiáng)制規(guī)定所有異步操作必須通過統(tǒng)一的、裝飾了TaskDecorator的線程池執(zhí)行或者使用CloseableThreadContext包裝問題才得以根治。一致性是分布式追蹤的生命線。6. 微服務(wù)場景下的logId透傳在微服務(wù)架構(gòu)中一個(gè)用戶請求會經(jīng)過網(wǎng)關(guān)、多個(gè)業(yè)務(wù)服務(wù)、數(shù)據(jù)庫、緩存等。要讓logId貫穿整條調(diào)用鏈需要在服務(wù)間調(diào)用時(shí)進(jìn)行透傳。6.1 HTTP調(diào)用透傳使用RestTemplate或Feign使用RestTemplate你可以通過自定義ClientHttpRequestInterceptor在發(fā)送請求前將logId添加到HTTP頭中。import org.slf4j.MDC; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; import java.io.IOException; Component public class LogIdRestTemplateInterceptor implements ClientHttpRequestInterceptor { private static final String LOG_ID_HEADER X-Request-ID; Override public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { String logId MDC.get(logId); if (logId ! null !logId.isBlank()) { request.getHeaders().add(LOG_ID_HEADER, logId); } return execution.execute(request, body); } }然后將這個(gè)攔截器配置到你使用的RestTemplateBean中。使用OpenFeignFeign可以通過自定義RequestInterceptor來實(shí)現(xiàn)同樣的功能。import feign.RequestInterceptor; import feign.RequestTemplate; import org.slf4j.MDC; import org.springframework.stereotype.Component; Component public class LogIdFeignInterceptor implements RequestInterceptor { private static final String LOG_ID_HEADER X-Request-ID; Override public void apply(RequestTemplate template) { String logId MDC.get(logId); if (logId ! null !logId.isBlank()) { template.header(LOG_ID_HEADER, logId); } } }只要這個(gè)Interceptor被Spring管理它就會自動應(yīng)用于所有的Feign客戶端。6.2 RPC框架透傳以Dubbo為例對于Dubbo這樣的RPC框架可以通過org.apache.dubbo.rpc.Filter來實(shí)現(xiàn)上下文的透傳。import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.rpc.*; import org.slf4j.MDC; Activate(group {CommonConstants.PROVIDER, CommonConstants.CONSUMER}) public class LogIdDubboFilter implements Filter { private static final String LOG_ID_KEY logId; private static final String DUBBO_LOG_ID_KEY dubboLogId; // 用于在Dubbo Attachment中傳遞的key Override public Result invoke(Invoker? invoker, Invocation invocation) throws RpcException { // 消費(fèi)者端將MDC中的logId放入RPC上下文中 if (RpcContext.getContext().isConsumerSide()) { String logId MDC.get(LOG_ID_KEY); if (logId ! null) { invocation.setAttachment(DUBBO_LOG_ID_KEY, logId); } } // 提供者端從RPC上下文中取出logId并設(shè)置到MDC中 if (RpcContext.getContext().isProviderSide()) { String logId invocation.getAttachment(DUBBO_LOG_ID_KEY); if (logId ! null !logId.isBlank()) { MDC.put(LOG_ID_KEY, logId); } else { // 如果沒有傳遞可以生成一個(gè)但最好保持鏈路一致這里生成可能會破壞鏈路 // MDC.put(LOG_ID_KEY, generateLogId()); } } try { return invoker.invoke(invocation); } finally { // 提供者端調(diào)用結(jié)束后清理MDC if (RpcContext.getContext().isProviderSide()) { MDC.remove(LOG_ID_KEY); } } } }還需要在src/main/resources/META-INF/dubbo目錄下創(chuàng)建org.apache.dubbo.rpc.Filter文件內(nèi)容為logIdFiltercom.yourpackage.LogIdDubboFilter6.3 消息隊(duì)列場景透傳當(dāng)服務(wù)通過消息隊(duì)列如RabbitMQ、Kafka進(jìn)行異步通信時(shí)也需要將logId放在消息頭中傳遞。以Spring AMQP (RabbitMQ)為例發(fā)送消息時(shí)import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageBuilder; import org.springframework.amqp.core.MessageProperties; import org.slf4j.MDC; public void sendMessage(String routingKey, Object payload) { String logId MDC.get(logId); Message message MessageBuilder.withBody(objectMapper.writeValueAsBytes(payload)) .setContentType(MessageProperties.CONTENT_TYPE_JSON) .setHeader(X-Request-ID, logId) // 將logId放入消息頭 .build(); rabbitTemplate.convertAndSend(exchangeName, routingKey, message); }消費(fèi)消息時(shí)在監(jiān)聽器方法中先從消息頭中取出logId并設(shè)置到MDC。import org.springframework.amqp.core.Message; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.slf4j.MDC; import org.slf4j.Logger; import org.slf4j.LoggerFactory; Component public class MyMessageListener { private static final Logger logger LoggerFactory.getLogger(MyMessageListener.class); RabbitListener(queues your.queue) public void handleMessage(Message message, Payload YourBusinessObject payload) { String logId null; try { // 從消息頭中獲取logId MessageProperties properties message.getMessageProperties(); if (properties ! null properties.getHeaders() ! null) { logId (String) properties.getHeaders().get(X-Request-ID); } // 如果消息中沒有可以生成一個(gè)新的但建議傳遞以保證鏈路完整 if (logId null) { logId MQ- UUID.randomUUID().toString().replace(-, ).substring(0, 16); } MDC.put(logId, logId); logger.info(開始處理消息消息ID: {}, properties.getMessageId()); // ... 你的業(yè)務(wù)邏輯 logger.info(消息處理完成); } catch (Exception e) { logger.error(處理消息失敗, e); } finally { // 務(wù)必清理MDC MDC.remove(logId); } } }注意事項(xiàng)在消息隊(duì)列場景中一個(gè)生產(chǎn)請求可能觸發(fā)多個(gè)消息進(jìn)而被多個(gè)消費(fèi)者處理。此時(shí)這幾個(gè)消費(fèi)者處理的日志會共享同一個(gè)logId。這既是優(yōu)點(diǎn)可以追蹤整個(gè)業(yè)務(wù)流也可能帶來混淆多個(gè)并行處理共享ID。需要根據(jù)業(yè)務(wù)語義判斷是否合適。對于完全獨(dú)立的并行任務(wù)有時(shí)生成子ID如parentLogId-childId會更清晰。7. 常見問題排查與實(shí)戰(zhàn)技巧即使配置看起來完美在實(shí)際運(yùn)行中還是會遇到各種“詭異”的問題。下面是我在多次實(shí)踐中總結(jié)的常見坑點(diǎn)和解決技巧。7.1 問題排查速查表問題現(xiàn)象可能原因排查步驟與解決方案日志中[logId:]為空1. Filter/Interceptor未生效或路徑不匹配。2. 在設(shè)置MDC之前就打印了日志。3. 使用了異步日志但未配置includeThreadContexttrue。1. 檢查Filter/Interceptor的注冊路徑確認(rèn)其能攔截到目標(biāo)請求。2. 確保在請求處理的最早期如Filter的doFilter開頭設(shè)置MDC。3. 檢查Log4j2配置為AsyncLogger/Root添加includeThreadContexttrue。異步任務(wù)中l(wèi)ogId丟失1. 未使用TaskDecorator或CloseableThreadContext傳遞上下文。2. 自定義線程池未處理上下文傳遞。1. 為Async使用的線程池配置TaskDecorator。2. 對于手動創(chuàng)建的線程或線程池使用CloseableThreadContext包裝Runnable任務(wù)。微服務(wù)調(diào)用鏈logId中斷1. HTTP/RPC客戶端未添加攔截器來傳遞請求頭。2. 服務(wù)端未從請求頭中讀取并設(shè)置到MDC。3. 網(wǎng)關(guān)未生成或轉(zhuǎn)發(fā)X-Request-ID。1. 檢查RestTemplate/Feign/Dubbo的攔截器配置是否正確加載。2. 確保服務(wù)端的Filter/Interceptor能正確讀取約定的請求頭如X-Request-ID。3. 在網(wǎng)關(guān)層如Spring Cloud Gateway, Nginx統(tǒng)一生成和轉(zhuǎn)發(fā)請求ID。定時(shí)任務(wù)等非請求場景無logId定時(shí)任務(wù)、命令行程序等沒有HTTP請求入口因此Filter/Interceptor不會執(zhí)行。1. 在定時(shí)任務(wù)的run方法開始時(shí)手動生成并設(shè)置一個(gè)logId到MDC。2. 使用try...finally確保任務(wù)結(jié)束后清理MDC。logId在異常堆棧中不顯示異常打印時(shí)默認(rèn)的e.printStackTrace()或日志框架的異常輸出不包含MDC信息。確保使用日志框架如logger.error(錯(cuò)誤信息, e)來記錄異常這樣異常信息會和帶有l(wèi)ogId的日志行關(guān)聯(lián)。PatternLayout中的%xEx或%throwable轉(zhuǎn)換符可以輸出異常。高并發(fā)下logId串號1. 線程池復(fù)用線程MDC未清理干凈。2. 在finally塊中清理MDC的代碼未執(zhí)行如線程被強(qiáng)制中斷。1.絕對保證在請求處理結(jié)束的finally塊中調(diào)用MDC.clear()或MDC.remove(logId)。2. 審查代碼避免在finally塊之前有System.exit()或無限循環(huán)導(dǎo)致無法清理。7.2 實(shí)戰(zhàn)技巧與心得為logId添加前綴以區(qū)分來源在復(fù)雜的系統(tǒng)中日志可能來自網(wǎng)關(guān)、不同服務(wù)、定時(shí)任務(wù)??梢栽趌ogId前加一個(gè)簡短前綴如GW-網(wǎng)關(guān)、US-用戶服務(wù)、JOB-定時(shí)任務(wù)這樣在日志聚合平臺如ELK中一眼就能看出日志來源。將logId返回給前端對于API請求可以將logId放在HTTP響應(yīng)頭如X-Request-ID或JSON響應(yīng)體的一個(gè)字段中。當(dāng)用戶報(bào)告錯(cuò)誤時(shí)讓他們提供這個(gè)ID能極大提升排查效率。前端在遇到錯(cuò)誤時(shí)也可以自動在錯(cuò)誤彈窗中展示這個(gè)ID。在日志聚合平臺中利用logId如果你使用ELKElasticsearch, Logstash, Kibana或Graylog可以將logId作為一個(gè)獨(dú)立的字段進(jìn)行索引。這樣在Kibana中你可以直接搜索某個(gè)特定的logId瞬間看到這次請求在所有微服務(wù)中產(chǎn)生的所有日志實(shí)現(xiàn)真正的分布式追蹤。小心MDC的內(nèi)存泄漏這是老生常談但至關(guān)重要的一點(diǎn)。ThreadLocalMDC的基石在線程池場景下是內(nèi)存泄漏的重災(zāi)區(qū)。務(wù)必、務(wù)必、務(wù)必在try...finally的finally塊中清理。一個(gè)檢查方法是監(jiān)控你的應(yīng)用線程數(shù)如果線程數(shù)穩(wěn)定但內(nèi)存持續(xù)增長就要懷疑MDC清理的問題。考慮使用更專業(yè)的分布式追蹤系統(tǒng)對于大型微服務(wù)系統(tǒng)手動管理logId透傳會變得繁瑣且容易出錯(cuò)。此時(shí)應(yīng)考慮引入專業(yè)的APM應(yīng)用性能管理工具如SkyWalking、Zipkin或Jaeger。它們通過字節(jié)碼增強(qiáng)或探針的方式自動完成鏈路追蹤、上下文傳遞和性能監(jiān)控功能遠(yuǎn)比一個(gè)簡單的logId強(qiáng)大。你的logId可以作為這些系統(tǒng)的TraceId的一部分實(shí)現(xiàn)平滑過渡。配置Log4j2的logId看似是一個(gè)簡單的日志格式調(diào)整實(shí)則是構(gòu)建可觀測性系統(tǒng)的基石。它強(qiáng)迫我們以“請求鏈路”的視角來思考日志記錄而不是孤立地看待每一條日志信息。從Filter中那幾行簡單的MDC.put()和MDC.remove()開始到處理異步、跨服務(wù)調(diào)用這些復(fù)雜場景每一步都是在為快速定位線上問題、理解系統(tǒng)行為鋪平道路。當(dāng)你第一次通過一個(gè)logId在幾秒鐘內(nèi)從數(shù)千萬條日志中精準(zhǔn)拉出某個(gè)用戶失敗請求的完整軌跡時(shí)你就會覺得這一切的配置和踩坑都是值得的。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
第五婷婷伊人丁香| 91趴趴| 综合玖玖性爱免费视频| 成人αV视频免费观看| 国庆精品久久| 欲色人妻| 久久精品天| 十月丁香九月婷婷综合| 九月影院義母在线播放| 白人荫道BBWBBB大荫道| 中文字幕 中文字幕明步| 久99久精品| 五月天色图| 99精品在线| 天天插综合网| 开心激情站| 97人妻碰碰中文无码久热丝袜| 婷婷亚洲综合| 中文字幕av在线| 五月情四婷婷| 操97免费超级视频| 丁香五月婷婷少妇| 操操操B| 天天操综合网| 精品人妻久久久久久久| 99热超碰| 日本色99| 金品在线视频99| 婷婷五月天成人网| 天天干狠狠艹| 1995年关宝慧版蜘蛛女| 草美女在线观看视频在线播放| 激情五月天.色网| 五月丁香| 丁香五月中文字幕| 六月 丁香 视频| 亚洲婷婷五月天在线激情综合网| 伊人婷婷五月天av| YW无码| 丁香色婷婷五月天| 丁香婷婷啪啪| 婷婷99狠狠躁天天| 亚洲综合1024| 97人人搞| 99久久婷婷五月综合| 激情久久天天| 色吊丝中文字幕| 五月天国产| 婷婷开心五月| 九九热九九热精品| 五月色亭丁香| 亚洲激情视频网| 天堂A∨在线| 丁香五月婷婷亚洲另类| 五月天婷婷激情在线色图| 国产精品久久久久久久久久| 少妇高潮A片无套内谢麻豆传| 九九精品re免费视频| 成片免费观看视频大全| 夜精品无码A片一区二区蜜桃 | 中文字幕欧美精品久久| 婷婷情色五月| 激情五月婷婷她| 午夜少妇在线观看视频| 无码激情AAAAA片-区区| www.wuyuetian啪啪| 九九热精品视频| 五月婷婷啪啪啪| 夜夜爱网站| 天天摸人人摸| 五月婷婷综合视频| 激情综合区| 婷婷综合五月天| 亚洲A色| 热久久视频99| 丁香六月婷婷综合缴| 深爱五月天天| 色情婷婷五月天| www天天爽| 婷婷天天综合| 月婷婷婷婷五月| 99久久6| 五月婷婷开心六月激情小说| 久久久这里有精品| 综合久久9| 96精品久久久久久久久| 成人短视频在线观看| 色99视频| 九九九激情综合| 久久机热这里只有精品| 五月花在线观看视频| 色婷婷中文字母五月丁香| 玖玖色综合网| 婷婷成人丁香色情基地30 | 开心激情站| 色色网站在线| 五月激香蕉网| 成人网在线视频| 久久9精品视频| 最新av在线观看| 欧美群妇大交乱婬网| 久久综合丁香五月| 狠狠狠夜夜夜| 99在线精品免费视频| 丁香五月亚洲| 五月天婷婷综合| 丁香五月激情综合| 欧洲第一无人区观看| 嫩草AV久久伊人妇女超级A | 大香蕉AV在线| 婷婷五月丁香六月天亚洲综合| 五月天色网站| 成人在线视频网| 久久久www| 色情五月天se| 秋霞A V毛片| 亚洲av网站在线观看| 99爱精品| 人橾人| 九月色婷婷| 五月花成人网| 色五月激情综合网| 九九热99精品| 深爱五月中文字幕| 亚洲综合久| 日本人妻伦在线中文字幕| 琪琪狠狠干| 中文字幕人妻AV| 欧美图片丁香五月天| 欧美激情综合| 日本WWW九九九| 亚洲亚洲人成综合网络| 粉嫩av蜜桃av蜜臀av| 99热久只有| 开心婷婷五月| 香蕉99网| 五月色精品| 五夜丁香| 欧美内射AAAAAAXXXXX| 奇米网大香蕉| 色五开心五月五月深深爱| 久色激情| 第五婷婷伊人丁香| 99性色| 激情AV| 性色综合网| 婷婷五月天AV网| 热99这就是精品视频| 久久99热这里只频精品6学生| www.99热这里精品| 色色综合色| 天天舔天天爽| Xx色综合| 丁香在线视频| 婷婷五月天成人五月天| 亚洲九区| 日韩另类| 伊人五月综合网| 久久婷婷东京热大香樵| 26uuu精品一区二区| 国产精品久久久久9999小说| 亚洲婷婷丁香五月亚洲| 激情综合五月丁香| 五月天快乐开心激情网| 思思热在线| 久久9精品| 久久人妻伦理| 美国不卡视频| 99熟女啪啪视频| 99婷婷色| 综合五月天| 色五月在线综合| 深爱五月亚洲| 玖玖九九超碰| 婷婷五点亚洲| 先锋资源婷婷| 国产免费AV网站| 伊人热婷婷| 亚洲欧美一区二区三区爱爱动图| 亚洲国产另类av| 亚洲婷婷成人五月天| 99精品成人无码A片观看金桔| 久久草大香蕉| 激情综合五月| 婷婷五月婷婷五月| 色色色9 9 9| 99国产这里只有精品| 久久综合九色综合97婷婷| WWW、日本色丁香、co m| 深爱激情五月天| 欧美久草在线日本一级特黄大片做受9在线观看韩国电影《两个女人》未删减-毛片 | 色婷婷狠狠| 毛片新网地| 99热综合网| 成人在线综合| 欧美大肥婆大肥BBBBB| 色婷婷婷av| 色色亚洲| 天天爽免费视频| 婷婷性爱综合| 99免费| 久久综合这里只有精品1 | 99热手机在线精品| 婷婷伊人激情婷婷| a毛片二逼wwwwwwwwww| 色久天| 久久98热re| 天天摸天天肏| 色婷婷五月天堂资源| 激情五月黄色| 天天草天天日| 久草 天堂| 人人草人人舔| 久色婷婷200| 97人妻碰碰碰久久香蕉| 成人片黄网站色大片免费毛片| 天天草天天日| 色色色激情| 人妻丰满精品一区二区A片| WWW.桔色成人.COM| 欧美日韩99| 影音先锋女人AA鲁色资源| 在线A色| 五月婷婷,六月婷婷| 亚洲中文字幕av| Av性爱网| 国产1区2区3区| 丁香五月影院| 婷婷五月综激情| 五月花综合网| 六月婷婷九月丁香| 新激情婷婷| 久久草中文日韩欧美| 婷婷五月激情基地| 九九热99在线视频| 国产肥白大熟妇BBBB视频| 高清无码视频网址| 久久这里都是精品视频| 五月丁香啪啪啪| www.99.色| 97精品欧美91久久久久久久| 五月天婷婷无码| 亚洲欧美日韩VIP| 狠狠综合网| 99色爱| 91色综合网| 日日日日日| 日本婷婷| 激情99| 激情性五月天免费小说视频| 激情婷婷色小说| 六月激情网| 色色色综合网| www.五月丁香| 99久在线精品99re8热| 丁香五月天欧美成人| 99热国产婷婷| 性爱五月婷| 欧美日韩精品人妻狠狠躁免费视频| 日本久久人| 就去涩涩丁香五月天| 婷婷五月天成人网| 啊V视频在线观看| 五月天AV大香蕉| 男女av免费看| 91色色五月天| 性做爰A片免费视频A片直播| 欧美色爱五月天| 国产日日夜夜操| 六月婷婷天天操夜夜爽视频| 99综合视频| 无码动漫av| 四川女人毛多水多A片| 五月天激情影院| 九九干视频| 午夜五月天| 五月丁香六月综合激情网| 无码网| 色综合色综合网| 91婷婷搞| 亚洲精品网站色视频| 人人97碰| 激情综合啪啪啪| 亚洲小电影在线观看黄999| 九九综合五月欧美| 吊色AV男人的天堂| 五月丁香综合啪啪| 五月天激情播播网| 天干干夜夜操| 综合五月天完整| 丁香六月激情网C0W| 激情都市五月天| 99秘 在线| 国产日日夜夜操| 激情com| ri电影在线| 婷婷色五月久久| 开心五月激情五月丁香五月婷婷| 伊人久久五月天综合| 五月丁香AV在线| SS丁香五月婷婷| 激情综合色婷婷啪啪六月天| 五月婷综合| 91丨九色丨熟女|老版| 中文字幕综合网| 激情五月天视频| 婷婷视频网| 专区无日本视频高清8| 五月香婷婷| 九九99九九精品免费 | 91热在线| 99re热视频这里只精品| 日本久碰| 久久久人妻人伦| 婷婷色色狠狠| 久久激情五月婷婷| 色色色热| 五月天丁香啪啪啪啪| 丁香婷婷超碰 | 五月丁香婷婷综合视频| 五月婷婷综合在线| 五月天色色色网| 99操无码视频观看| 国产精品色一哟哟| 91精品久久久久久| 国产伊人大香蕉| 超碰亚洲天堂| cc精品国产性传播| 五月婷婷六月激情| 成人资源在线| 亚洲激情丁香五月基地| 天天摸天天肏| 久久婷婷青青| 激情无码五月天| 亚洲成人婷婷| 日本欧美成人片AAAA| 五月丁香趴趴| 狠狠色狠狠色综合日日91| 开心五月网 | 在线中文字幕视频| 久久天堂女人| 五月婷婷狠天天色综合| 99精品在线| 日本三级99人妇网站| 亚洲AV网站在线观看| 丁香色播五月天| 五月天婷婷色综合| 五月婷婷丁香91| 国产操B视频| 99爱视频在线免费观看| 梁铮版《蜘蛛女侠》在线| 亚州操人在线视频| 亚洲色99| 91碰在线| 日韩久热| 男人的天堂97| 久久丁香五月婷| 国产日比| 五月天色婷婷激情综合| 五月丁香福利| 啪啪激情综合| www.婷婷.com| 亚洲国产网站| 国产色色色色| 变态另类色图| 五月天激情视频五月天| 婷婷六月激情综合| 色婷婷影音| 五月丁香六月激情综合| 国产乱码久久| 这里只有精品免费| 婷婷欧美色| 香蕉国产2013| 五月婷婷啪| 国产精品日日躁夜夜躁| 成人电影在线免费试看| 久久久久久久97| 久久伊人婷| 这里只有精彩亚洲视频推荐| 男女激情久久| 无码人妻一区| www:99热视频| 婷婷五月综合体验看| 五月婷无码| 俺去也在线视频| 婷婷五月天亚洲五码| 操逼综合激情网| 欧美成人精品一区二区| 91丨九色丨国产打屁股网站| www夜夜操| 伊人大香久久| 91色在线/日韩| 丁香五月婷婷老师网站| 五月天婷婷乱论小说| 91熟妇大香蕉| 91九色熟女| 色婷婷大香蕉| 亚洲激情综合| 婷婷五月天干干| 狼人伊人干| 五月开心深爱激情网| 五月婷视频在线观看| 99热在线观看精品免费| 国产操B视频| 久久色情| 少妇口诉沐足视频播放器网址| 99噜噜噜在线播放| 色五月婷婷在线观看| 九九热99在线视频| 九九热最新地址| 色亚洲中文| 亚洲最大成人综合网720P| 开心五月激情五月丁香五月婷婷| 91好好热日本在线| 激情五月婷婷开心网| 99热99操| 亚洲激情四射| 五日激情综合| 五月色婷婷亚洲 | 国产69久久久欧美黑人A片| 深爱激情四射| 色综合色婷色基地| 丁香五月电影| 色丁香五月综合网| aa久久| 777精品久无码人妻蜜桃| 色J香五月天| www久久艹| 婷婷五月影院| 日韩av在线免费观看| 四色永久成人网站| 丁香五月婷婷影视先锋| 夜夜干夜夜操| 99国产性感视频| 在线另类视频| 色亭亭九月| 成人片在线播放| 99热精这里只有精品| 97碰碰视频| 婷婷综合五月天| 99久久免费精品| 五月天久久www| 无码成人AAAAA毛片AI换脸| 色五月激情| 开心五月激情| 久久婷婷五月天激情四射| 高清一区二区三区日本久| xxx.色婷婷| 六月丁香啪啪| 大天天伊人| 免费看欧美成人A片无码| 久久激情网| 婷婷亚洲丁香五月| 激情五月天婷婷图| 91丨九色丨白浆秘| 五月天丁香欧美激情| 欧美激情五月天| 99热激情| 日韩视频99| 操碰久| 在线看的免费网站| www.minyis.com【JT】实力收量可预付QQ2101460746 | 五月综合视频| 色婷婷久久综合| 五月婷婷九| 涩综合在线 | 人妻VideOssS人妻高清| 久热超碰| 综合激情九月婷婷,激情综合婷婷中文字| 欧洲色| 性色婷婷| 婷久久| 色婷婷婷婷五月天| 天天操狠狠操| 五月天成人在线播放丁香| 天天搞夜夜六| 五月视频日本免费观看| 啪啪东京热| 密着浓厚中出乚交尾GvG935| 国产精品久久久久久久久久| 五月丁香啪| 婷婷五月天激情网| 婷婷丁香五月天激情| 色狠狠999综合| 久热这里有精品视频| 97色婷婷成人综合在线观看| 久久人人看| 国内一级精品| 丁香六月啪| 国内一级精品| 日本高清久久| 婷婷五月天成人动漫 | 五月在线| 激情综合激情综合| 中文字幕 中文字幕明步| 天天日天天干天天天| VfJxEwPH| 久久久精品人妻录| 色婷婷六月| 荷兰av一级| 丁香婷婷激情| 97人人超| 国产精品国产成人国产三级| 欧美成人AAA片一区国产精品| 五月婷婷六月激情| 色色色无码| 久久婷五月天| 99久久国产宗和精品1上映| 八戒青柠影视剧在线观看| 在线观看国产高清视频免费网站 | 5月婷婷激情网| 日日操日日爽| 亚洲午夜一区二区| 五月丁香婷婷综合网| 亚洲色五月婷婷| 日产精品久久久久久久蜜臀| 99视频热99| 免费啪啪啪网站| 91九色 婷婷| 五月婷婷综合激情网| AV堂狠狠干| 色天天久婷婷| 婷婷五月六月| 婷婷五月激情小说| 久草婷| 99日逼视频| 蜜臀丁香黄色婷婷五月天| 欧美综合激情五月丁香| 丁香婷婷色情社区成人小说| 亚洲区视频| 青青草免费公开视频| 字母不卡码人逼| 婷婷97碰碰| 国产精品久久99| 六月丁香激情婷婷| 亚洲永久四色| 欧美偷偷操| 天堂久久精品| 天天爽天天做| 丁香五月六月| 涩涩激情五月婷婷| 天天舔天天摸天天射| 欧美成人性爱网| 亚州色色色| 亚洲182在线观看| PORNY九色9l自拍视频成人| 激情5月婷婷狠狠干| 拳交大逼| 亚洲欧美在线观看| 国产免费AV在线| 激情综合网婷婷久久| 在线只有精品| 五月Huangsewang| 99九九在线| 婷婷五月天亚洲综合| 91性高潮久久久久久久久| 99热精品在这里| 九九综合88| 99在线视频免费| 狠狠操天天干| 97在线天堂| 丁香五月天色综合| 综合久久久| 日韩专区五月天婷婷丁香| 中文字幕av在线| 天天摸色吧天天摸色吧| 在线观看国产高清视频免费网站 | 日日操夜夜爽| 婷婷九月狠狠色| 五月欧美色色五月| 精品一区二区三区四区五区六区| 亚洲操操| 亚洲性爱电影| 人人妻人人澡人人爽| 婷婷五月天亚洲综合网| 99热| 97色色色色色色色| 99精品在线| 日本系列_4页_777FP| 精品人妻一区二区三区四区不卡在| 九九综合影音先锋| 婷婷五月天深爱| 丁香五月影院| 九九熱最新視頻| 激情婷婷丁香五月天| 亚洲AV无码成人精品区电影网| 久久久区区一久久久久久| 另类小说五月天| 日本激情91| 色欲婷婷五月天丁香| 99ri精品在线| 色五月婷婷网| 99re这里只有精品首页| 免费看片操逼| 激情六月综合| 色五月成人网| 五月丁香激情综合网| 五月天婷婷xxx| 天天色宗合| 婷婷色在线| 69精品人人人人| 亭亭五月丁香综合欧美| 免费黄色片子| 97久久视频| 色99视频| 大香av| 永久免费一区二区三区| 影视av久久久噜噜噜噜噜三级| 狠狠干综合| 狠狠综合区| 色5月婷婷色| 五月婷婷色色网址| 久久久婷婷婷| 婷婷玉月丁香五月在线视频| 五月婷婷先锋| 丁香婷婷色| 亚洲操逼片| 高清无码网址| 99热的无码| 色婷狠狠| 97五月天婷婷| 综合爱久久| 久久五月激情综合| 婷婷丁香五月激情综合站_久久五月丁香激情综合_开心五月综合激情综合五月_婷 | 激情小说五月丁香在线视频观看视频| 免费视频在线观看的网站| 五月婷婷激情综合拍| 亚洲男人的天堂婷婷色五月| 久去色色| 国产偷人爽久久久久久老妇APP| 丁香5月啪啪| 免费99色| 4438亚洲欧美| 天天爽天天日| 婷婷欧美| 天天爽天天做| 欧美色色色色色色色色色色影视| 久久久久久久久久91| 日韩限制级大尺度黑料泄密大尺度视频一区二区在线观看 | 婷婷丁香六月| 欧洲亚洲免费视频9| 99在这里有精品| 五月天婷a在线| 丁香五月区| 男女激情久久| 国内一级片| 亚洲综合九九| 这里只有精品免费视频| 五月综合久久| 伊人日日干| 碰碰女| a级毛片一区二区免费视频| 丁香五月大香蕉| 五月婷婷六月激情| 成人丁香五月天| 欧美综合五月丁香六月婷| 日韩欧美一区二区三区四区| 99re免费精品视频| 丁香五月婷婷色情综合| 超碰在线观看9| 超碰精品国产首页| 97人操| 超级碰91| 五月婷婷av| 国产另类综合| 婷婷丁香五月亚洲免费| 久久人妻在线| 五月丁香婷婷成人综合网| 国产又黄又爽又激情不遮挡视频在线观看 | 91精品综合久久久久久五月天| 一级片操逼视频| 亚洲精品久久久无码| 久久免费精彩视频| 乱精品一区字幕二区| 青草视频在线观看视频| 人妻丰满精品一区二区A片| av大香蕉| 蜜乳av一级av| 曰本aaaaaa丈片| 玖玖玖婷婷婷| 全高清无码视頻| 色啪影院| 久久99最新| 天天综合图片| 五月婷色激情五月| 丁香婷婷六月| 六月色色| 亚洲亚洲人成综合网络| 丁香五月玖玖| 99热精品99| www.zbzhongsen.com| 九九视频免费| 热的无码综合视频| 丁香色五月天| 激情综合五月| 日本欧美成人片AAAA| 丁香99| 久久精品99久久| 五月丁香六月婷婷精品| 西瓜美女a片| 综合网天天| 91色久| 夫妇交换刺激做爰| 人操人| 超碰成人电影| 狠狠狠狠狠操| 伊人五月婷婷| 青草青草视频2免费观看| 91 久热| 色色免费网站| 色婷婷丁香AV综合| 日日夜夜干| 亚洲1区| 激情五月天情色| 久9视频| 丁香五月天欧美在线| 国产精品VA在线| 丁香六月综合| 日本天堂久久| 狠狠干天天内射| 性爱视频99| 五月天开心网| 婷婷狠狠97| 亚洲舔观看| 五月婷婷激情综合av| 五月婷婷六月激情| 蜜臀99久久精品久久久久| 开心婷婷五月激情网小说| 99热精品在线免费观看| 亚洲精品成人| 色五月激情综合| 呦呦视频无码播放| 99热97| 97碰在线免费观看| 丁香久久五月天视频在线观看| 五月激情婷婷综合| 日逼影音先锋AV男人资源站| 五月婷婷六月丁香综合视频在线| 精品女人九九九| 人妻视频一区而且二区| 丁香五月在线伊人| 色婷婷综合亚洲| 婷婷五月激情在线| 婷婷六月丁香久| 日韩成人电影AV| 亚洲成人av在线观看 | 538任你爽| 另类亚洲电影| 久久人妻情侣| 婷婷爱五月| WWW.99热| 九九99九九99| 亚洲九九婷婷| 丁香婷婷激情网站| 超碰在线观看三级片| 丁香六月婷婷综合色| 午夜成人网站在线观看| 99热99草97| 免费观看欧美成人AA片爱我多深| 在线看九一V图片| 久久草人妻| 五月大香蕉| 精品久久9| 色五月偷偷| 亚洲热久| 久久人妻人人| 九九久久免费视频44| 九九性视频| 九月婷婷在线视频| 九九九九九九九热| 日日鲁鲁鲁夜夜爽爽狠狠视频97| 成人婷婷桔色| 超碰99在线| 影音先锋xfplay资源男人网| 热久久这里只有精品| 色色综合无码| 五月天激情四射| 日日日,com| 99色色网| www.91有码.com| 日韩人妻AV在线| 色五月婷婷天天操夜夜操| 中国无码av| 色婷婷狠狠久久综合五月| 狠狠干.com| 精品A√| 色色色色色五月| 婷婷娌伦网| 婷婷色啪| 久久久噜噜噜久久人妻| 五月丁香啪啪啪免费看| 农村熟妇高潮精品A片| 激情五月丁香色婷婷| 欧美性生交XXXXX无码小说 | 综合五月激情| 六月婷婷五月天| 天天综合91入口| 亚洲不卡| 亚洲综合新99视频| 丁香五月天大香蕉啪啪| 天天综合在线网| 伊人网碰碰| 激情五月天网站| 五月天激情AAAA| 东京热人妻一区二区三区在线| 五月丁香偷拍| 91久久久久久| 中文字幕日本最新乱码视频| 99re最新地址| 亚洲六月色婷婷| 丁香五月综合| 思思热在线播放| 99久久久免费| 欧美69久成人做爰视频| 99热免费看| 夜夜 操无码| 成人美女网| 久久丁香五月天| 激情文学 综合 色| 五月丁香久久激情综合| 成人婷99最新| WWW.桔色成人.COM| 日本一级特黄大片AAAAA级| 九九色综合| 777色色色| 永久的网站AAAA | 久久人人九九| 色综合久久天天综合网 | 极品人妻VIDEOSSS人妻| 五月激情六月丁香| 99爱这里只有精品| 国产精品人妻在线网址| 国精产品一区一区三区免费视频| 色婷婷成人| 色婷婷成人丁香| 成人网页在线观看| 黑人糟蹋人妻HD中文字幕| 可以看的av网站| 狠狠 婷婷| Www99热| 七月丁香婷婷 色色| 超碰人人操人人干| 婷婷五月天另类网站| 国产激情视频在线观看| 五月婷婷 自拍| 大香蕉av在线| 久久多色| 99爱视频在线观看这里只有精品| 激情丁香婷婷五月天| 亚洲在线视频321| 4438亚洲欧美| 99综合网| 人人97碰| 婷婷五月综合网| 天天操夜夜夜拍拍拍| 欧美va视频| 1024亚洲| 成人AV片播放| 久久人妻熟女一区二区| av大香蕉| 久久总和99| 婷婷天天婷婷天天澡| 激情丁香网| 乱女乱妇熟女熟妇综合网站| 日本三级日本三级三级人妇四虎| 亚洲精品网址| 大香久久综合网| 激情内射人妻1区2区3区| 五月花免费视频| 中文字幕综合| 亚洲视频99| 丁香五月开心婷婷| 五月丁香欧美| 亚洲尤物在线| 丁香激情合作五月| 婷婷在线观看五月天在线视频| 操逼视频一区| 婷婷五月丁香花综合| 久久亭亭电影| 五月激情婷婷偷拍| 毛片九九九九九九九九18| 午夜天堂一区人妻| 国产做A爰片毛片A片美国| 久久小视频| 99亚洲精品| 99这里只有精| 伊人色综合网| 99色热| 午夜婷婷| 99噜噜噜在线播放| 色www久视频| 色五月婷婷777| 狠狠色噜噜狠| 狠狠婷婷日韩| 亚洲视频久久| 国产精品色婷婷久久久精品| 成人色图情色成人网 www.5b5b5bcom 五月天| 婷婷五月天丁香综合网| 大香伊人婷婷影院| Caop在线| 色婷婷免费视频| 色色色99| mmm1717.6dbm人人爱人人操| 婷婷操逼网| 五月婷婷欧美激情| 亚洲五月花| 1024操逼视频| 色爱亚洲| 欧美性猛交AAAA片黑人 | 激情内射人妻1区2区3区| 精品久久久中文字幕大豆网推荐理由| 色婷婷狠狠禁18久久| 丁香五月婷婷国产在线| 一区二区三区XXXXXX| 伊人www22综合色| 婷婷月五天在线在线看| www.狠狠操.com| 五月天 另类图片| 色婷婷婷婷| 久久精品婷婷| 亚洲色五月| 亚洲色99综合天堂| www91久久| 草综合网| 天天射综合网夜夜操| 天天爽天天摸天天爱| 色五月天堂| 成人综合网站| 亚洲天堂碰碰婷婷| 大香蕉婷婷五月天| 激情丰满熟妇五月| 伊人在线视频| 99在线精品观看99| 91综合网| 日韩色色色色色| 丁香久久五月天视频在线观看 | 激情久久综合| 热99re| 外国碰视频网站97| 任你躁XXXXX麻豆精品| 欧美亚洲成人在线| 五月花综合网| 在线综合网| 97在线精品| 婷婷伊人五月丁香天堂网| 九月婷婷| 五月天亚洲色| 日日夜夜干| 激情无码网| 伊人狠狠狠综合| 五月丁香久久网| 久草婷婷在线| 亚洲综合激情五月久久| 啪到高潮激情丁香五月| 天天插天天干| 91九色中文| 亚洲人妻一区二区 | 99国产精品白浆在线观看免费| 五月丁香久久婷| 成人羞羞啪啪 全 视频| 久久玖玖综合| 激情综合丁香六| 天天爽爽日日做做| 99这里有精品视频| www.97视频| 天天色播| 99热在线看片| 亚洲AV无码电影| 色色色视频免费无码 | 婷婷五月综合激情| 亚洲综合五月天婷婷| 国产全是老熟女太爽了| 丁香五月婷婷啪| 丁香六月无码播放| 日本不卡一区二区三区| 青草青草久热这里只有精品| 高清无码视频网址| 五月婷婷啪啪啪啪| 久久这里面只有精品视频| 色爱综合网| 亚洲精品成人片在线播| 开心五月深爱激情| 97精品人人A片免费看| 婷婷伊人綜合中文字幕| 综合99视频| 人人操人人添人人摸97| 热的无码综合视频| 99ER热精品视频| 色五月丁香总合网| 婷婷色网| 久久性爱视频| 成人五月丁香社区| 免费看无码视频A级| 夜夜躁爽日| 五月丁香亭亭A片| 色婷婷香蕉丁丁网| 黄色三级毛片中字| 久久6这里只有精品| www.婷婷五月| 色婷婷手机在线| 五月婷婷天| 玖玖综合色| 五月丁香影院| 91超级碰碰碰| 久久九九免费视频| 婷婷久久综合久| 99久re热视频精品98| 99啪| 色婷婷影视| 久久五月婷婷电影| 久久a热| 色丁香五月婷婷婷| 色999;丁香五月| 丁香五月六月久久综合| 超碰在线看| 日韩抽插操逼| 7EzOBIhNq85TO| 日日操人人操| 99久久婷婷国产综合亚洲| 久久九九视频| 丁香五月婷婷五月| 狼友视频在线观看18| www.婷婷五月天.com| 岛国AV网| 欧美激情五月天在线观看| 欧美性生交XXXXX无码小说| 第四色婷婷色五月| 在线色婷婷| 夜夜干夜夜操| 国产成人高清| 综合五月婷婷| 五月亭亭激情综合| 欧美日本国产| 日日爽夜夜爽| 97av在线视频| 欧美搡BBBBB摔BBBBB| 日韩人妻操逼视频| 国产免费一区二区三州老师F1F1……| 香蕉人在线香蕉人在线 | 婷婷五月天六点丁香五月| 色婷网| 五月婷婷九月婷婷九月婷婷| 一起草av在线观看| 99免费| 青青草视频福利| 91人碰| 五月丁香六月| 精品草原久久视频| 五月婷婷色啪| 色婷婷基地| 99热这里只有精品18| www.91九色| 久久精品99国产精品日本| 俺也去在线视频| 婷婷四色五月| 综合色、色综合| www.天天干| 蜜臀A∨在线水帘洞| 91怕怕网| 婷婷五月综合网| 久久激情五月天| 色综合九九| www,婷婷,com| 色综合综合色| 五月婷婷久久网| 9l视频自拍9l九色9l成人| 一起草av| 五月激情天| 婷久看人爽| 韩国19 主播内部福利vip免费播放| 99色在线视频| 九九热在线99| 9九热视频| 人人操人人看97干| 黄桃AV无码免费一区二区三区| 天天爱天天吃狠天天透| 日本va欧美va精品发布视频| 婷婷第一页| 成人做爰A片免费看网站找不到了| 五月丁香色综合| 婷婷六月插屄激情| WWW.99热| 9热在线视频| 极品人妻VIDEOSSS人妻| 六月色播| 色五月婷婷激情| 丁香婷婷激情五月色| 超碰97免费在线| 99色综合久久| 伊人久久婷婷| 欧美综合123区| 五月丁香龟婷婷| caopeng超碰| 欧美在线97| 超级97碰碰| 婷色影院| 欧洲色| 婷婷伊人网| 婷婷玖玖五月天| 婷婷综合色播网| 天天拍夜夜爽日日| 五月天激情国产综合婷婷婷就去爱| 色色婷婷色色| 在线五月婷| 亚洲字幕AV一区二区三区四区| 噜噜噜狠狠色综合| 在线观看亚洲视频影院| 激情五月,激情综合网| 丁香五月日啪| 丁香六月婷月91婷月| 翔田千里 50岁 无码| 欧美激情伊人| 五月婷天堂视频| 在线精品97| 91性交在线播放| 被强行糟蹋的女人A片| 丁香五月性| 日本丁香五月| 日夜操B| AV在线免费播放| 色色色99| 无码区婷婷五月花开| 九九在线这里只有精品视频| 五月丁香另类网| 伦99热| 深爱五月亚洲| 丁香五月狠狠综合欧美| 日日噜噜久久婷婷五月天| www.狠狠操.co m| 可以免费看av网站| 丁香五月 综合| 色色色精品无码区| 五月停停直播| 色情播放| 人人操A| 婷婷色欧美激情| 婷婷丁香色情五月天| 蜜桃五月天| 五月天久久婷婷| 九九热在线视频| 久99视频在线观看| 色综合激情| 五月婷婷六月丁香在线| 综合五月婷婷| 成人无码精品1区2区3区免费看| 成人无码精品1区2区3区免费看| 日韩成人精品中文字幕| 激情综合网,婷婷五月天| 天天爽人人爽| 婷婷亚洲色| 天天日本夜夜谢| 深爱激情五月天| 色噜噜综合网| 依人大香蕉| 婷婷丁香日韩五月| 夜色.cnm| 免费人人操| 久久9久| 五月婷婷亚洲天堂激情在线| 日日鲁鲁夜夜爽爽| 99性视频| 欧美影院婷婷| 丁香五月成人| 五月丁香久久激情综合| 激情综合网色五月| 久久五月婷婷电影| 亚洲久久婷婷丁香五月天| 毛片色五月| 亚洲色碰| 屁股翘好撅高迎合跪趴| 五月色婷丁香| 婷婷六月天天| 婷婷五月天在线综合导航| 五月涩涩网| 99毛片| 国产69久久久欧美黑人A片| 久超免费视频| 91热99| 天天狠狠色噜噜| 激情爱爱网站超大免费| 久久久久久久人妻| 九九热99在线视频| 久久九九怡红院| 99er精品视频| 操一操干一干| 婷婷五月另类网站| 色婷婷影视| 五月丁香龟婷婷| 婷婷五月天精品| 中文字幕操比影片| 亚洲成人免费电影| 婷婷五月天干干| 婷婷五月色| 激情五月丁香六月婷婷| 五月天色综合| 婷婷丁香六月天| 操97| 国产婷婷五月在线视频| 色色五月天激情| 婷婷色片| 成人婷婷五月| 婷婷综合网| 五月天大香蕉视频| 99在线视频免费| 九九99香蕉在线视频播放| 中文毛片无遮挡高潮免费| 91超级碰在线| 天天夜天天色天天| 丁香五月播播| 九九激情视频| 色小说婷婷五月天天天| 91碰超| 啪啪视频99| 狠狠另类视频| 久99久在线| 国产女生爱爱AA| 午夜丁香六月婷| 99色天堂| 久热久操久热久草国产91| 五月丁香久久久| 99热这里都是精品| 成人丁香色| 亚洲六月色| av中文网| 五月丁香啪啪激情| 久碰视频| 色欲五月婷婷| 丁香六月欧美| 色欲AVV| hd五月婷婷在线| 这里只有精品久久| AV在线中文| 久久婷婷五月综合激情国产| 91九色在线观看免费| 色综合久久久久久久久五月| 99ER热精品视频| 丁香五月天在线观看视频| AA久久| www.sebowuyue| 激情五月婷婷五月丁香五月开心五月 | 色婷婷狠狠禁18久久| 人人爱天天摸摸天天爱| 五月丁香六月激情| 影音先锋按摩| 4399成人黄A片| 黄网免费观看| 九九综合伊人| 人人综合久| 99在线视频精品| 91人操| 五月婷婷中文字幕| 色婷婷天堂| 色婷婷88| 六月丁香综合| 97操视频| 五月丁香激情综合网| 99热自拍| 亚洲Va成人| 亚洲综合激情五月久久| 天天爽在线视频| 五月花婷婷| 天天上天天爽| 国产69久久久欧美黑人A片| 五月永久激情| 久久这里只有精品视频15 | 五月开心婷婷|