spring cloud zuul在使用中遇到的坑

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

在使用zuul的时候遇到的坑总结一下:
逐渐增加更新以后遇到的
1、在路由的时候莫名其妙的把serviceId给去掉,导致404。比如请求:/serviceId/search/book,zuul会把serviceId去掉,导致匹配不到服务404
解决办法:
zuul:
strip-prefix: false

因为我们没有设置zuul.prefix 为所有的匹配增加前缀, 例如 /api,代理前缀默认会从请求路径中移除(通过 zuul.stripPrefix=false 可以关闭这个功能)

当stripPrefix=true的时候 (http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/user/list) #

当stripPrefix=false的时候(http://127.0.0.1:8181/api/user/list -> http://192.168.1.100:8080/api/user/list) #

设置这个值以后还是出现了404的问题。最后只能自己实现路由映射。
自定义路由:https://www.jianshu.com/p/647cf467b47c
2、在zuul的过滤器中,有一个FormBodyWrapperFilter过滤器,在使用resin做web容器时启动会报 ServletRequestWrapper.request field not found
通过跟踪源码发现resin的ServletRequestWrapper种的request会多一个下划线,导致

    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);
                    }
                }
            }

        }

    }
赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » spring cloud zuul在使用中遇到的坑

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