- 首先,spring cloud 的版本为 Edgware.SR3
- 自定义FallbackProvider 的实现请点击这里,大神写的很详细;
- 起初我的bootstrap.yml 配置服务路由为:
routes: auth-server: strip-prefix: true sensitiveHeaders: path: /v1/auth-api/** url: http://localhost:8002/ system-server: strip-prefix: true sensitiveHeaders: path: /v1/system-api/** url: http://localhost:8004/
- 配置完MyServerFallbackProvider之后启动项目发现回退没生效,还是一直抛异常:com.netflix.zuul.exception.ZuulException:Connect to localhost:8004 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect
at org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException.<init>(ZuulRuntimeException.java:33)
at org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter.run(SimpleHostRoutingFilter.java:207)
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) - 最终查看源码得知抛出异常而没有回退发现和zull 的默认 filter有关;对zuul 过滤器不了解的小伙伴点击这里,一下为zuul 的默认过滤器
由于我的bootstrap.yml 路由配置为 url 形式(上文bootstrap.yml标红的部分) ,所以server 转发filter 为 SimpleHostRoutingFilter,最终通过hettpclient转发到服务端,而SimpleHostRoutingFilter的run()方法中直接抛出了ZuulRuntimeException:类型 顺序 过滤器 功能 pre -3 ServletDetectionFilter 标记处理Servlet的类型 pre -2 Servlet30WrapperFilter 包装HttpServletRequest请求 pre -1 FormBodyWrapperFilter 包装请求体 route 1 DebugFilter 标记调试标志 route 5 PreDecorationFilter 处理请求上下文供后续使用 route 10 RibbonRoutingFilter serviceId请求转发 route 100 SimpleHostRoutingFilter url请求转发 route 500 SendForwardFilter forward请求转发 post 0 SendErrorFilter 处理有错误的请求响应 post 1000 SendResponseFilter 处理正常的请求响应 try { CloseableHttpResponse response = forward(this.httpClient, verb, uri, request, headers, params, requestEntity); setResponse(response); } catch (Exception ex) { throw new ZuulRuntimeException(ex); } return null;
- SimpleHostRoutingFilter的forwardRequest()方法:
private CloseableHttpResponse forwardRequest(CloseableHttpClient httpclient, HttpHost httpHost, HttpRequest httpRequest) throws IOException { return httpclient.execute(httpHost, httpRequest); }
- 至此回退不生效的原因已找到,将bootstrap.yml中服务的路由方式更改为 serviceId形式,默认转发filter为RibbonRoutingFilter
routes: auth-server: strip-prefix: true sensitiveHeaders: path: /v1/auth-api/** serviceId: auth-server system-server: strip-prefix: true sensitiveHeaders: path: /v1/system-api/** serviceId: system-server
- RibbonRoutingFilter 中的转发方法:
protected ClientHttpResponse forward(RibbonCommandContext context) throws Exception { Map<String, Object> info = this.helper.debug(context.getMethod(), context.getUri(), context.getHeaders(), context.getParams(), context.getRequestEntity()); RibbonCommand command = this.ribbonCommandFactory.create(context); try { ClientHttpResponse response = command.execute(); this.helper.appendDebug(info, response.getRawStatusCode(), response.getHeaders()); return response; } catch (HystrixRuntimeException ex) { return handleException(info, ex); } }
- RibbonCommand 接口继承了HystrixExecutable,重新启动zuul服务,MyServerFallbackProvider全局回退启用正常了;
- 注:随便写写,可能关键点写的不太详细,各位小伙伴如有异议欢迎指正。
-
附上小弟久违得订阅号,路过的大佬不嫌弃点个关注
-
spring cloud zuul 配置全局回退无效的原因
最新推荐文章于 2021-04-05 20:19:56 发布