spring cloud zuul在使用中遇到的坑
阿新 • • 發佈:2018-12-13
在使用zuul的時候遇到的坑總結一下: 逐漸增加更新以後遇到的 1、在路由的時候莫名其妙的把serviceId給去掉,導致404。比如請求:/serviceId/search/book,zuul會把serviceId去掉,導致匹配不到服務404 解決辦法: zuul: strip-prefix: false
因為我們沒有設定zuul.prefix 為所有的匹配增加字首, 例如 /api,代理字首預設會從請求路徑中移除(通過 zuul.stripPrefix=false 可以關閉這個功能)
設定這個值以後還是出現了404的問題。最後只能自己實現路由對映。 自定義路由:https://www.jianshu.com/p/647cf467b47c
this.servletRequestField = ReflectionUtils.findField(ServletRequestWrapper.class,
"request", ServletRequest.class);
找不到servletRequestField。 解決辦法: 重寫ZuulServerAutoConfiguration這個類並註釋掉FormBodyWrapperFilter的bean
/* * Copyright 2013-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.cloud.netflix.zuul; import com.netflix.zuul.FilterLoader; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.filters.FilterRegistry; import com.netflix.zuul.http.ZuulServlet; import com.netflix.zuul.monitoring.CounterFactory; import com.netflix.zuul.monitoring.TracerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.actuate.metrics.CounterService; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.web.ErrorController; import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.cloud.client.actuator.HasFeatures; import org.springframework.cloud.client.discovery.event.HeartbeatEvent; import org.springframework.cloud.client.discovery.event.HeartbeatMonitor; import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent; import org.springframework.cloud.netflix.ribbon.SpringClientFactory; import org.springframework.cloud.netflix.zuul.filters.CompositeRouteLocator; import org.springframework.cloud.netflix.zuul.filters.RouteLocator; import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator; import org.springframework.cloud.netflix.zuul.filters.ZuulProperties; import org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter; import org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter; import org.springframework.cloud.netflix.zuul.filters.pre.DebugFilter; import org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter; import org.springframework.cloud.netflix.zuul.filters.pre.ServletDetectionFilter; import org.springframework.cloud.netflix.zuul.filters.route.SendForwardFilter; import org.springframework.cloud.netflix.zuul.metrics.DefaultCounterFactory; import org.springframework.cloud.netflix.zuul.metrics.EmptyCounterFactory; import org.springframework.cloud.netflix.zuul.metrics.EmptyTracerFactory; import org.springframework.cloud.netflix.zuul.web.ZuulController; import org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Primary; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.core.annotation.Order; import java.util.Collection; import java.util.Map; /** * @author Spencer Gibb * @author Dave Syer * @author Biju Kunjummen */ @Configuration @EnableConfigurationProperties({ZuulProperties.class}) @ConditionalOnClass(ZuulServlet.class) @ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class) // Make sure to get the ServerProperties from the same place as a normal web app would @Import(ServerPropertiesAutoConfiguration.class) public class ZuulServerAutoConfiguration { @Autowired protected ZuulProperties zuulProperties; @Autowired protected ServerProperties server; @Autowired(required = false) private ErrorController errorController; @Bean public HasFeatures zuulFeature() { return HasFeatures.namedFeature("Zuul (Simple)", ZuulServerAutoConfiguration.class); } @Bean @Primary public CompositeRouteLocator primaryRouteLocator( Collection<RouteLocator> routeLocators) { return new CompositeRouteLocator(routeLocators); } @Bean @ConditionalOnMissingBean(SimpleRouteLocator.class) public SimpleRouteLocator simpleRouteLocator() { return new SimpleRouteLocator(this.server.getServletPrefix(), this.zuulProperties); } @Bean public ZuulController zuulController() { return new ZuulController(); } @Bean public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) { ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController()); mapping.setErrorController(this.errorController); return mapping; } @Bean public ApplicationListener<ApplicationEvent> zuulRefreshRoutesListener() { return new ZuulRefreshListener(); } @Bean @ConditionalOnMissingBean(name = "zuulServlet") public ServletRegistrationBean zuulServlet() { ServletRegistrationBean servlet = new ServletRegistrationBean(new ZuulServlet(), this.zuulProperties.getServletPattern()); // The whole point of exposing this servlet is to provide a route that doesn't // buffer requests. servlet.addInitParameter("buffer-requests", "false"); return servlet; } // pre filters @Bean public ServletDetectionFilter servletDetectionFilter() { return new ServletDetectionFilter(); } // @Bean // public FormBodyWrapperFilter formBodyWrapperFilter() { // return new FormBodyWrapperFilter(); // } @Bean public DebugFilter debugFilter() { return new DebugFilter(); } @Bean public Servlet30WrapperFilter servlet30WrapperFilter() { return new Servlet30WrapperFilter(); } // post filters @Bean public SendResponseFilter sendResponseFilter() { return new SendResponseFilter(); } @Bean public SendErrorFilter sendErrorFilter() { return new SendErrorFilter(); } @Bean public SendForwardFilter sendForwardFilter() { return new SendForwardFilter(); } @Bean @ConditionalOnProperty(value = "zuul.ribbon.eager-load.enabled", matchIfMissing = false) public ZuulRouteApplicationContextInitializer zuulRoutesApplicationContextInitiazer( SpringClientFactory springClientFactory) { return new ZuulRouteApplicationContextInitializer(springClientFactory, zuulProperties); } @Configuration protected static class ZuulFilterConfiguration { @Autowired private Map<String, ZuulFilter> filters; @Bean public ZuulFilterInitializer zuulFilterInitializer( CounterFactory counterFactory, TracerFactory tracerFactory) { FilterLoader filterLoader = FilterLoader.getInstance(); FilterRegistry filterRegistry = FilterRegistry.instance(); return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory, filterLoader, filterRegistry); } } @Configuration @ConditionalOnClass(CounterService.class) protected static class ZuulCounterFactoryConfiguration { @Bean @ConditionalOnBean(CounterService.class) public CounterFactory counterFactory(CounterService counterService) { return new DefaultCounterFactory(counterService); } } @Configuration protected static class ZuulMetricsConfiguration { @Bean @ConditionalOnMissingBean(CounterFactory.class) public CounterFactory counterFactory() { return new EmptyCounterFactory(); } @ConditionalOnMissingBean(TracerFactory.class) @Bean public TracerFactory tracerFactory() { return new EmptyTracerFactory(); } } private static class ZuulRefreshListener implements ApplicationListener<ApplicationEvent> { @Autowired private ZuulHandlerMapping zuulHandlerMapping; private HeartbeatMonitor heartbeatMonitor = new HeartbeatMonitor(); @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent || event instanceof RefreshScopeRefreshedEvent || event instanceof RoutesRefreshedEvent) { this.zuulHandlerMapping.setDirty(true); } else if (event instanceof HeartbeatEvent) { if (this.heartbeatMonitor.update(((HeartbeatEvent) event).getValue())) { this.zuulHandlerMapping.setDirty(true); } } } } }