Arthas實踐–快速排查SpringBoot應用404/401問題
背景
在Java Web/Spring Boot開發時,很常見的問題是:
- 網頁訪問404了,為什麼訪問不到?
- 登陸失敗了,請求返回401,到底是哪個Filter攔截了我的請求?
碰到這種問題時,通常很頭痛,特別是線上上環境時。
本文介紹使用Alibaba開源的Java診斷利器Arthas,來快速定位這類Web請求404/401問題。
Java Web裡一個請求被處理的流程
在進入正題之前,先溫習下知識。一個普通的Java Web請求處理流程大概是這樣子的:
Request -> Filter1 -> Filter2 ... -> Servlet
|
Response <- Filter1 <- Filter2 ... <- Servlet
Demo
本文的介紹基於一個很簡單的Demo:https://github.com/hengyunabc/spring-boot-inside/tree/master/demo-404-401
- 訪問 http://localhost:8080/ ,返回200,正常列印Welconme資訊
- 訪問 http://localhost:8080/a.txt ,返回404
- 訪問 http://localhost:8080/admin ,返回401
是哪個Servlet返回了404?
Demo啟動後,訪問:http://localhost:8080/a.txt ,返回404:
$ curl http://localhost:8080/a.txt
{"timestamp":1546790485831,"status":404,"error":"Not Found","message":"No message available","path":"/a.txt"}
我們知道一個HTTP Request,大部分情況下都是由一個Servlet處理的,那麼到底是哪個Servlet返回了404?
我們使用Arthas的trace
命令來定位:
$ trace javax.servlet.Servlet *
Press Ctrl+C to abort.
Affect(class-cnt:7 , method-cnt:185) cost in 1018 ms.
然後訪問 http://localhost:8080/a.txt ,Arthas會列印出整個請求樹,完整的輸出太長,這裡只擷取關鍵的一輸出:
+---[13.087083ms] org.springframework.web.servlet.DispatcherServlet:resolveViewName()
| `---[13.020984ms] org.springframework.web.servlet.DispatcherServlet:resolveViewName()
| +---[0.002777ms] java.util.List:iterator()
| +---[0.001955ms] java.util.Iterator:hasNext()
| +---[0.001739ms] java.util.Iterator:next()
| `---[12.891979ms] org.springframework.web.servlet.ViewResolver:resolveViewName()
| +---[0.089811ms] javax.servlet.GenericServlet:<init>()
| +---[min=0.037696ms,max=0.054478ms,total=0.092174ms,count=2] org.springframework.web.servlet.view.freemarker.FreeMarkerView$GenericServletAdapter:<init>()
可以看出請求經過Spring MVC的DispatcherServlet
處理,最終由ViewResolver
分派給FreeMarkerView$GenericServletAdapter
處理。所以我們可以知道這個請求最終是被FreeMarker
處理的。
後面再排查FreeMarker
的配置就可以了。
這個神奇的trace javax.servlet.Servlet *
到底是怎樣工作的呢?
實際上Arthas會匹配到JVM裡所有實現了javax.servlet.Servlet
的類,然後trace
它們的所有函式,所以HTTP請求會被列印出來。
這裡留一個小問題,為什麼只訪問了
http://localhost:8080/a.txt
,但Arthas的trace
命令列印出了兩個請求樹?
是哪個Filter返回了401?
在Demo裡,訪問 http://localhost:8080/admin ,會返回401,即沒有許可權。那麼是哪個Filter攔截了請求?
$ curl http://localhost:8080/admin
{"timestamp":1546794743674,"status":401,"error":"Unauthorized","message":"admin filter error.","path":"/admin"}
我們還是使用Arthas的trace
命令來定位,不過這次trace
的是javax.servlet.Filter
:
$ trace javax.servlet.Filter *
Press Ctrl+C to abort.
Affect(class-cnt:13 , method-cnt:75) cost in 278 ms.
再次訪問admin,在Arthas裡,把整個請求經過哪些Filter處理,都列印為樹。這裡擷取關鍵部分:
+---[0.704625ms] org.springframework.web.filter.OncePerRequestFilter:doFilterInternal()
| `---[0.60387ms] org.springframework.web.filter.RequestContextFilter:doFilterInternal()
| +---[0.022704ms] org.springframework.web.context.request.ServletRequestAttributes:<init>()
| +---[0.217636ms] org.springframework.web.filter.RequestContextFilter:initContextHolders()
| | `---[0.180323ms] org.springframework.web.filter.RequestContextFilter:initContextHolders()
| | +---[0.034656ms] javax.servlet.http.HttpServletRequest:getLocale()
| | +---[0.0311ms] org.springframework.context.i18n.LocaleContextHolder:setLocale()
| | +---[0.008691ms] org.springframework.web.context.request.RequestContextHolder:setRequestAttributes()
| | `---[0.014918ms] org.apache.commons.logging.Log:isDebugEnabled()
| +---[0.215481ms] javax.servlet.FilterChain:doFilter()
| | `---[0.072186ms] com.example.demo404401.AdminFilterConfig$AdminFilter:doFilter()
| | `---[0.021945ms] javax.servlet.http.HttpServletResponse:sendError()
可以看到HTTP Request最終是被com.example.demo404401.AdminFilterConfig$AdminFilter
處理的。
總結
- 通過trace Servlet/Filter,可以快速定位Java Web問題
- trace是瞭解應用執行流程的利器,只要trace到關鍵的介面或者類上
- 仔細觀察trace的結果,可以學習到Spring MVC是處理Web請求細節
連結
相關文章
- 深入Spring Boot--使用Arthas排查應用404/401問題Spring Boot
- 當DUBBO遇上Arthas - 排查問題的實踐
- Arthas 實踐——生產環境排查 CPU 飈高問題
- Arthas實踐–使用redefine排查應用奇怪的日誌來源
- Java線上問題排查神器Arthas實戰分析Java
- Java 線上問題排查神器 Arthas 快速上手與原理淺談Java
- Java線上問題排查神器Arthas快速上手與原理淺談Java
- 線上問題排查神器入門——Arthas
- 深入SpringBoot:利用Arthas排查NoSuchMethodErrorSpring BootError
- 線上FullGC問題排查實踐——手把手教你排查線上問題GC
- 應用系統瓶頸排查和分析的思考-Arthas 實戰
- Arthas常用功能及一次線上問題排查
- 使用 Arthas 排查 SpringBoot 詭異耗時的 BugSpring Boot
- SpringBoot Seata 死鎖問題排查Spring Boot
- 一次線上CPU高的問題排查實踐
- windows系統相關命令及問題排查實踐Windows
- 線上問題排查,一不小心踩到阿里的 arthas坑了阿里
- 利用 Arthas 精準定位 Java 應用 CPU 負載過高問題Java負載
- 詳說TCP重傳問題的排查思路與實踐TCP
- SpringBoot Admin2.0 整合 Java 診斷神器 Arthas 實踐Spring BootJava
- Linux系統及應用問題分析排查工具Linux
- 深入剖析:如何使用Pulsar和Arthas高效排查訊息佇列延遲問題佇列
- 中原銀行 Arthas 實踐之路
- Vue單頁及多頁應用全域性配置404頁面實踐Vue
- Springboot應用快取實踐之:Ehcache加持Spring Boot快取
- 如何快速排查Linux伺服器效能問題Linux伺服器
- 快速搭建主從的指令碼和問題排查指令碼
- 網易雲信 RTC 音訊問題排查的挑戰與實踐音訊
- 阿里開源那個牛哄哄問題排查工具竟然不會用?最佳實踐來了!阿里
- laravel 路由404問題Laravel路由
- 解決SpringBoot頁面localhost 404問題,即Whitelabel Error Page問題Spring BootlocalhostError
- Nginx 配置 cros 跨域以及遇到 401 響應的問題NginxROS跨域
- 如何應用TFGAN快速實踐生成對抗網路?
- SpringBoot應用首次啟動慢的問題Spring Boot
- java問題排查Java
- JVM 問題排查JVM
- 框架問題排查框架
- 使用Docker容器化SpringBoot+Dubbo應用的實踐DockerSpring Boot