1. 簡介
當我們與微服務或一般 Web 服務一起工作時,瞭解用户如何與我們的服務交互非常有用。 這可以通過跟蹤所有擊打我們服務的請求並稍後分析這些信息來實現。
有一些系統可以幫助我們做到這一點,並且可以輕鬆地與 Spring 集成,例如 Zipkin。 但是,Spring Boot Actuator 具有內置此功能,並且可以通過其 httpTrace 端點進行使用,該端點跟蹤所有 HTTP 請求。 在本教程中,我們將展示如何使用它以及如何自定義它以更好地適應我們的要求。
2. HttpTrace 端點設置
為了本教程的目的,我們將使用一個 Maven Spring Boot 項目。第一步我們需要做的就是將 Spring Boot Actuator 依賴 添加到我們的項目中:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>之後,我們需要在我們的應用程序中啓用 httpTrace 端點。
要做到這一點,只需修改我們的 application.properties 文件,使其包含 httpTrace 端點:
management.endpoints.web.exposure.include=httptrace如果我們需要更多端點,我們只需用逗號分隔它們,或者使用通配符 * 將它們全部包含進來。
現在,我們的 httpTrace 端點應該出現在我們應用程序的 actuator 端點列表中。
{
"_links": {
"self": {
"href": "http://localhost:8080/actuator",
"templated": false
},
"httptrace": {
"href": "http://localhost:8080/actuator/httptrace",
"templated": false
}
}
}請注意,我們可以通過訪問我們 Web 服務的 actuator</em/> 端點來列出所有啓用的 actuator 端點。
3. 分析追蹤數據
現在,讓我們分析 httpTrace 監控端點返回的追蹤數據。
讓我們向我們的服務發送一些請求,調用 /actuator/httptrace 端點,並獲取其中一個返回的追蹤數據。
{
"traces": [
{
"timestamp": "2019-08-05T19:28:36.353Z",
"principal": null,
"session": null,
"request": {
"method": "GET",
"uri": "http://localhost:8080/echo?msg=test",
"headers": {
"accept-language": [
"en-GB,en-US;q=0.9,en;q=0.8"
],
"upgrade-insecure-requests": [
"1"
],
"host": [
"localhost:8080"
],
"connection": [
"keep-alive"
],
"accept-encoding": [
"gzip, deflate, br"
],
"accept": [
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
],
"user-agent": [
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 OPR/62.0.3331.66"
]
},
"remoteAddress": null
},
"response": {
"status": 200,
"headers": {
"Content-Length": [
"12"
],
"Date": [
"Mon, 05 Aug 2019 19:28:36 GMT"
],
"Content-Type": [
"text/html;charset=UTF-8"
]
}
},
"timeTaken": 82
}
]
}如我們所見,響應被劃分為若干節點:
- timestamp: 請求接收的時間
- principal: 如果適用,執行請求的已認證用户
- session: 與請求相關的任何會話
- request: 請求的相關信息,例如方法、完整 URI 或標頭
- response: 響應的相關信息,例如狀態碼或標頭
- timeTaken: 處理請求所花費的時間
如果覺得響應過於冗長,我們可以根據需要進行調整。通過在 application.properties 的 management.trace.http.include 屬性中 指定要返回的字段,向 Spring 傳遞我們的需求。
management.trace.http.include=RESPONSE_HEADERS在這種情況下,我們指定只想要響應頭信息。因此,我們可以看到之前包含的信息,如請求頭或耗時等,現在不再出現在響應中。
{
"traces": [
{
"timestamp": "2019-08-05T20:23:01.397Z",
"principal": null,
"session": null,
"request": {
"method": "GET",
"uri": "http://localhost:8080/echo?msg=test",
"headers": {},
"remoteAddress": null
},
"response": {
"status": 200,
"headers": {
"Content-Length": [
"12"
],
"Date": [
"Mon, 05 Aug 2019 20:23:01 GMT"
],
"Content-Type": [
"text/html;charset=UTF-8"
]
}
},
"timeTaken": null
}
]
}所有可能的值均可在 源代碼 中找到,包括默認值。
4. 自定義 HttpTraceRepository
默認情況下,httpTrace 端點僅返回最近的 100 個請求並將其存儲在內存中。
好消息是,我們可以通過創建自己的 HttpTraceRepository 來自定義它。
現在讓我們創建我們的存儲庫。 HttpTraceRepository 接口非常簡單,我們只需要實現兩個方法:findAll() 用於檢索所有跟蹤記錄;以及 add() 用於將跟蹤記錄添加到存儲庫中。
為了簡化起見,我們的存儲庫也將跟蹤記錄存儲在內存中,並且只存儲最近的 GET 請求,該請求命中我們的服務:
@Repository
public class CustomTraceRepository implements HttpExchangeRepository {
AtomicReference<HttpExchange> lastTrace = new AtomicReference<>();
@Override
public List<HttpTrace> findAll() {
return Collections.singletonList(lastTrace.get());
}
@Override
public void add(HttpExchange trace) {
if ("GET".equals(trace.getRequest().getMethod())) {
lastTrace.set(trace);
}
}
}儘管這個簡單的例子可能看起來不太實用,但我們可以看到它能變得多麼強大,以及我們如何將日誌存儲在任何地方。
5. 過濾路徑以進行跟蹤
接下來,我們將討論如何過濾要跟蹤的路徑,以便忽略我們不感興趣的一些請求。
如果在我們發出一些請求到我們的服務後,稍微調整一下 httpTrace 端點,我們可以看到我們還會獲得 actuator 請求的跟蹤信息:
{
"traces": [
{
"timestamp": "2019-07-28T13:56:36.998Z",
"principal": null,
"session": null,
"request": {
"method": "GET",
"uri": "http://localhost:8080/actuator/",
// ...
}我們可能無法利用這些痕跡,因此我們更傾向於排除它們。在這種情況下,我們需要創建我們自己的 HttpTraceFilter,並在 shouldNotFilter方法中指定我們想要忽略的路徑:
@Component
public class TraceRequestFilter extends HttpExchangesFilter {
public TraceRequestFilter(HttpExchangeRepository repository) {
super(repository, Include.defaultIncludes());
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return request.getServletPath().contains("actuator");
}
}請注意,HttpTraceFilter 只是一個普通的 Spring 過濾器,但具有一些跟蹤特定功能。
6. 結論
在本教程中,我們介紹了 httpTrace Spring Boot Actuator 端點及其主要功能。我們還深入探討,並解釋瞭如何修改默認行為以更好地適應我們的特定需求。