参考资料:
Spring Cloud 官网
Zuul wiki
相关版本:zuul 1.3.1,spring boot 2.1.4 ,spring cloud Greenwich.SR1
一个简单的 zuul 案例
-
step1、引入依赖
// zuul 依赖
spring-cloud-starter-netflix-zuul
// eureka 依赖
spring-cloud-starter-netflix-eureka-client -
step2、开启 zull 功能
@EnableZuulProxy -
step3、application.properties 相关配置
## 服务名称
spring.application.name = gateway
server.port=18080
## 配置路由映射 ,忽略其他的路由
#zuul.routes.admin = /admin/**
zuul.routes.admin.path = /admin/**
zuul.routes.admin.sensitive-headers =
zuul.routes.admin.service-id = admin
zuul.ignored-services = *
# 注册到 eureka 服务中
eureka.client.enabled = true
eureka.client.service-url.defaultZone = http://user-wtf:pwd-wtf@localhost:1111/eureka
通过上面三个步骤配置,便完成了一个带有路由和过滤功能的 API 网关。
zuul 工作流程
zuul 功能开启
追踪注解 @EnableZuulProxy
@EnableCircuitBreaker
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}
@EnableZuulProxy 引入了配置类 ZuulProxyMarkerConfiguration
聚焦 ZuulProxyMarkerConfiguration
@Configuration
public class ZuulProxyMarkerConfiguration {
@Bean
public Marker zuulProxyMarkerBean() {
return new Marker();
}
class Marker {
}
}
可以看到 ZuulProxyMarkerConfiguration 中实例化了一个空的对象 Marker。
这个空对象实例 ZuulProxyMarkerConfiguration .Marker 有啥用?
通过查看 zuul的两个自动配置类:ZuulServerAutoConfiguration 、 ZuulProxyAutoConfiguration 类上的注解
可以得出结论:ZuulProxyMarkerConfiguration.Marker.class 是 zuul 实现自动配置的触发开关。
换句话说,@EnableZuulProxy 是触发 zuul 自动配置的开关,相当于 zuul 功能开启开关。
zuul 工作路程图
[外链图片转存失败(img-3hSjKrWA-1562471647049)(/img/technological_course/spring/spring-cloud/Spring Cloud Zuul【源码篇】Zuul工作流程_zuul流程图 .jpg)]
上图是 Zuul 处理请求的全过程。
zuul 主线执行流程
ZuulController
1、在 ZuulServerAutoConfiguration 自动配置类中进行实例化。实例托管 Spring 。
public class ZuulServerAutoConfiguration {
@Bean
public ZuulController zuulController() {
return new ZuulController();
}
}
2、ZuulController 功能作用
public class ZuulController extends ServletWrappingController {
public ZuulController() {
setServletClass(ZuulServlet.class);
setServletName("zuul");
setSupportedMethods((String[]) null); // Allow all
}
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
try {
// We don't care about the other features of the base class, just want to
// handle the request
return super.handleRequestInternal(request, response);
}
finally {
// @see com.netflix.zuul.context.ContextLifecycleFilter.doFilter
RequestContext.getCurrentContext().unset();
}
}
}
ZuulController 继承自 ServletWrappingController。
ServletWrappingController 作用:将应用中的某个 Servlet 封装成 Controller 用来处理 Servlet 中的所有请求。
ZuulController 是 ZuulServlet Controller 方式的封装。
ZuulController 拦截了 zuulServlet 处理的请求,
通过 ZuulController#handleRequest 中的 super.handleRequestInternal(request, response); 最终调用 ZuulServlet#service
ZuulServlet
1、在 ZuulServerAutoConfiguration 自动配置类中实例化并注册为一个 servlet 。实例托管 Spring 。
public class ZuulServerAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "zuulServlet")
@ConditionalOnProperty(name = "zuul.use-filter", havingValue = "false", matchIfMissing = true)
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;
}
}
2、ZuulServlet 主要功能作用
public class ZuulServlet extends HttpServlet {
@Override
public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
try {
init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
// Marks this request as havi