日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

010-映射诊断环境

發布時間:2025/4/17 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 010-映射诊断环境 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. Logback的設計目標之一是審查和調試復雜的分布式應用程序。真實世界的多數分布式系統需要同時處理多個客戶端。在一個典型的多線程方式實現的分布式系統里, 不同的線程

處理不同的客戶端。區分不同客戶端的記錄輸出的一個可行的但不好的方法是為每個客戶端都創建新的、獨立的logger。但是這種技術使logger的數量增多且大大增加了管理開銷。

2. 一個輕量的技術是為客戶端的每個記錄請求添加唯一戳(uniquely stamp)。Logback在SLJ4J里使用了這種技術的一種變體: 映射診斷環境(MDC)。

3. 為了給每個請求添加唯一戳, 可以把用戶信息放進MDC。MDC類的重要部分如下:

4. MDC類只有靜態方法, 開發者可以把信息放進一個診斷環境, 之后用其他logback組件獲取這些信息。MDC是基于每個線程進行管理的。子線程自動繼承其父的映射診斷環境

的一個副本。典型地, 當開始為新的客戶端請求服務時, 開發者會向MDC里插入恰當的環境信息, 比如客戶端id、客戶端IP地址、請求參數等等。Logback組件會自動在每個記錄

條目里包含這些信息。

5. MDC簡單使用例子

5.1. 新建一個名為SampleMDC的Java項目, 同時添加相關jar包。

5.2. 新建SampleMDC.java

package com.fj.smdc;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC;public class SampleMDC {private static final Logger logger = LoggerFactory.getLogger(SampleMDC.class);public static void main(String[] args) {MDC.put("first", "錯誤");MDC.put("last", "警告");logger.error("MDC簡單使用錯誤信息。");logger.warn("MDC簡單使用警告信息。");MDC.put("first", "信息");MDC.put("last", "測試");logger.info("MDC簡單使用信息。");logger.debug("MDC簡單使用測試信息。");} }

5.3. 新建logback.xml

5.4. 運行項目

6. 映射診斷環境在客戶端-服務器模式下最有奇效。典型情況是, 多個客戶端被服務器的多個線程所處理。雖然MDC里的方法都是靜態的, 但MDC是基于每個線程進行管理的,?這允許服務器的每個線程都有自己獨立的MDC戳。MDC的操作, 比如put()和get(), 只作用于當前線程和當前線程的子線程, 不影響其他線程里的MDC。由于MDC的信息是基于每個線程進行管理的, 因此每個線程都有自己的MDC副本。所以在使用MDC時, 開發者不需要操心線程安全或同步, 因為MDC透明地、安全地處理了這些問題。

7. 客戶端-服務器例子

7.1.?新建一個名為ClientServerMDC的Java項目, 同時添加相關jar包。

7.2.?在src目錄下創建logback.xml

7.3.?新建一個MyServer.java

package com.fj.csmdc;import java.io.IOException; import java.net.ServerSocket; import java.net.Socket;public class MyServer {public static void main(String[] args) {ServerSocket server = null;try {server = new ServerSocket(9999);System.out.println("server start...");int tnum = 0;while(true) {Socket socket = server.accept();new Thread(new ServerHandler(socket), "t" + (++tnum)).start();}} catch (IOException e) {e.printStackTrace();} finally {if(server != null) {try {server.close();} catch (IOException e) {e.printStackTrace();}}}} }

7.4.?新建一個ServerHandler.java

package com.fj.csmdc;import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC;public class ServerHandler implements Runnable {private static final Logger logger = LoggerFactory.getLogger(ServerHandler.class);private Socket socket;public ServerHandler( Socket socket) {this.socket = socket;}@Overridepublic void run() {if(socket == null) {logger.error("socket為空。");return;}MDC.put("client", socket.getRemoteSocketAddress().toString());try {BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));String line = null;while(socket != null && (!socket.isClosed()) && (line = br.readLine()) != null) {logger.info(line);}} catch (IOException e) {e.printStackTrace();} finally {if(socket != null && (!socket.isClosed())) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}socket = null;}} }

7.5.?新建一個MyClient.java

