99精品久久精品一区二区-亚洲熟妇无码?v在线播放-日本国产精品无码字幕在线观看-久久久亚洲永夜AV-亚洲一级无码一区二区一-免费国产成高清人在线视频-中文字幕乱码免费观看-国产毛片精品妇女久久久

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
返回資訊列表
色综合色综合色综合高潮| 婷婷成人网五月天| 青青草视频免费观看| 97超级碰人人| 婷婷丁香十月| 色婷婷激情| 久久ER视频com| www.久9| 四色99久久| 爱草视频在线观看| 色欲婷婷夜夜| 综合激情五月丁香| 国产精品人妻欲求不满| 婷婷六月综合基地| 碰碰碰91| 99玖玖视频| 人妻中文在线| 激情小说五月天| 26uuu亚洲精品国产| 亚洲视频二区| 99热综合| AV电影在线播放| 操熟女成人网| 99热99这里免费的精品| 人妻操操色| 色婷婷黄色网络| 九九人人看| 色婷婷网大全在线| 操91综合网| 五月丁香六月色| 日韩99视频| 婷婷开心久久| 色噜噜狠狠一区二区三区| 国产精品噜噜在线视频| 丁香五月成人论坛| 色婷婷丁香五月天激情综合网| 91碰碰碰| 天天成人综合| Jh7Uf088VHafNm| 袁子仪视频观看| 噜噜干日本| 日韩人妻无码精品| 99热伊人| 中文无码精品一区二区三区| 99热这里只有精品50| 国产精产国品一二三在观看| 日韩av一区二区在线/日产精品久久久 | 五月婷视频在线观看| 人人摸人人干| 激情5月婷婷| 天天爱天天天射AV| 五月天之色情综合网| 亚洲AVwwwwwww| 九久九精品| 北条麻妃九九九国产精品视频| 国产毛片欧美毛片久久久| 深爱五月婷婷| 久久久aaa| 热思思九九| 六月丁香网| 五月花婷婷| 可以直接看的AV| 狠狠狠狠狠干| 色色六月| 九九成人精品免费视频| 婷婷六月中文字幕| 超碰人人91| 五月丁香婷婷中文| 99精品偷自拍| 久久999久久999久久999久久| 久久99精品久久久久久青青AR| 中文字幕第四色.999| 99热免费精品| 亚州美女| 五月丁香激情啪啪网| 综合色影院| 另类图片激情五月| 丁香五月天婷婷中文| 五月婷婷精品无在线| 五月丁香六月婷婷亚洲综合| 亚洲天堂色色| 婷婷色偷拍| 91精品久久久久久| 五月丁香在线看| 丁香色综合| 婷婷五月天视频| 婷婷色色网站| 色久播播| 亚洲激情另类| 91干婷婷| 凹凸探花电影| 97综合在线| 国产日韩精品SUV| 日日噜噜久久婷婷五月天| 操碰久| www.激情.com.| 色情久久久| 操操自拍| 激情婷婷视频在线| 久久五月天激情视频| 天天操比比| 丝袜大香蕉| 日本欧美999久久久三级片| 99ri国产在线| 久久婷婷综合国产| 婷婷丁香五月天之开心少妇| 国语对白性爱视频播放| 97干97色| 天天干天天操天天射| 五月婷婷伦理| 激情综合网五月天天| 天天xxxxxx天天日| 亚洲欧洲另类| 色五月首页| 婷婷狠狠五月综合| 婷婷五月花| 色射7856五月天激情四射| WWW.99热| 99热大香蕉| OYIWbGcPu8H| 99性视频| 级情九色| 99热大香蕉| 激情丁香五月婷婷啪啪| 成人国产网站在线免费看| 黄网在线免费观看| 五月天堂婷婷| 婷婷五月丁香啪啪| 五月丁香av中文| 日韩av免费版| 色婷婷先锋| 欧美99热| .操區COm| 国产99久久久国产精品免费看| 最新色色五月天| 激情五月天综合婷婷网| 九九色天堂| 天天操,夜夜骑| 精品一二三区久久AAA片| 99爱视频免费| 综合97五月| 色99热| 色五月色五天色情网址| 人人干人人操人人摸| 99热久久这里只有精品| 天堂AV在线看| 丁香六月激情国产| 99热这里只有精品8| 婷婷久久色| www.开心激情| 色五月97| 女婷久久| 99er免费在线观看| 精品一区久热| 久色资源| 大香蕉五月天| 五月天大香蕉| 就爱射中文字幕资源网| 狠狠爱激情网| 国产婷婷色五月| 六月婷婷色综合| 久久综合爱| 99综合视频| 久久综合婷婷| 天天日天天肏天天奸| 97深爱伊人综合| 国产欧美精品AAAAAA片| 色综合激情| 日韩美一级毛卡片| 99日韩| 96丁香六月婷婷蜜桃综合久久| 五月婷婷六月天| www.黄色片-久久成人国产精品在线播放-999AV | 欧美激情综合色丁香婷婷五月天| 第五婷婷伊人丁香| 99精品热| 丁香五月性爱爱五月| 激情综合一| 色色色色色五月丁香| 99热亚洲精品| 亚洲视频丁香网va| 色婷婷色九月| 国产免费性爱| 激情久久久久| 手机AVAV天堂看网| 激情五月婷婷视频一区二区三区| 性爱综合网| 五月丁香婷中文字幕| 色色色色色色综合网| 99这里是精品| 婷婷五月激情四月综合 | www.婷婷五月| 成人超碰网| 99色精品| 我爱宗和色| 9999热免费视频视频| 能看的av网站| 五月天成人网婷婷| 久久婷婷五月天蜜桃| 色婷婷六月| 激情综合另类| 五月婷婷新网站| www。五月,com| 五月丁香久久网| 综合色天天| www久久久久久| 99视频久久| 五月丁香婷婷三级| 婷婷5月开心6月| 日韩美女在线视频19| 五月丁香六月天| 99日韩网站| 六月激情婷婷| 思思re99视频在线观看| 六月天六月婷| 精品人妻伦| 99视频91| 久艹久| 婷婷综合久久| 亚洲精品成人| 超碰99热精品| 婷婷九月丁香| 99热这里只有精品86| 天天操夜夜啊| 五月色情婷婷| 久久狠狠欧美| 伊人激情综合网| 精品日本视频444| 六月丁香五月天| 天天做天天爱| 亚洲综合色色色| 久久婷婷五月天激情| 激情床戏| 97啪啪| 综合色色色| 日日做天天操夜夜爽| 99精品在线观看| 丁香五月777| 婷婷色色宗合网| 草草夜夜操| 大香蕉AV在线| 天天综合精品| 亚洲经典三级| 国产日产亚洲系列最新| 日韩av手机在线观看| 丁香六月综合激情| 丁香五月天啪啪| 色综合久| 99久久综合| 九九九九这里只有精品| 五月天婷婷丁香花| 色综合久久久久久久久五月| 久播影院免费观看电视剧大全最新网| 牛牛碰免费| 66精品成人免费网站在线观看| 欧美天天五月丁香免费观看| 色婷婷丁香五月天在线视频 | 9l视频自拍九色9l视频自拍九色9l社区| 1024久婷| 超碰人人91| 先锋资源婷婷| 五月丁香婷婷综合久久| 丁香五月天导航| 永久无码色| 91成人品| 婷婷五月丁香六月伊人网| 日本综合色图| 色婷婷狠狠18禁| 99热都是精品| 一本道综合网| 五月天婷婷婷| 成人一级片| 91狠狠色| 99久久九九视频| 成人在线观看精品| 久久久99日本大片| 激情五月图| 91热er| 色噜噜,噜噜色| 婷婷五月丁香五月天| 色狠狠图片| 婷婷爱五月天人人爱| 婷婷五月天免费视频| 丁香五月六月婷婷综合| 精品久热| 天综合日日夜综合7799| 99热99色| 人人摸人人干人人做| 五月天婷婷综合免费| 99热爱爱干干日| 激情网站综合五月天| 思思热久久婷婷五月天| 超碰人人干| 99精品久久| 欧美日韩成卜| 狠狠香蕉| 五月丁香六月情| AV在线观看网站| 五月天色色网站| 青青草伊人婷婷| 婷婷五月18永久免费网站| 人妻中文在线| 精品A√| 婷婷射丁香| 色婷婷视频| 久久久精品99| 怡红院院久久| 婷婷丁香五月综合| 在线网黄| 久久全意婷婷| 成人日韩欧美| 婷婷六月天激情| 丁香五月五月婷婷| 六月婷婷网| 包操45分钟网站| a久久免费视频| 夜夜大香蕉婷婷丁香| 野战J办公桌椅H| 99热丁香| 天天噜噜| 色婷婷8| 久久色五月| 婷婷香五月综合激情| 久色网| 久热re视频在线观看网站| 久久色天堂| 久热AⅤ| 丁香五月婷婷啪| 超碰不卡在线| 日本人妻操| 丁香五月婷婷成人色区| 天天干天天做| 久久婷婷五月综合| 99久在线精品99re8| 中文网婷婷字幕婷| 五月情色天| 国产做A爰片毛片A片美国| 97色啪| 五月婷婷开心亚州在线| 五月天色小说| 五月色婷婷AV| 国产欧美精品AAAAAA片| 亚洲综合色网站| 色色色色综合网| 婷婷久久在线| 久草热在线视频| 99re欧美精品| 99小视频网站| 丁香操逼| 色婷婷久久综合中文久久一本| 强辱丰满人妻HD中文字幕| 99热乎| 婷婷六月色开| 久久五月婷婷电影| 五月丁香六月综合激情 | 色婷婷综合亚洲| 99精品久| 天天插天天爽| 97色色婷婷五月天| 97中文在线| 免费亚洲婷婷中文字幕| 五月天久久婷婷| 亚洲永久免费| 97色色色| 人人看人人摸人人| AV免费在线网站| 欧美婷婷五月天| 亚洲免费电影2| 婷婷五月六月| 92国产福利| 婷婷人人操| 大香蕉五月丁香| 九九五月天| 色欲人妻综合aaaaaaaa网| 日本片日本片祼观看网站在线看中文版网页在线看 | 亚洲VA口| 五月婷婷另类| 婷婷五月天VI| 婷婷色综合| 国产成人在线不卡AV| 日本高清久| 国产激情AV| 狠狠操狠狠操| 蜜乳国产网站| 99热免费精品| 疯狂做受XXXX高潮A片动画| 婷婷丁香六月影视| 99热这里只有精品8| 99视频九九热| 韩国真做片在线观看| 五月婷色丁香| 在线超碰91| 日本色婷婷| 亚洲丁香婷婷五月天综合色| 97成人视频| 丁香五月最新地址| 婷婷六月丁香久| 91人人妻人人操人人爽| 婷婷五月六月| 五月激情天天干| 久久资源网五月婷| 九月婷婷人人操人人舔人人爱| 伊人婷婷五月天| 婷婷丁香69精华| 丁香五月之久操视频| 五月婷婷之综合激情| 久9视频| 激婷网| 99无码| 在线五月色播| 色五月婷婷在线| 色婷婷五月天综合网| 97超级操操| 99久久九九| 99热99re6国产在线播放| 99riAV国产精品视频| 婷婷五月在线视频| www.91九色| 亚洲乱码成人| 人人草公开操| 日韩在线视频网站| 性色综合网| 久久综合婷婷| 99ri国产| 国产精品爽爽久久久久久| 人人人人人人人人人草| 五月天堂婷婷| 人人操操| 69人人操人人爽| 婷婷五月色播| 亚洲综合色婷婷| 丁香五月婷婷激情完整版| 九九热精品| 久久视频婷婷| 婷婷五月婷| 99热99热在线观看| 99热免费网站| 久久综合激情| 丁香久久综合| 超碰不卡在线| 九九热青青草| 香港九九六区八区99| 丁香五月婷婷啪啪| 亚洲精品99| 激情久久久久久久久| 天天高潮夜夜爽| 婷婷五月天视频小说| 久久精品爱爱| 99在线观看视频免费| 久久久久久久久久91| xxxx五月天色色| 超碰婷婷五月| 五月天久久小说| 日本乱子人伦在线视频| 全部老头和老太XXXXX| se99视频| 另类婷婷丁香| 97色色色视屏| ...婷婷国产成人亚洲日韩| 中文字幕婷婷| 天天插天天玩天天干| 另类激情五月| 热中文字幕| 久/久精品99看9| 婷婷五月综激情| 婷婷色偷拍| 91jiuseshunv| 99久久精品国产色欲| 丁香五月婷婷久久久| 久久五月天精品视频| 色综合激情图区| 婷婷五月天97干| 激情综合网激情五月婷婷| 婷婷99狠狠躁天天久久久九九九| 4399啪啪视频| 狠狠色综合网站久久久久| 真实熟女-91九色| 亚洲欧美成人在线观看| 99超碰在线免费| 婷婷伊人75| 天天日夜夜欢| AA片在线观看视频在线播放 | 精品亚洲国产成AV人片传媒| 久久婷婷五月综合色丁香花| 精品操逼一区二区| 人伦30P| 亚洲视频五区| 色婷婷丁香五月高清在线| 五月丁香啪啪拍| 五月天激情子轮| 天天插综合| 操日视频| 色婷婷狠狠18禁| 国产全是老熟女太爽了| 丁香五月天社区婷婷| 9久9久| 色婷婷激情| 欧美丁香婷婷天天操| 深爱五月天 开心网| 天天天综合网| WWW.婷婷| 六月丁香开心婷婷欧美| 日韩999| 亚洲久久婷婷丁香五月天| 日本操逼九九九九58日本操逼| 五月丁香综合在线| 丁香婷婷六月| 色爱综合五月| 五月丁香六月日逼| 色天堂在线| www.色综合| 婷婷六月香| 激情久久综合| 99re这里只有精品视频了| 色天堂A| 亚洲无AV在线中文字幕| 夜夜躁婷婷AV| 天天日夜夜爽。| 婷综合| 91狼友视频在线观看| 亚洲成人在线免费| 色婷婷六月丁香综合欲精品| 丁香五月成人| 丁香五月婷婷亚洲综合精品| 五月天色婷婷网| 亚洲中文乱字字幕在线永久| 玖色色综合| 思思视频这里是精品| 五月丁香六月欧美综合网站| 人人人操 超碰| 免费黄色片子| 色五月丁香婷婷久草| 亚洲综合婷婷五月天| 任你爽精品免费视频6| 97色婷婷| 五月色亭丁香| 色情综合| 久久综合影院| 激情五月天小说|五月天开心激情网|亚洲精品国产自在现线|黄色五月天 | 天天舔夜夜操www com| 亚洲婷婷欧美婷婷| 婷婷天天五月天| 国产婷婷五月中文字幕高清| 亚洲热久久| 超碰99热精品| 人妻精品一区二区三区| 色婷婷中文| 热这里只有精| 婷婷伊人| 久久最新色色色| 97碰久久| 色婷婷五月色| 中文久久婷婷| 国产99久9在线| 这里只有精品免费观看网占| 丁香五月天大香蕉啪啪| 久久婷婷五月丁香| 99热最新| 91日婷婷在线| 婷婷五月天电影区小说区| 屁股翘好撅高迎合跪趴| 亚洲五月天综合| 五月婷婷色| 婷婷色网| 欧美交换配乱吟粗大25P| 久久免费精品小视频| 五月综合激情| 伊人久久婷婷| 天天干夜晚夜操| 玖玖综合色| 九色PORNY自拍成人精彩视频| 婷婷欧美激情| 婷婷黄色| 色五月天天在线观看资源站| 国产午夜精品AV一区二区麻豆| 婷婷五月天改成什么了| 拍真实国产伦偷精品| 国产在线6| 激情综合亚洲| 夜夜爽日日躁| 97久操| 夜夜骑夜夜操| 五月天丁香综合| 97超碰综合| 婷婷偷拍网| 午夜一区| 涩玖玖免费视频| 色五月综合在线| 123草逼网| 亚洲午夜AV| 欧美天天爽| 久久人妻熟女一区二区| 五月天激情啪啪| 欧美成人日韩| 六月婷婷中文字幕| 六月丁香婷婷尤物| 99爱爱网| 极品人妻VIDEOSSS人妻| 天天爽天天日天天舔| 伊人综合婷婷| 色五月婷婷网| 亚州色色色| 五月丁香福利| 高潮毛片又色又爽免费| 日本在线va| 久久五月婷| XX色综合| 91九色熟女| 99热 在线观看| 国内9l视频自拍老熟女九色| 9|无码久久久久久| 99热这里只有精品一| 五月天丁香成人社| 日韩激情婷婷五月天| 五月综合激情图片| 天天综合精品| 国产激情综合五月久久| 99热99思午夜精品| 日本在线99| 日本色色色| 五月亭亭性| 亚洲人人96@| 99久免费视频| 成 人片 黄 色 大 片| 五月天天久久香| 五月色情婷婷开心五月色情| 婷婷综合一二三| 中文字幕日产A片在线看| 91精品久久久久、久五月天| AV五月丁香| 超级碰碰91| 天天揷综合网| 天天爱天天操| 午夜婷婷久久 | 激情综合网激情五月欧美| 五月激情婷婷综合| www.cao.com久久| 欧美性爱五月天| 婷婷大乡焦噜噜| 色婷婷在线视频综合| 国产99久久久国产精品免费看| 夜夜谢天天干| 大陆肏屄视频| 亚洲婷婷六月天| 五月天大香蕉| 九九人人自拍| 综合超碰熟| 久久久全国免费视频| 91久久婷婷| 久久久WWW| 深爱激情五月天| 丁香六月婷婷一区二区三区| 俺五月| 99 热国产在| 五月天婷综合| 91疯狂操操操操| 嫩草视频。| 日韩av一区二区在线/日产精品久久久 | 狠狠五月激情丁香六月| 久久这里只有精品16| 777久久综合视频| 青草网在线观看| 91超碰九色| www.maotanji.com| 五月婷婷婷综合网| 国产精品操| 1024成人在线观看| 色娸娸综合网| 色婷婷色情| 99操视频| 丁香五月天堂网| 中文字幕综合网| 色九月婷婷丁香| 婷婷五月天小说| 69色婷婷| 九九99九九99偷拍视频免费看| 天天舔天天摸| 久久精品视频99| 久九色| 99热网站| 五月激情小说| 色伊人91在线视频| 91丨九色丨国产打屁股网站| 九九九九中文字幕| 99精品97| 日本99视频| 五月天激情小说婷婷| 密黄站| 精品综合久久久久久五月天| 91大屁股| 色综合色色色| 99超级碰免费视频| 国产精品a无线| 亚洲色无码A片一区二区麻豆| 国产又爽又猛又粗的视频A片 | 99热精品在线播放| 精品亚洲国产成AV人片传媒| 色99综合色88| 五月叮香啪| 五月丁香琪琪| 五月丁香WWW| 激情五月婷婷丁香综合网 | 99性色| 丰满少妇猛烈A片免费看观看 | 午夜丁香婷婷| 婷婷五月天av| 五月丁久久| 青青草99热久久精品国| 婷婷她六月天| 婷婷激情五月天小说| 99re热99| 丁香六月爱综合| 去色色五月天| 亚洲成人乱码av网站| 五月丁香啪啪激情| 五月天婷婷在线播放| 久月婷婷| 五月婷婷综合在线亚洲视频| 五月丁香少妇| 99热这里只有精品98| 天天综合社区| 26uuu欧美| 免费操超碰| 激情五月第四色| 婷婷播5月| 五月婷婷五月天| 婷婷丁香黄色| 欧美成人热| 五月婷婷六月激情| 黄色片久久| 99碰超| 日韩精品二三区| 深爱开心激情| 玖玖婷婷婷丁香五月| 五月天天天开心激情网| 人人操97| 99精品网址| 激情综合色五月六月婷婷| 日韩 中文 欧美| 超碰97在线观看免费| 色五月婷婷久久| 亚洲成人五月天| 青青草国产亚洲精品久久| 97久人人| 狠狠色综合精品视频在线| 色色五月婷| 五月丁香成人| 五月婷婷五月天| 丁香婷婷成年| ...婷婷国产成人亚洲日韩| 91.com男女操| 五月婷免费视频| 欧美天天干天天草| 国产真人做爰视频免费| 97色色色色| 99热青青草| 久xxxx| 五月婷婷综合在线观看| 4438亚洲欧美| 五月婷人妻| 五月婷婷深深爱| 久月婷婷| 色五月综合| 五月狠狠| 久久久欧美精品sm网站| 六月丁香综合| 免费观看日韩成人av| 五月天激情日色在线| 777影视理论片大全在线观看| 丁香五月综合| 九九黄色网| 91人人操人人| 91Chinese在线| 丁香六月啪啪啪| 丁香六月狠狠干| 97干在线观看视频| 九九久久99精品免费观看www| 五月丁香成年黄色| 看片视频在线免费日产在线看| 久久久久视剧HD| 亚洲色无码| 91人人看| 欧美狠狠色| 4399在线观看免费毛片| 成人AV中文字幕| 14色综合婷婷| www,天天干| www.25五月婷婷| 乱精品一区字幕二区| 色婷婷综合五月| 男人大jjc女人免费视频| 婷婷伊人久久综合| 97热超碰| 色综合综合色| wuyuedingxiang99| AV在线不卡播放| 噜噜久| 五月婷婷丁香六月| 色情综合| 狠狠va| 噢美99| 99色热| 日本色色图| 亚州美女| 99热在线免费| av在线中文| 色五月丁香五月| 婷婷五月婷婷五月天| 涩玖玖免费视频| 色五月天激情| 丁香六月高清视频| 中文字幕婷婷在线| 色婷婷成人| 天天舔天天插天天干| 性爱五月婷| 五月丁香成人网| 天天综合亚洲综合| 97综合在线| www.五月激情.com| 欧洲区自拍| 色99网| 五月婷婷六月基地| AA久久| 久久国产一区二区三区| www.五月.com| 久久er免费视频| 韩日AV片| 九九在线视频| 亚洲婷婷五月天激情| 久久久久久久丁香五月天婷婷| 国产免费性爱| 五月天堂色| 久久久区区一久久久久久| 草榴视频网| 少妇熟女视频一区二区三区| 婷婷丁香五月网| 婷婷五月天成人动漫| 97超碰欧美中文字幕| 五月丁香啪啪网| 久久婷婷综合五月天| www.夜夜操.con| 久婷久婷激情肉| 超喷97免费在线视频| 婷婷中文无码| 五月天色婷婷网| 色激情综合狠狠婷婷| 4399欧美另类视频| 丁香五月五月婷婷欧美大香蕉| 狠狠爱激情网| 色婷婷五月天小说| 五月婷婷激情四季| 手机旧版看人妻1025| 天天操夜夜橾| www.25五月婷婷| 97干在线观看视频| 亚洲国产网址| 拍真实国产伦偷精品| 色婷婷成人网| 日日色综合| 99热精这里只有精品| 色婷久久| 丁香五月色网| 青青操成人福利| 国产人妻人伦精品一区二区| 色综合综合色| 婷婷五月天基地| 五月激情五月婷婷五月天在线| 久热这里只有精品在线观看 | 97操碰在线视频| 中文字幕在线视频播放| 国产精品扒开腿做爽爽爽A片唱戏| 亚洲操人| 999婷婷综合| 色爱综合网| 色婷婷综合网| 色色色综合色| 夜夜操激情| 色青五月天| 激情五月婷婷伊人| 亚洲丁香五月天在线视频| 天天性视频| 综合久久综合久久| 婷婷综合97| 九月婷婷激情| 国产精品色婷婷99久久精品| 九九色天堂| 伊人9草在线观看| 狠狠色噜噜狠狠亚洲A∨| 人妻激情久久| 91碰人人| 欧美日韩精品一区二区三区钱| 亚洲午夜国产成人电影VA国产欧…| 精品无码久久久久久久久| 国产精品色| 中字幕视频在线永久在线观看免费| 六月综合婷婷开心伊人| 99热免费在线| 99爱爱| 99热这里| 九久久婷婷| 超碰成人影视| 色五月自偷自拍婷婷婷婷| 97精品综合久久内射| 色综合久久88| 婷婷五月AV| 六月色色| 婷婷五月天 偷拍| 国产免费一区二区三州老师F1……| 久久性爱99国产| 色九九中文字幕| 9 1 A v久久久| 99久精品视频| 久久婷五月天| 激情五月天在线| 丁香六月天婷婷开心综合| 久热精品视频| 久久999久久999久久999久久| 最新色色五月天| 99热只有| 五月精品99综合| 久艹伊| 日韩啪啪视频| 五月天婷婷丁香花| 色五月婷婷综合| 婷婷五月天av| 国产日产亚系列精品版优势| 99日本视频在线观看专区| 99视频久久久| 青青草原中文字幕| 国精产品一区二区三区| 激情五月婷婷在线观看| 丁香五月五月婷婷| 任我干视频在线观看| 蜜臀av粉嫩av懂色av| 97色色-99久久| 五月丁香黄色| 婷婷在线精品| 五月婷婷久草| 四虎成人精品永久免费AV九九| 大波美女VA网站| 99这里只有精品|v| 91chinese在线| 96丁香婷婷九月蜜桃综合久久| 婷婷五月天网址| 日日操夜夜爽白洁| 婷婷亚洲五月| 欧美大肥婆大肥BBBBB| 日本9区视频| 五月天激情综合首页| av五月天婷婷丁香| 色五月六月| 激情婷婷五月在线合集| 超碰在线国产| 婷婷涩涩五月天| 涩五月婷婷| 一二区成人电影| 五月婷婷就去色| 五月丁香久人妻中文| 国产婷伊人| 中文激情网| 五月亚洲| 中字幕视频在线永久在线观看免费 | 97狠狠色| 婷婷综合国产| 99热 在线观看| 丁香五月婷婷av| 超碰人人在线观看| 丁香五月在线视频| 久久99精品久久久久久三级| 国产精品美女久久久久AV超清| 五月丁香成人| 五月婷婷丁香俺日污视频| 婷婷五月色| a在线观看| 99在线观看精品视频| 亚洲深喉aV| 五月激情日本在线| 日韩AV片| 亚洲成人AV在线| 婷婷五月丁香久久| 亚洲乱码日产精品BD| 色一情一乱一乱一区91Av| 六月激情久久| 国产原创视频91九色| 人人人人人人人人人草| 亚洲久热| 爱操人妻| 日韩狠狠色| 97婷婷狠狠久久综合9色| 色天天综合| 国产精品天天狠天天看| 这里只有精品,日韩视频| 九九碰九九爱97| 天天综合网91| 丁香九月综合激情| 六月婷婷视频| 日日操天天操| 久久精品噜噜噜成人A∨色欲| 色情五月天婷婷| 欧美日韩成卜| 色综合久久天天综合网 | 大香蕉啪啪啪| 五月天色色色| 久久99视频| 97久久久| 67194国产| 性爱综合网| 欧美婷婷| 色婷婷丁香| 第四色色六月色综合| 丁香五月天视频| 五月天色导航婷婷资源婷婷| 六月婷婷五月天| 九九九精品视频免费观看| 九九视频在线| 开心 五月 综合| 五月天精品| 综合久久丁香婷婷,五月婷婷六月丁香,开心激情综合网,六月丁香在线观看,婷婷丁 | 熟妇无码乱子成人精品| 夜夜www| 热91久| 丁香五月婷婷色| 九月婷婷在线观看| 丁香五月婷婷五月天| 26uuu丁香婷婷五月| 999婷婷综合| 久久九九怡红院| www.婷婷六月天| 日日操,夜夜爽| 色色色五月| 五月天婷婷爱| 色五月丁香六月资源站| 蜜桃人妻无码AV天堂三区| 五月天成人手机在线视频| 婷婷综合在线网| 五月天丁香| 亚洲小视频免费播放| 蜜桃成语时李时珍 免费| 激情5月天天天| 东京热免费视频网站| 色情婷婷| 爱的综合网| 色99免费视频中文| 色婷婷丁香五月天| va婷婷在线免费观看| 九九热99精品| 久久久精品色| 色五月丁香婷婷综合| 超碰人人妻| 婷婷丁香五月麻豆| 天天插轮理| 人妻中文字幕网| 综合色播| 99热在线观看免费| 91人操| 欧美成人AAA片一区国产精品| 99热无码首页| 91五月天| 精品九九久久| 日日爽日日| 99爱无码| 欧美操人| 欧美三级韩国三级日本三斤| 啪啪99| 激情亚洲婷婷六月| 亚洲综合视频网| 美国少妇性做爰| 六月丁香婷婷综合狠狠爱夜夜爱| 99热视| jiujiujiuwuyuetian| 精品夜夜澡人妻无码AV| 日韩黄色电影| 六月丁香五月激情网| 五月婷在线影院| 色色色五月天婷婷| 91色久| 五月丁香六月婷婷综合网站| 爱性综合网| 97干在线看| 四川女人毛多水多A片| 国产精品视频| 婷婷五月天综合中文| 9.1综合网| 热久69| 天天日天天肏天天奸| 91精品丝袜久久久久久| 桔色成人在线| 婷婷五月天Av| 成人在线网址| www久久久久久| 欧美性色A片免费免费观看的| 91精品国产99久久久久久天美| 深爱激情久久| 色噜噜狠狠色综| 丁香六月| 亚洲视频另类| 亚洲网综合在线| 99热在线播放| www.99久| 热久久这里只有精品| 亚洲色婷婷视频| 最新精品视频99| 伊人丁香六月婷婷| 91精品在线看| 亚洲AV无码影院| 1024在线视频| 超极99精品| 午夜精品人妻无码一区二区三区| 五月天综合视频| 日本啪啪网| 色色99| 五月天婷婷在线视频| 丁香婷婷激情网站| 日日噜狠狠色综合久久| 久久国产精品乱子伦_靑青草…| 99久久网站| 猫咪伊人久久| 成人中文字幕在线| 日韩av网站在线观看| 久碰久| 亚洲 成人 电影av在线观看| 五月婷三级片| yazhoujiqingav| AⅤ网站在线看| 国产高清av黄色看片| 少妇水多A片太爽了| 少妇被躁爽到高潮无码文| 色婷婷成人| 国产毛片精品一区二区色欲黄A片| 五月丁香六月婷| 婷婷色色网| 青柠影视免费高清电视剧| 成人综合网站| 国精产品一区一区三区免费视频| 国产精产国品一二三在观看| 色色无码| 影音先锋91网站在线观看| 五月日韩中文字幕| 99九九这里有免费视频| 伊人激情综合| 激情骚五月| 日韩精品一区二区亚洲AV观看| 狼人婷婷综合| 色啪综合| WWW、日本色丁香co m| 亚洲丁香五月天在线视频| 婷婷丁香六月激情综合| 国产熟女日日骚五月丁香爱| 五月天婷婷中文字幕在线播放| 91色情播放| 五月丁香综合激情| 国产9色在线/日韩| 99精品视频免费观看| av亚洲国产小电影| 亚洲AV日韩在线观看| 国产精品视频网| 538任你爽| 五月丁香婷婷激情在线视频| 玖玖福利视频资源| 99视频在线观看网址| 久热黄色| 九九精品免费| 成人丁香婷婷| 秋霞AV美国| 99精品视频免费在线播放| 日在线V视频在线播放| 婷婷丁香成人五月天| 超碰在线观看9| 久久久免费精彩视频| 99色一| www热久久yy9| 99色色爰| sewuyuejiqingwang| www夜夜操com| 丁香五月婷婷啪啪啪| 99综合网| 色 噜噜 九月 婷婷| 另类专区在线观看| 久热最新视频| 99精品在线| 五月婷视频| 丁香综合久久| 激情丁香久久| 日日综合网| 婷婷五月色播放| 国产免费一区二区三州老师F1……| 五月天综合久久丁香91| 99国产小视频免费观看| 色狠久| 五月丁香综合激情| 99啪视频在线观看| 婷婷五月在线综合| 丁香五月电影| 激情五月婷婷综合| 六月激情丁香一道本7777| 九九热再线九九视频免费在线观看 | 婷婷色情网| 天天久综合网永久入口18| 国产精品成人AV在线| 五月天婷婷乱| 久久只有18视频| 天天操天天国产三级片处女学生妹| 亚洲色婷婷| 五月婷婷婷| 国产精品人人做人人爽人人添| 天天色99| 严洲天天插| 欧美成人va| 99操免费视频| 色色综合视频| 九月丁香| 色综合久久99色| 噜噜色com| 国产毛片精品一区二区色欲黄A片| 9九色首页| 久久九九大香蕉电院| www.91色| 亚洲、欧美、国产另类笫二区| 伊人五月丁香| 色婷婷基地 | 思思热天天看| 婷婷五月综合社区| 色婷婷五月天无码视频| 亚洲九九九九| 亚洲va综合va国产va中文| 丁香激情四射| 开心五月网 | 日韩av大全| 色噜噜狠狠色综合日日| 五月丁香六月成人| 人妻久久久久久久| 九九爱精品网站| 深爱丁香激情| 少妇AB又爽又紧无码网站| 激情五月深爱五月观看| 91热在线| 日本九九视频| 人妻精品一区二区三区| 婷婷九九色| www.俺去也com| 97在线99| 婷婷丁香人妻| 无码AV免费精品一区二区三区 | 99热在线观看免费精品| 色九九九综合| 五月天基地| 性爱激情五月| 婷婷五月色丁香在线看| 欧洲MV日韩MV国产| 南京搡BBBB搡BBBB| 欧美成人AAA片一区国产精品| 涩涩涩,com| 大香蕉久久| 情婷婷五月天在线| 婷婷五月天av| 天天综合.com| 亚洲精品又粗又大又爽A片| 欧美日韓成人亚洲精品另类| 99这里有精品| 五月婷免费视频久久久| 国产av天堂| 玖玖精品视频99| 丁香婷婷成年| 深爱激情丁香五月| 欧美、日韩、中文、制服、人妻| 色五月大|