https://www.jianshu.com/p/9b813f6ca4c2
spring cloud gateway 作为新一代的微服务网关已经发布了一段时间,我从7月份开始使用到现在已经4个月了。但是我一直处于一种只会使用,原理一知半解的水平。我们小组作为公司微服务产品的实践者,我自己作为组中一员完成了spring cloud gateway的开发,也解决了很多棘手的问题,却对它的原理和启动流程一知半解,好几次就是因为不了解它的启动流程,导致开发受挫,进度缓慢。现在正值闲时,正好看一下相关的源码,理解他的启动流程。本文基于spring cloud Finchley.RELEASE版本,最新的SR2版本一些内容有改变,但总体改变不大。
首先是网关的包结构
其中actuate中定义了一个叫GatewayControllerEndpoint的类,这个类提供一些对外的接口,可以获取网关的一些信息,比如路由的信息,改变路由地址等等。
config中定义了一些启动时去加载的类,配置路由信息和读取你的配置文件就在这里完成。
discovery中定义了注册中心相关的内容,包括注册中心的路由等。
event定义了一些事件他们都继承自ApplicationEvent,对事件发布不了解的可以去看看spring的代码。
filter中定义了spring cloud gateway实现的一些过滤器。
handler中定义了很多Predicate相关的Factory
route就是我们路由的相关
support是工具包等。
下面就是gateway启动流程的分析了
config包
网关启动第一步加载的就是去加载config包下的几个类。
这几个类就定义了网关需要加载的配置项。
在我第一次做网关开发的时候我引入了spring-boot-starter-web的依赖,这样是会报错的,因为gateway是基于spring-webflux开发的,他依赖的DispatcherHandler就和我们web里的DispatcherServlet一样的功能。
这里的GatewayClassPathWarningAutoConfiguration这个类,就指明了我们需要什么不需要什么,他加载于GatewayAutoConfiguration之前,如果DispatcherServlet存在,就会给与警告,同样的DispatcherHandler不存在也会警告。
@Configuration
@AutoConfigureBefore(GatewayAutoConfiguration.class)
public class GatewayClassPathWarningAutoConfiguration {
private static final Log log = LogFactory.getLog(GatewayClassPathWarningAutoConfiguration.class);
private static final String BORDER = "\n\n**********************************************************\n\n";
@Configuration
@ConditionalOnClass(name = "org.springframework.web.servlet.DispatcherServlet")
protected static class SpringMvcFoundOnClasspathConfiguration {
public SpringMvcFoundOnClasspathConfiguration() {
log.warn(BORDER+"Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. "+
"Please remove spring-boot-starter-web dependency."+BORDER);
}
}
@Configuration
@ConditionalOnMissingClass("org.springframework.web.reactive.DispatcherHandler")
protected static class WebfluxMissingFromClasspathConfiguration {
public WebfluxMissingFromClasspathConfiguration() {
log.warn(BORDER+"Spring Webflux is missing from the classpath, which is required for Spring Cloud Gateway at this time. "+
"Please add spring-boot-starter-webflux dependency."+BORDER);
}
}
}
它加载完成之后加载的是GatewayLoadBalancerClientAutoConfiguration这个是gateway负载均衡的过滤器实现的加载,他将LoadBalancerClientFilter 注入到了容器中,这个过滤器后面再说。
@Configuration
@ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class, DispatcherHandler.class})
@AutoConfigureAfter(RibbonAutoConfiguration.class)
public class GatewayLoadBalancerClientAutoConfiguration {
// GlobalFilter beans
@Bean
@ConditionalOnBean(LoadBalancerClient.class)
public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client) {
return new LoadBalancerClientFilter(client);
}
}
之后便是我们的GatewayAutoConfiguration正式加载了,这个里面定义了非常多的内容,我们大部分用到的过滤器,过滤器工厂都是在这里构建的。包括之前的gatewayControllerEndpoint也是在这里注入容器中的。这个类的定义很长,我就不再这里都放了,列举几个。
@Configuration
//开启网关,不写默认为true
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore(HttpHandlerAutoConfiguration.class)
@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
@Configuration
@ConditionalOnClass(HttpClient.class)
protected static class NettyConfiguration {
@Bean
@ConditionalOnMissingBean
public HttpClient httpClient(@Qualifier("nettyClientOptions") Consumer<? super HttpClientOptions.Builder> options) {
return HttpClient.create(options);
}
... //还有很多 这里不列举了。我们都知道spring cloud 是基于Netty实现的,这里他这个静态内部类就是初始化netty需要的东西。
}
//初始化了加载配置文件的对象,建立route
@Bean
public GatewayProperties gatewayProperties() {
return new GatewayProperties();
}
//初始化请求转发 过滤器
@Bean
@ConditionalOnProperty(name = "spring.cloud.gateway.forwarded.enabled", matchIfMissing = true)
public ForwardedHeadersFilter forwardedHeadersFilter() {
return new ForwardedHeadersFilter();
}
//最后初始化gatewayControll