zuul 网关启动源码分析
1 依赖配置
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
启动
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy //启动zuul代理,@EnableZuulServer 非代理方式启动
public class ZuulApplication {
final static Logger logger = LoggerFactory.getLogger(ZuulApplication.class);
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(ZuulApplication.class)
.web(true).run(args);
logger.debug(applicationContext.getId() + "已经启动,当前host:{}",
applicationContext.getEnvironment().getProperty("HOSTNAME"));
}
}
2 自动启动配置入口过程
按springboot 源码分析的老套路从启动注解@EnableZuulProxy 开始
/**
* Sets up a Zuul server endpoint and installs some reverse proxy filters in it, so it can
* forward requests to backend servers. The backends can be registered manually through
* configuration or via DiscoveryClient.
*
* @see EnableZuulServer for how to get a Zuul server without any proxying
@EnableCircuitBreaker //开启断路器(hystrix)
@EnableDiscoveryClient
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}
//让ZuulProxyMarkerConfiguration 配置生效
@Configuration
public class ZuulProxyMarkerConfiguration {
//创建Marker 实例,让ZuulProxyMarkerConfiguration 配置生效
@Bean
public Marker zuulProxyMarkerBean() {
return new Marker();
}
class Marker {
}
}
//zuul代理配置
@Configuration
//引用创建下面三种客户端配置
@Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class })
//Marker 实例存在,该配置类生效
@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {
//省出一大波呆码
}
3 ZuulServerAutoConfiguration 代理配置详解
从上面可以看到ZuulProxyAutoConfiguration 继承ZuulServerAutoConfiguration 那么在这里先分析ZuulServerAutoConfiguration
//zuul 配置属性类,如路由等信息
@Autowired
protected ZuulProperties zuulProperties;
@Autowired
protected ServerProperties server;
//请求错误控制器
@Autowired(required = false)
private ErrorController errorController;
//省去一些代码
//组合路由定位器,将个种路由定位器进行组合
@Bean
@Primary
public CompositeRouteLocator primaryRouteLocator(
Collection<RouteLocator> routeLocators) {
return new CompositeRouteLocator(routeLocators);
}
//简单路由定位器,作用于uri与服务地址的匹配
@Bean
@ConditionalOnMissingBean(SimpleRouteLocator.class)
public SimpleRouteLocator simpleRouteLocator() {
return new SimpleRouteLocator(this.server.getServletPrefix(),
this.zuulProperties);
}
//关网控制器,会被ZuulServlet(跟DispatchServlet类似) 通过handlerAdapter找到并被调用
@Bean
public ZuulController zuulController() {
return new ZuulController();
}
//HandlerMapping 一个实现,这块完全是spring-mvc的东西
@Bean
public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) {
ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController());
mapping.setErrorController(this.errorController);
return mapping;
}
@Bean
public ApplicationListener<ApplicationEvent> zuulRefreshRoutesListener() {
return new ZuulServerAutoConfiguration.ZuulRefreshListener();
}
//如果zuulServlet 不存在存执行
@Bean
@ConditionalOnMissingBean(name = "zuulServlet")
public ServletRegistrationBean zuulServlet() {
ServletRegistrationBean servlet = new ServletRegistrationBean(new ZuulServlet(),
this.zuulProperties.getServletPattern());
// The whole point of exposing this servlet is to provide a route that doesn't
// buffer requests.
servlet.addInitParameter("buffer-requests", "false");
return servlet;
}
//实例化一个前置zuulfilter
@Bean
public ServletDetectionFilter servletDetectionFilter() {
return new ServletDetectionFilter();
}
//下面省去一波代码,主要是各中zuulfilter
4 ZuulProxyAutoConfiguration 代理配置详解
//ribbon个性化参数设置
@SuppressWarnings("rawtypes")
@Autowired(required = false)
private List<RibbonRequestCustomizer> requestCustomizers = Collections.emptyList();
//服务发布客户端
@Autowired
private DiscoveryClient discovery;
//服务路由匹配器
@Autowired
private ServiceRouteMapper serviceRouteMapper;
//省去一点代码
//注入封装了服务发现客户端各路由定位器及其它一些信息
@Bean
@ConditionalOnMissingBean(DiscoveryClientRouteLocator.class)
public DiscoveryClientRouteLocator discoveryRouteLocator() {
return new DiscoveryClientRouteLocator(this.server.getServletPrefix(), this.discovery, this.zuulProperties,
this.serviceRouteMapper);
}
//zuul 前置过滤器
@Bean
public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, ProxyRequestHelper proxyRequestHelper) {
return new PreDecorationFilter(routeLocator, this.server.getServletPrefix(), this.zuulProperties,
proxyRequestHelper);
}
// ribbon 路由过滤器,如果是使用serviceId请求服务执行该过滤器
@Bean
public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper,
RibbonCommandFactory<?> ribbonCommandFactory) {
RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory, this.requestCustomizers);
return filter;
}
// 主机地址路由器,如果发现是主要地址请求,帽执行该路由器
@Bean
@ConditionalOnMissingBean(SimpleHostRoutingFilter.class)
public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties zuulProperties) {
return new SimpleHostRoutingFilter(helper, zuulProperties);
}
//省去一堆代码
到这里,以上是zuul 启动的基本过程,一下编将会分析zuul请求的执行过程