1.背景
错误信息:
-- [http-nio-9904-exec-5] o.s.c.n.z.filters.post.SendErrorFilter : Error during filtering
com.netflix.zuul.exception.ZuulException: Forwarding error
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.handleException(RibbonRoutingFilter.java:183)
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.forward(RibbonRoutingFilter.java:158)
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.run(RibbonRoutingFilter.java:106)
at com.netflix.zuul.ZuulFilter.runFilter(ZuulFilter.java:112)
at com.netflix.zuul.FilterProcessor.processZuulFilter(FilterProcessor.java:193)
at com.netflix.zuul.FilterProcessor.runFilters(FilterProcessor.java:157)
at com.netflix.zuul.FilterProcessor.route(FilterProcessor.java:118)
at com.netflix.zuul.ZuulRunner.route(ZuulRunner.java:96)
at com.netflix.zuul.http.ZuulServlet.route(ZuulServlet.java:116)
at com.netflix.zuul.http.ZuulServlet.service(ZuulServlet.java:81)
at org.springframework.web.servlet.mvc.ServletWrappingController.handleRequestInternal(ServletWrappingController.java:157)
at org.springframework.cloud.netflix.zuul.web.ZuulController.handleRequest(ZuulController.java:44)
at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:50)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.cloud.sleuth.instrument.web.TraceFilter.doFilter(TraceFilter.java:169)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
2018-01-18 09:48:18.852 ERROR [api-gateway,5047c7e7b4449179,aa1e88c3768befe6,true] 1 --- [http-nio-9904-exec-5] c.r.k.api.gateway.filter.AccessFilter : 错误信息:{timestamp=Thu Jan 18 09:48:18 UTC 2018, status=500, error=Internal Server Error, exception=com.netflix.zuul.exception.ZuulException, message=GENERAL}
2018-01-18 09:48:18.855 INFO [服务名,5047c7e7b4449179,5047c7e7b4449179,true] 1 --- [http-nio-9904-exec-5] c.r.k.api.gateway.filter.ResponseFilter : 请求耗时:5016毫秒
2.场景分析
根据日志信息进行回溯问题的发生点;
at org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter.handleException(RibbonRoutingFilter.java:183)根据 这段日志我们找到如下源码:
package org.springframework.cloud.netflix.zuul.filters.route
public class RibbonRoutingFilter extends ZuulFilter
protected ClientHttpResponse handleException(Map info,
HystrixRuntimeException ex) throws ZuulException {
int statusCode = HttpStatus.INTERNAL_SERVER_ERROR.value();
Throwable cause = ex;
String message = ex.getFailureType().toString();
ClientException clientException = findClientException(ex);
if (clientException == null) {
clientException = findClientException(ex.getFallbackException());
}
if (clientException != null) {
if (clientException
.getErrorType() == ClientException.ErrorType.SERVER_THROTTLED) {
statusCode = HttpStatus.SERVICE_UNAVAILABLE.value();
}
cause = clientException;
message = clientException.getErrorType().toString();
}
info.put("status", String.valueOf(statusCode));
throw new ZuulException(cause, "Forwarding error", statusCode, message);
}
分析如上函数handleException(... ...)执行逻辑;重点是最后一行代码,throw new ZuulException(cause,"Forwarding error",statusCode,message);接下来我们逐个分析各个变量是如何被赋值的;
1) 其中变量statusCode赋值有两种情况,一种为初始被赋值为HttpStatus.INTERNAL_SERVER_ERROR.value()(值:500);另一种情况被赋值为HttpStatus.SERVICE_UNAVAILABLE.value()(值:503);
HttpStatus.INTERNAL_SERVER_ERROR.value()
/**
* {@code 500 Internal Server Error}.
* @see HTTP/1.1: Semantics and Content, section 6.6.1
*/
INTERNAL_SERVER_ERROR(500, "Internal Server Error"),
HttpStatus.SERVICE_UNAVAILABLE.value()
/**
* {@code 503 Service Unavailable}.
* @see HTTP/1.1: Semantics and Content, section 6.6.4
*/
SERVICE_UNAVAILABLE(503, "Service Unavailable"),
由于最终new ZuulExceptioin的statusCode为500,所以可以排除SERVER_UNAVAILABLE的情况;
2) 变量message的赋值也有两种情况:一种如初始赋值String message = ex.getFailureType().toString();(HystrixRuntimeException);另一种是message = clientException.getErrorType().toString();(ClientException);
下面分别为HystrixRuntimeException 的FailureType的类型信息,ClientException的ErrorType类型信息:
public static enum FailureType {
BAD_REQUEST_EXCEPTION, COMMAND_EXCEPTION, TIMEOUT, SHORTCIRCUIT, REJECTED_THREAD_EXECUTION, REJECTED_SEMAPHORE_EXECUTION, REJECTED_SEMAPHORE_FALLBACK
}
/**
* define your error codes here
*
*/
public enum ErrorType{
GENERAL,
CONFIGURATION,
NUMBEROF_RETRIES_EXEEDED,
NUMBEROF_RETRIES_NEXTSERVER_EXCEEDED,
SOCKET_TIMEOUT_EXCEPTION,
READ_TIMEOUT_EXCEPTION,
UNKNOWN_HOST_EXCEPTION,
CONNECT_EXCEPTION,
CLIENT_THROTTLED,
SERVER_THROTTLED,
NO_ROUTE_TO_HOST_EXCEPTION,
CACHE_MISSING;
static String getName(int errorCode){
if (ErrorType.values().length >= errorCode){
return ErrorType.values()[errorCode].name();
}else{
return "UNKNOWN ERROR CODE";
}
}
}
而最终message=GENERAL ,排除了初始赋值,异常由ClientException产生;
解决思路:
关于上面