依赖配置
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
启动
@RestController
@SpringBootApplication
public class DemogatewayApplication {
public static void main(String[] args) {
SpringApplication.run(DemogatewayApplication.class, args);
}
//普通一个rest接口
@RequestMapping("/hystrixfallback")
public String hystrixfallback() {
return "This is a fallback";
}
//这里定义一堆路由信息,跟上面的接口类似
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
//@formatter:off
return builder.routes()
.route("path_route", r -> r.path("/get")
.uri("http://httpbin.org"))
.route("host_route", r -> r.host("*.myhost.org")
.uri("http://httpbin.org"))
.route("rewrite_route", r -> r.host("*.rewrite.org")
.filters(f -> f.rewritePath("/foo/(?<segment>.*)",
"/${segment}"))
.uri("http://httpbin.org"))
.route("hystrix_route", r -> r.host("*.hystrix.org")
.filters(f -> f.hystrix(c -> c.setName("slowcmd")))
.uri("http://httpbin.org"))
.route("hystrix_fallback_route", r -> r.host("*.hystrixfallback.org")
.filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback")))
.uri("http://httpbin.org"))
.route("limit_route", r -> r
.host("*.limited.org").and().path("/anything/**")
.filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter())))
.uri("http://httpbin.org"))
.route("websocket_route", r -> r.path("/echo")
.uri("ws://localhost:9000"))
.build();
//@formatter:on
}
}
基于spring-boot 自动配置
GatewayAutoConfiguration(主配置)
@Configuration
//默认配置自动生效
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
//http协议处理配置,这是webflux的东西
@AutoConfigureBefore(HttpHandlerAutoConfiguration.class)
//负载均衡的一些配置
@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
@Configuration
@ConditionalOnClass(HttpClient.class)
protected static class NettyConfiguration {
//创建基于reactor netty的客户端
@Bean
@ConditionalOnMissingBean
public HttpClient httpClient(@Qualifier("nettyClientOptions") Consumer<? super HttpClientOptions.Builder> options) {
return HttpClient.create(options);
}
//配置上面netty 客户的作为消费端的一些配置信息
@Bean
public Consumer<? super HttpClientOptions.Builder> nettyClientOptions(HttpClientProperties properties) {
return opts -> {
// configure ssl
HttpClientProperties.Ssl ssl = properties.getSsl();
if (ssl.isUseInsecureTrustManager()) {
opts.sslSupport(sslContextBuilder -> {
sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE);
});
}
// 资源池配置
HttpClientProperties.Pool pool = properties.getPool();
if (pool.getType() == DISABLED) {
//不使用池
opts.disablePool();
} else if (pool.getType() == FIXED) {
//使用固定池
PoolResources poolResources = PoolResources.fixed(pool.getName(),
pool.getMaxConnections(), pool.getAcquireTimeout());
opts.poolResources(poolResources);
} else {
//使用弹性池
PoolResources poolResources = PoolResources.elastic(pool.getName());
opts.poolResources(poolResources);
}
//配置代理主机
HttpClientProperties.Proxy proxy = properties.getProxy();
if (StringUtils.hasText(proxy.getHost())) {
opts.proxy(typeSpec -> {
ClientProxyOptions.Builder builder = typeSpec
.type(ClientProxyOptions.Proxy.HTTP)
.host(proxy.getHost());
PropertyMapper map = PropertyMapper.get();
map.from(proxy::getPort)
.whenNonNull()
.to(builder::port);
map.from(proxy::getUsername)
.whenHasText()
.to(builder::username);
map.from(proxy::getPassword)
.whenHasText()
.to(password -> builder.password(s -> password));
map.from(proxy::getNonProxyHostsPattern)
.whenHasText()
.to(builder::nonProxyHosts);
return builder;
});
}
};
}
//netty 路由过滤器
@Bean
public NettyRoutingFilter routingFilter(HttpClient httpClient,
ObjectProvider<List<HttpHeadersFilter>> headersFilters) {
return new NettyRoutingFilter(httpClient, headersFilters);
}
//省略一些代码
}
//路由构造器
@Bean
public RouteLocatorBuilder routeLocatorBuilder(ConfigurableApplicationContext context) {
return new RouteLocatorBuilder(context);
}
//属性配置路由定议器,在properties文件里配置路由信息由该路由器处理
@Bean
@ConditionalOnMissingBean
public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
return new PropertiesRouteDefinitionLocator(properties);
}
//内存路由定义器,跟上面类似
@Bean
@ConditionalOnMissingBean(RouteDefinitionRepository.class)
public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() {
return new InMemoryRouteDefinitionRepository();
}
//多种路由定义器的组合,一般数组组合多种路由器
//实其该组合包含上面两外还包含一个动态的路由定议器
//DiscoveryClientRouteDefinitionLocator
@Bean
@Primary
public RouteDefinitionLocator routeDefinitionLocator(List<RouteDefinitionLocator> routeDefinitionLocators) {
return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators));
}
//创建定义路由器的路由器
//这里的routeDefinitionLocator 实际传入的上面组合定义器
//通过该定义器就可以定义各种路由信息
@Bean
public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
List<GatewayFilterFactory> GatewayFilters,
List<RoutePredicateFactory> predicates,
RouteDefinitionLocator routeDefinitionLocator) {
return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties);
}
//略去一些代码
//路由判断映射,routeLocator 是一个组合路由器或组合的代理
@Bean
public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler,
RouteLocator routeLocator) {
return new RoutePredicateHandlerMapping(webHandler, routeLocator);
}
//省去一堆代码
}
GatewayLoadBalancerClientAutoConfiguration
负载过滤的配置
@Configuration
@ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class, DispatcherHandler.class})
@AutoConfigureAfter(RibbonAutoConfiguration.class)
public class GatewayLoadBalancerClientAutoConfiguration {
@Bean
@ConditionalOnBean(LoadBalancerClient.class)
public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client) {
//实际传入的是RibbonBalancerClient,路由过程中会通过该client选择一个合适
//的服务实例去调用远端务
return new LoadBalancerClientFilter(client);
}
}
动态路由发现配置
GatewayDiscoveryClientAutoConfiguration
@Configuration
//默认开户动态路由
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@AutoConfigureBefore(GatewayAutoConfiguration.class)
@ConditionalOnClass({DispatcherHandler.class, DiscoveryClient.class})
@EnableConfigurationProperties
public class GatewayDiscoveryClientAutoConfiguration {
@Bean
@ConditionalOnBean(DiscoveryClient.class)
//默认不开户路由发现
@ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled")
public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(
DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) {
//创建动态路由定义器,disconverClient实质是eurekaClient具有发现列表的能力,据些可动态定义路由信息
return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties);
}
//省去一些代码
}
路由判断映射
RoutePredicateHandlerMapping
该类实现了HandlerMapping 接口,从前面分析的webflux来看,该实现将会将DispatchHandler 用来转路由判定处理