首页 文章

Zuul Api Gateway映射了错误的服务URL(字符集)?

提问于
浏览
0

我试图创建微服务,但zuul api网关服务maped错误的网址 . 似乎它与编码问题有关 .

Zuul application.properties

spring.application.name=zuul-api-gateway
server.port=8765

eureka.client.service-url.default-zone=http://localhost:8761/eureka

服务application.yml

spring:
  application:
    name: car-service
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3307/car_service_db?useSSL=false
    username: root
    password: admin
  profiles:
    active: local
server:
  port: 8080

eureka:
  client:
    service-url:
      default-zone: http://localhost:8761/eureka

management:
  security:
    enabled: false

其他服务application.yml

spring:
  application:
    name: company-service
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3307/company_service_db?useSSL=false
    username: root
    password: admin
server:
  port: 8081

eureka:
  client:
    service-url:
      default-zone: http://localhost:8761/eureka


management:
  security:
    enabled: false

尤里卡日志:

2018-02-11 00:02:41.204  INFO 22672 --- [nio-8761-exec-2] c.n.e.registry.AbstractInstanceRegistry  : Registered instance CAR-SERVICE/localhost:car-service:8080 with status UP (replication=false)
2018-02-11 00:02:58.469  INFO 22672 --- [a-EvictionTimer] c.n.e.registry.AbstractInstanceRegistry  : Running the evict task with compensationTime 0ms
2018-02-11 00:03:06.468  INFO 22672 --- [nio-8761-exec-4] c.n.e.registry.AbstractInstanceRegistry  : Registered instance COMPANY-SERVICE/localhost:company-service:8081 with status UP (replication=false)
2018-02-11 00:03:26.139  INFO 22672 --- [nio-8761-exec-9] c.n.e.registry.AbstractInstanceRegistry  : Registered instance ZUUL-API-GATEWAY/localhost:zuul-api-gateway:8765 with status UP (replication=false)

和zuul日志

