本文作者:陈刚,叩丁狼高级讲师。原创文章,转载请注明出处。
zuul舍命周期
zuul,在SpringCloud中充当服务网关的角色,它包含了请求路由,过滤,安全等功能,可以说是我们web应用的“安保人员”,保证了我们“微服务园区”的安全,那么zuul是如何实现路由和过滤等功能的呢?我这里有一张摘抄于SpringCloud官网的zuul的生命周期图片

叩丁狼教育.png
这张图的大致流程为:
1.当客户端请求过来首先会到 "pre" filters 这样的一个前置过滤器做一些处理,然后调用自定义的过滤器
2.前置过滤器执行完了之后会调用 “routing”filter 过滤器 ,看名字都知道这是做路由分发的过滤器
3.在路由的过程中出现了异常,那么会走 “error”filters过滤器,然后再走 "post"filters 过滤器 ,或者正常路由完成也会走到“post”filters
4."post"filters过滤器负责处理响应 ,最后把结果响应给客户端
这里是zuul大致的生命周期流程,我们看到它这里大量用到了filter进行处理,并且Zuul允许我们自定义Filter ,他提供了抽象的 ZuulFilter 过滤器,里面有四个基本方法,我们要自定义Filter就需要继承ZuulFilter,然后复写四个方法
/**
服务过滤
*/
@Component
public class MyFilter extends ZuulFilter {
/**
返回过滤器的类型,过滤器类型如下:
pre:请求路由之前调用过滤
routing:请求routing之时调用过滤
post: 请求路由之后调用过滤
error:发送错误时调用过滤
*/
@Override
public String filterType() {
return "pre";
}
//filterOrder:过滤的顺序
@Override
public int filterOrder() {
return 0;
}
//shouldFilter:是否要过滤,true表示永远过滤。我们可以在这里做一写过滤处理
@Override
public boolean shouldFilter() {
return true;
}
//当前过滤器的执行方法
//我们可以在该方法中处理一些自己的判断
@Override
public Object run() {
//获取请求对象
RequestContext ctx = RequestContext.getCurrentContext();
Object pass = ctx.getRequest().getParameter("pass");
if(pass == null) {
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
try {
ctx.getResponse().getWriter().write("pass is empty");
}catch (Exception e){}
}
return null;
}
}
那么我们接下来就分析他的源码就是去看这些内置的filter做了什么事情。
zuul的启动/配置
简单回顾一下zuul的使用 ,除了引入zuul相关依赖而外,我们要使用zull还需要在配置类上开启zuul功能
//@EnableZuulProxy :开启路由网关功能
@SpringBootApplication
@EnableZuulProxy
public class ServiceZuulApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceZuulApplication.class, args);
}
}
EnableZuulProxy的注释告诉我们,这里设设置Zuul服务器端点,和安装了一些过滤器,通过这些过滤器它可以转发请求到后端服务器
/**
* 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
*
* @author Spencer Gibb
* @author Dave Syer
* @author Biju Kunjummen
*/
@EnableCircuitBreaker
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}
不过这里引入了 ZuulProxyMarkerConfiguration 配置类,这个配置在干嘛呢?
/**
* Responsible for adding in a marker bean to trigger activation of
* {@link ZuulProxyAutoConfiguration}
*
* @author Biju Kunjummen
*/
@Configuration
public class ZuulProxyMarkerConfiguration {
@Bean
public Marker zuulProxyMarkerBean() {
return new Marker();
}
class Marker {
}
}
翻译:“Responsible for adding in a marker bean to trigger activation of
- {@link ZuulProxyAutoConfiguration}”
它在负责添加标记bean以触发激活 ZuulProxyAutoConfiguration 这个类,研究过springboot自动配置的同学就会知道 ,SpringBoot 中会有大量的 xxxAutoConfiguration 自动配置的类会在应用启动的过程中被激活实现自动装配,从而节省了我们很多的配置。
而这个类在配置些什么东西?
/**
* @author Spencer Gibb
* @author Dave Syer
* @author Biju Kunjummen
*/
@Configuration
//这里引入了几种客户端配置
@Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class,
RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class,
HttpClientConfiguration.class })
//如果存在了 ZuulProxyMarkerConfiguration.Marker的实例,该配置生效,这里是满足条件的
@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {
...省略代码...
ZuulProxyAutoConfiguration继承了 ZuulServerAutoConfiguration ,我们先看下这个配置类
/**
* @author Spencer Gibb
* @author Dave Syer
* @author Biju Kunjummen
*/
@Configuration
@EnableConfigurationProperties({ ZuulProperties.class })
@ConditionalOnClass(ZuulServlet.class)
@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class)
// Make sure to get the ServerProperties from the same place as a normal web app would
// FIXME @Import(ServerPropertiesAutoConfiguration.class)
public class ZuulServerAutoConfiguration {
//绑定zuul的配置信息
@Autowired
protected ZuulProperties zuulProperties;
@Autowired
protected ServerProperties server;
//注入请求错误控制器
@Autowired(required = false)
private ErrorController errorController;
@Bean
public HasFeatures zuulFeature() {
return HasFeatures.namedFeature("Zuul (Simple)", ZuulServerAutoConfiguration.class);
}
//RouteLocator that composes multiple RouteLocators. :
//多路由组合定位器
@Bean
@Primary
public CompositeRouteLocator primaryRouteLocator(
Collection<RouteLocator> routeLocators) {
return new CompositeRouteLocator(routeLocators);
}
//简单的路由定位器
@Bean
@ConditionalOnMissingBean(SimpleRouteLocator.class)
public SimpleRouteLocator simpleRouteLocator() {
return new SimpleRouteLocator(this.server.getServlet().getServletPrefix(),
this.zuulProperties);
}
@Bean
public ZuulController zuulController() {
return new ZuulController();
}
// MVC HandlerMapping that maps incoming request paths to remote services.
//看名字也知道,他是做请求路径和远程服务的映射的,是 HandlerMapping的实现
@Bean
public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) {
ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController());
mapping.setErrorController(this.errorController);
return mapping;
}
//定义ZuulRefreshListener zuul刷新的监听器
@Bean
public ApplicationListener<ApplicationEvent> zuulRefreshRoutesListener() {
return new ZuulRefreshListener();
}
// Core Zuul servlet which intializes and orchestrates zuulFilter execution
//这里在注册ZuulServlet 这样的一个servlet, 这个东西了不得了,
//他是负责核心Zuul servlet初始化和调用zuulFilter执行,跟DispatcherServlet差不过
@Bean
@ConditionalOnMissingBean(name = "zuulServlet")
public ServletRegistrationBean zuulServlet() {
ServletRegistrationBean<ZuulServlet> 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;
}
// pre filters :
//前置过滤器,看名字是用来做检测的
@Bean
public ServletDetectionFilter servletDetectionFilter() {
return new ServletDetectionFilter();
}
//前置过滤器,是对请求数据做一些增强处理
@Bean
public FormBodyWrapperFilter formBodyWrapperFilter() {
return new FormBodyWrapperFilter();
}
@Bean
public DebugFilter debugFilter() {
return new DebugFilter();
}

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



