SpringCloud 版本 Dalston.RELEASE 中ZUUL組件的BUG的解決辦法

近日在使用zuul組件時,出現下面的異常:

java.lang.NullPointerException: null

         at org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator.getRoutes(SimpleRouteLocator.java:72)
         at org.springframework.cloud.netflix.zuul.filters.CompositeRouteLocator.getRoutes(CompositeRouteLocator.java:55)
         at org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping.registerHandlers(ZuulHandlerMapping.java:102)
         at org.springframework.cloud.netflix.zuul.web.ZuulHandlerMapping.lookupHandler(ZuulHandlerMapping.java:93)
         at org.springframework.web.servlet.handler.AbstractUrlHandlerMapping.getHandlerInternal(AbstractUrlHandlerMapping.java:118)
         at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:352)

翻看源碼時, 其中模塊spring-cloud-netflix的版本號爲:1.3.0.RELEASE。類org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator 的代碼如下:

public List<Route> getRoutes() {
   if (this.routes.get() == null) {
      this.routes.set(locateRoutes());
   }
   List<Route> values = new ArrayList<>();
   for (String url : this.routes.get().keySet()) {
      ZuulRoute route = this.routes.get().get(url);
      String path = route.getPath();
      values.add(getRoute(route, path));
   }
   return values;
}

線程在調用getRoutes()方法時,其餘線程可能正在調用doRefresh()方法。所以在getRoutes()方法的兩次this.routes.get()時,成員屬性routes的值可能已經發生變更。

protected void doRefresh() {
   this.routes.set(locateRoutes());
}


解決辦法(二選一):

1:升級SpringCloud辦法爲:Edgware.SR3。

2:重寫RouteLocator類,並改寫getRoutes()方法,比如:

public class CustomerRouteLocator implements RouteLocator, Ordered, RefreshableRouteLocator

@Override
public List<Route> getRoutes() {
    if (this.routes.get() == null) {
        this.routes.set(locateRoutes());
    }
    List<Route> values = new ArrayList<>();

    Set<Map.Entry<String, ZuulProperties.ZuulRoute>> entries = this.routes.get().entrySet();

    for (Map.Entry<String, ZuulProperties.ZuulRoute> entry : entries) {
        ZuulProperties.ZuulRoute route = entry.getValue();
        String path = route.getPath();
        values.add(getRoute(route, path));
    }
    return values;
}

然後將此類註冊到Spring,如下:

@Configuration
public class CustomerRouteLocatorConfig extends ZuulProxyConfiguration {
@Bean
@ConditionalOnMissingBean(CustomerRouteLocator.class)
public CustomerRouteLocator customerRouteLocator() {
    return new CustomerRouteLocator(this.server.getServletPrefix(), this.discovery, this.zuulProperties,
            this.serviceRouteMapper);
}

@Bean
@Override
@ConditionalOnMissingClass("com.route.locator.CustomerRouteLocator")
public DiscoveryClientRouteLocator discoveryRouteLocator() {
    return null;
}

@Bean
@Override
@ConditionalOnMissingClass("com.route.locator.CustomerRouteLocator")
public SimpleRouteLocator simpleRouteLocator() {
    return null;
}
@EnableDiscoveryClient
@EnableCircuitBreaker
@SpringBootApplication(scanBasePackages = {"com.route"})
@Import(CustomerRouteLocatorConfig.class)
public class CustomerRouteZuulApplication {



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章