1. 程式人生 > >Spring Boot Ribbon負載均衡配置的坑(避免被ComponentScan掃描)

Spring Boot Ribbon負載均衡配置的坑(避免被ComponentScan掃描)

配置

Spring Boot Ribbon負載均衡配置很簡單,網上一搜類似下面:

@Configuration
public class LoadBalanceConfiguration {

    @Bean
    public IRule rule() {
        return new WeightedResponseTimeRule();
    }
}

在Ribbon的文件中有這樣一段話:

The FooConfiguration has to be @Configuration but take care that it is not in a @ComponentScan

 for the main application context, otherwise it will be shared by all the @RibbonClients. If you use @ComponentScan (or @SpringBootApplication) you need to take steps to avoid it being included (for instance put it in a separate, non-overlapping package, or specify the packages to scan explicitly in the @ComponentScan
).

大體意思是對於Ribbon的配置必須用@Configuration註解標識,並且不能被@Component註解或者@SpringBootApplication(因為裡面包含了@Component)掃描到。因為如果被@ComponetScan掃描到會導致所有的RibbonClient都去共享這個配置。

樓主在使用Spring Cloud Gateway閘道器的過程中因為這樣自定義了負載均衡策略,但是出現:

訪問A服務:A/foo再去訪問B服務B/bar, 這個時候轉頭回來再訪問A/foo的時候會出現404.

通過debug發現在路由到指定的服務之後,使用Ribbon去做負載均衡,但是此時返回的負載均衡ILoadBalancer中鎖包含的IRule(負載均衡策略, 其中可以通過setLoadBalancer設定負載均衡器)實際上是上一個服務(B服務)的負載均衡器。

解決

按照上面英文描述的思路,方案如下:

@EnableDiscoveryClient
@SpringBootApplication
@ComponentScan(basePackages = "com.foo.bar", excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = LoadBalanceConfiguration.class)})
public class FooGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(FooGatewayApplication.class, args);
    }
}

關於具體的負載均衡策略配置,以及@ComponentScan詳解請自行百度。