2018-02-11 00:03:35.037  INFO [zuul-api-gateway,6944cfba5180a640,6944cfba5180a640,false] 2132 --- [nio-8765-exec-1] o.s.c.n.zuul.web.ZuulHandlerMapping      : Mapped URL path [/car-servıce/**] onto handler of type [class org.springframework.cloud.netflix.zuul.web.ZuulController]
2018-02-11 00:05:06.872  INFO [zuul-api-gateway,773aa5fc779af5e6,773aa5fc779af5e6,false] 2132 --- [nio-8765-exec-3] o.s.c.n.zuul.web.ZuulHandlerMapping      : Mapped URL path [/company-servıce/**] onto handler of type [class org.springframework.cloud.netflix.zuul.web.ZuulController]
2018-02-11 00:05:06.873  INFO [zuul-api-gateway,773aa5fc779af5e6,773aa5fc779af5e6,false] 2132 --- [nio-8765-exec-3] o.s.c.n.zuul.web.ZuulHandlerMapping      : Mapped URL path [/zuul-apı-gateway/**] onto handler of type [class org.springframework.cloud.netflix.zuul.web.ZuulController]

在zuul日志中,所有服务都用特殊字母和'ı'映射,这是土耳其字符而不是'i',我无法通过zuul api网关到达我的服务 .

我在这个例子中也试过覆盖Zuul配置:Spring-Cloud Zuul breaks UTF-8 symbols in forwarded multipart request filename

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Bean
    FormBodyWrapperFilter formBodyWrapperFilter() {
        return new FormBodyWrapperFilter(new MyFormHttpMessageConverter());
    }

    private class MyFormHttpMessageConverter extends FormHttpMessageConverter {

        private byte[] getAsciiBytes(String name) {
            try {
                // THIS IS THE ONLY MODIFICATION:
                return name.getBytes("UTF-8");
            } catch (UnsupportedEncodingException ex) {
                // Should not happen - US-ASCII is always supported.
                throw new IllegalStateException(ex);
            }
        }
    }
}

因此,当我通过Zuul api网关尝试呼叫服务时,它返回404未找到 .

我使用spring-boot 2.0.0.M3,spring-cloud Finchley.M2版本

2 回答

  • 0

    当你使用Spring启动时,我建议你为zuul网关使用注释,并为zuul创建自定义过滤器,它将照顾每一件事 .

    请找到下面的代码,看看它是否适合您:

    主类

    @EnableZuulProxy
    @SpringBootApplication
    @EnableScheduling
    @EnableFeignClients(basePackages = { Constants.FEIGN_BASE_PACKAGE })
    @ComponentScan(basePackages = { Constants.BASE_PACKAGE, Constants.LOGGING_PACKAGE })
    @EntityScan(basePackages = { Constants.ENTITY_BASE_PACKAGE })
    @EnableDiscoveryClient
    public class GatewayInitializer {
    
        /**
         * The main method.
         *
         * @param args the arguments
         */
        public static void main(String[] args) {
    
            Security.setProperty("networkaddress.cache.ttl", "30");
            ConfigurableApplicationContext context = SpringApplication.run(Initializer.class, args);
    
        }
    

    ZUUL过滤器

    package com.sxm.aota.gateway.filters;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.MessageSource;
    import org.springframework.util.ReflectionUtils;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.netflix.zuul.ZuulFilter;
    import com.netflix.zuul.context.RequestContext;
    import com.netflix.zuul.exception.ZuulException;
    
    
    /**
     * This CustomErrorFilter involve to handle ZuulException.
     */
    public class CustomErrorFilter extends ZuulFilter {
    
        /** The logger. */
        private static final Logger logger = LoggerFactory.getLogger(CustomErrorFilter.class);
        /** The message source. */
        @Autowired
        private MessageSource messageSource;
        /** The properties. */
        @Autowired
        private Properties properties;
    
        /*
         * (non-Javadoc)
         * 
         * @see com.netflix.zuul.ZuulFilter#filterType()
         */
        @Override
        public String filterType() {
            return "post";
        }
    
        /*
         * (non-Javadoc)
         * 
         * @see com.netflix.zuul.ZuulFilter#filterOrder()
         */
        @Override
        public int filterOrder() {
            return -1; // Needs to run before SendErrorFilter which has filterOrder == 0
        }
    
        /*
         * (non-Javadoc)
         * 
         * @see com.netflix.zuul.IZuulFilter#shouldFilter()
         */
        @Override
        public boolean shouldFilter() {
            // only forward to errorPath if it hasn't been forwarded to already
            return RequestContext.getCurrentContext().containsKey("error.status_code");
        }
    
        /*
         * (non-Javadoc)
         * 
         * @see com.netflix.zuul.IZuulFilter#run()
         */
        @Override
        public Object run() {
            try {
                RequestContext ctx = RequestContext.getCurrentContext();
                Object e = ctx.get("error.exception");
                if (e != null && e instanceof ZuulException) {
                    ZuulException zuulException = (ZuulException) e;
                    logger.error("Zuul failure detected: " + zuulException.getMessage(), zuulException);
                    // Remove error code to prevent further error handling in follow up filters
                    ctx.remove("error.status_code");
    
                    } else {
                        error.setMessage(messageSource.getMessage(Constants.REQUESTED_SERVICE_UNAVAILABLE, new Object[] { zuulException.getCause() }, properties.getCurrentLocale()));
                        ctx.setResponseBody(mapper.writeValueAsString(error));
                        ctx.getResponse().setContentType("application/json");
                        ctx.setResponseStatusCode(500); // Can set any error code as excepted
                    }
                }
            } catch (Exception ex) {
                logger.error("Exception filtering in custom error filter", ex);
                ReflectionUtils.rethrowRuntimeException(ex);
            }
            return null;
        }
    }
    
  • 0

    我通过为toLowerCase(Locale.ROOT)选项创建扩展的EurekaDiscoveryClient来解决问题 .

    import com.netflix.appinfo.EurekaInstanceConfig;
    import com.netflix.discovery.EurekaClient;
    import com.netflix.discovery.shared.Application;
    import com.netflix.discovery.shared.Applications;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.cloud.client.discovery.DiscoveryClient;
    import org.springframework.cloud.netflix.eureka.EurekaDiscoveryClient;
    import org.springframework.stereotype.Component;
    
    import java.util.*;
    
    @Component
    public class CustomEurekaDiscoveryClient extends EurekaDiscoveryClient implements DiscoveryClient {
    
    
        private final EurekaInstanceConfig config;
    
        private final EurekaClient eurekaClient;
    
        public CustomEurekaDiscoveryClient(EurekaInstanceConfig config, @Qualifier("eurekaClient") EurekaClient eurekaClient) {
            super(config, eurekaClient);
            this.config = config;
            this.eurekaClient = eurekaClient;
        }
    
        @Override
        public List<String> getServices() {
            Applications applications = this.eurekaClient.getApplications();
            if (applications == null) {
                return Collections.emptyList();
            }
            List<Application> registered = applications.getRegisteredApplications();
            List<String> names = new ArrayList<>();
            for (Application app : registered) {
                if (app.getInstances().isEmpty()) {
                    continue;
                }
                names.add(app.getName().toLowerCase(Locale.ROOT));
    
            }
            return names;
        }
    }
    

    大写'I'转换为土耳其语OS和jvm中的小写'ı'而不是'i'这就是我需要覆盖 public List getServices() 方法的原因 .

    如果toLowerCase(Locale.ROOT)方法在没有 Locale.ROOT java转换字符的情况下调用'ı'但使用 Locale.ROOT 选项,方法转换为'i'并且项目工作正常 .

相关问题