package com.fj.csmdc;import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket;public class MyClient {public static void main(String[] args) {try {Socket socket = new Socket("192.168.25.1", 9999);System.out.println("client start...");new Thread(new ClienWriter(socket)).start();} catch (IOException e) {e.printStackTrace();}} }class ClienWriter implements Runnable{private Socket socket;public ClienWriter(Socket socket) {this.socket = socket;}@Overridepublic void run() {try {BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String line = null;while(socket != null && (!socket.isClosed())) {System.out.println("請輸入內容(不允許為空), 輸入886退出程序: ");line = br.readLine();if(line == null || line.length() <= 0) {continue;}if(line.equals("886")) {break;}bw.write(line);bw.newLine();bw.flush();}} catch (IOException e) {e.printStackTrace();} finally {System.out.println("client close socket writer " + System.currentTimeMillis());if(socket != null && (!socket.isClosed())) {try {socket.close();} catch (Exception e) {e.printStackTrace();}}socket = null;}} }

7.6.?運行MyServer.java

7.7.?運行MyClient.java

7.8.?在MyClient運行控制臺輸入"你好哇", 然后按下回車鍵

7.9.?查看運行的MyServer控制臺

7.10. 再運行一個MyClient.java客戶端

7.11.?在第二個MyClient運行控制臺輸入"很高興見到你", 然后按下回車鍵

7.12.??查看運行的MyServer控制臺

8. MDCInsertingServletFilter

8.1. 我們已經看到, 在處理多個客戶端時, MDC非常有用。在一個管理用戶驗證的web程序里, 可以在MDC里設置用戶名, 然后在用戶注銷登錄時從MDC刪除用戶名。不幸的是, 上面的方法不是始終可靠的。由于MDC 是基于每個線程對數據進行管理的, 所以服務器循環使用線程時會導致錯誤地使用MDC里的信息。

8.2. 在處理請求時, 為保證MDC里的信息始終正確, 一個可行的方法是, 在處理流程的開頭存儲用戶名, 然后再這個處理流程的尾部移除用戶名。這種情況可以用一個servlet過濾器。

8.3. 在servlet過濾器的doFilter()方法里, 我們可以從請求取得相關的用戶數據, 然后存儲在MDC。后續的其他過濾器和servlet將自動從先前存儲的MDC里受益。最終, 當我們的servlet 過濾器重新得到控制權后, 就有機會清除MDC數據。就是在過濾器鏈完成后, 該過濾器從MDC移除用戶信息。

8.4. 在web程序里, 經常需要取得http請求的主機名、請求uri和user-agent。MDCInsertingServletFilter把這些數據放入MDC, 所用的鍵如下:

8.5. 新建一個名為FilterMDC的動態Web工程, 同時添加相關jar包。

8.6. 在src目錄下創建logback.xml

8.7. 編寫index.html

8.8. 編寫MyServlet.java

package com.fj.fmdc;import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class MyServlet extends HttpServlet {private static final long serialVersionUID = 1L;private static final Logger logger = LoggerFactory.getLogger(MyServlet.class);@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String userName = req.getParameter("userName");String password = req.getParameter("password");if(userName != null && password != null) {logger.debug("userName = " + userName + ", password = " + password);resp.getWriter().write("login success.");}}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req, resp);} }

8.9. 配置web.xml

8.10. 運行項目, 使用瀏覽器訪問

8.11. 點擊提交, 控制臺打印

8.12. 瀏覽器輸出

9. 子線程訪問MDC副本

9.1. 在初始(主線程)上調用MDC.getCopyOfContextMap()。當子線程運行時, 它的第一個動作就應該是調用MDC.setContextMapValues(), 為子線程關聯初始MDC值的副本。

9.2. 更改我們的SampleMDC.java

package com.fj.smdc;import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC;public class SampleMDC {private static final Logger logger = LoggerFactory.getLogger(SampleMDC.class);public static void main(String[] args) {MDC.put("first", "錯誤");MDC.put("last", "警告");logger.error("MDC簡單使用錯誤信息。");logger.warn("MDC簡單使用警告信息。");MDC.put("first", "信息");Map<String, String> contextMap = MDC.getCopyOfContextMap();new Thread(new Runnable() {@Overridepublic void run() {MDC.setContextMap(contextMap);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}logger.info("MDC簡單使用信息。");logger.debug("MDC簡單使用測試信息。");}}).start();MDC.put("last", "測試");try {Thread.sleep(10000);} catch (InterruptedException e) {e.printStackTrace();}} }

9.3. 運行程序

總結

以上是生活随笔為你收集整理的010-映射诊断环境的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。