您好,登錄后才能下訂單哦!
本篇內容主要講解“Spring Cloud Zuul中異常處理細節有哪些”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Spring Cloud Zuul中異常處理細節有哪些”吧!
首先我們來看一張官方給出的Zuul請求的生命周期圖,如下:
關于這張圖我說如下幾點:
1.正常情況下所有的請求都是按照pre、route、post的順序來執行,然后由post返回response
2.在pre階段,如果有自定義的過濾器則執行自定義的過濾器
3.pre、routing、post的任意一個階段如果拋異常了,則執行error過濾器,然后再執行post給出響應
這是這張圖給我們的信息,我們再來看看源碼com.netflix.zuul.http.ZuulServlet
類中的service方法,這是整個調用過程的核心,如下:
try { init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse); // Marks this request as having passed through the "Zuul engine", as opposed to servlets // explicitly bound in web.xml, for which requests will not have the same data attached RequestContext context = RequestContext.getCurrentContext(); context.setZuulEngineRan(); try { preRoute(); } catch (ZuulException e) { error(e); postRoute(); return; } try { route(); } catch (ZuulException e) { error(e); postRoute(); return; } try { postRoute(); } catch (ZuulException e) { error(e); return; } } catch (Throwable e) { error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); }
我們看到這里有一個大的try…catch,大的try…catch里邊有三個小的try…catch,小的try…catch只負責捕獲ZuulException異常,其他的異常交給大的try…catch來捕獲。pre和route執行出錯之后都會先執行error再執行post,而post執行出錯之后就只執行error而不會再執行post。
ZuulFilter最終會在com.netflix.zuul.FilterProcessor的processZuulFilter方法中被調用,在該方法中會判斷runFilter是否執行成功,如果執行失敗,則將異常信息提取出來,然后拋出異常,拋出的異常如果是ZuulException的實例,則拋出一個ZuulException類型的異常,如果不是ZuulException的實例,則拋出一個狀態碼為500的ZuulException類型的異常,所以無論如何,我們最終看到的都是ZuulException類型的異常,下面我貼出processZuulFilter方法的一部分核心代碼,如下:
public Object processZuulFilter(ZuulFilter filter) throws ZuulException { try { ZuulFilterResult result = filter.runFilter(); ExecutionStatus s = result.getStatus(); execTime = System.currentTimeMillis() - ltime; switch (s) { case FAILED: t = result.getException(); ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime); break; case SUCCESS: break; default: break; } if (t != null) throw t; usageNotifier.notify(filter, s); return o; } catch (Throwable e) { usageNotifier.notify(filter, ExecutionStatus.FAILED); if (e instanceof ZuulException) { throw (ZuulException) e; } else { ZuulException ex = new ZuulException(e, "Filter threw Exception", 500, filter.filterType() + ":" + filterName); ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime); throw ex; } } }
在Zuul中,所有的錯誤問題的最終都是被SendErrorFilter類來處理,該類在早期的版本是一個post類型的filter,post類型的filter有一個缺陷就是不能處理post中拋出的異常,需要我們手動去完善,而我目前使用的這個版本(Dalston.SR3)已經修復了這個問題,SendErrorFilter現在是一個error類型的filter,而且只要RequestContext中有異常就會進入到SendErrorFilter中,錯誤信息也都從exception對象中提取出來,核心代碼如下:
@Override public boolean shouldFilter() { RequestContext ctx = RequestContext.getCurrentContext(); // only forward to errorPath if it hasn't been forwarded to already return ctx.getThrowable() != null && !ctx.getBoolean(SEND_ERROR_FILTER_RAN, false); } @Override public Object run() { try { RequestContext ctx = RequestContext.getCurrentContext(); ZuulException exception = findZuulException(ctx.getThrowable()); HttpServletRequest request = ctx.getRequest(); request.setAttribute("javax.servlet.error.status_code", exception.nStatusCode); log.warn("Error during filtering", exception); request.setAttribute("javax.servlet.error.exception", exception); if (StringUtils.hasText(exception.errorCause)) { request.setAttribute("javax.servlet.error.message", exception.errorCause); } RequestDispatcher dispatcher = request.getRequestDispatcher( this.errorPath); if (dispatcher != null) { ctx.set(SEND_ERROR_FILTER_RAN, true); if (!ctx.getResponse().isCommitted()) { dispatcher.forward(request, ctx.getResponse()); } } } catch (Exception ex) { ReflectionUtils.rethrowRuntimeException(ex); } return null; }
如果我們想要自定義異常信息也很方便,如下:
@Component public class MyErrorAttribute extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) { Map<String, Object> result = super.getErrorAttributes(requestAttributes, includeStackTrace); result.put("status", 222); result.put("error", "error"); result.put("exception", "exception"); result.put("message", "message"); return result; } }
到此,相信大家對“Spring Cloud Zuul中異常處理細節有哪些”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。