一文搞懂流程和原理——Zuul应用网关

Zuul

Zuul是什么?

一个应用网关服务,为庞大复杂的微服务系统提供统一的对外门面。

能够提供动态路由,负载均衡,统一鉴权,协议转换,监控监测等一系列功能。

Zuul自带了Ribbon和hystrix依赖,提供负载均衡和容灾支持。

Zuul的各种功能实现是基于其一系列的过滤器来实现的。

Zuul怎么用?

使用@EnableZuulProxy注解开启Zuul

路由功能

zuul:
  routes: 
  	<服务名>:
  		path: /server/url/**
  		serviceId: <服务名>

以上配置会对请求路径符合/server/url/**规则的路由到对应的服务中去。

路由规则的匹配按照定义顺序进行,第一个匹配的成功返回,因此要保证有序,使用yaml代替properties文件

过滤器

ZuulFilter提供了四种类型的过滤器,分别为

  • pre:在请求被路由前调用
  • routing:在路由过程中调用,类似around
  • post:路由后调用
  • error:处理发生错误时被调用,通过判断context中是否含有Throwable判断,调用完后还会流到post中用于返回响应

对于同种类型的过滤器,order越小优先级越高,越先被调用

Zuul如何实现?

过滤器调用

Zuul实现了一个ServletWrappingController

public class ZuulController extends ServletWrappingController

即包裹了一个Servlet的Controller,所有请求经过SpringMVC的DispatcherServlet会转到这个Controller中,而这个Controller又会将请求转发到内部持有的Servlet中,即ZuulServlet

我们来看一下这个Servlet的实现,其过滤器的调用实现一目了然。

public void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {
        try {
            init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);

            // Marks this request as having passed through the "Zuul engine", as opposed to servlets
            // explicitly bound in web.xml, for which requests will not have the same data attached
            RequestContext context = RequestContext.getCurrentContext();
            context.setZuulEngineRan();

            try {
                preRoute();
            } catch (ZuulException e) {
                //error中会RequestContext.getCurrentContext().setThrowable(e),然后调用error过滤器
                error(e);
                postRoute();
                return;
            }
            try {
                route();
            } catch (ZuulException e) {
                error(e);
                postRoute();
                return;
            }
            try {
                postRoute();
            } catch (ZuulException e) {
                error(e);
                return;
            }

        } catch (Throwable e) {
            error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));
        } finally {
            RequestContext.getCurrentContext().unset();
        }
    }

路由转发

路由信息

RouteLocator
Route getMatchingRoute(String path)

解析请求URL为Route

例如访问http://localhost:8080/service/test 获取的Route

Route{id='service', fullPath='/service/test', path='/test', location='service', prefix='/service'}
SimpleRouteLocator

ZuulProperties即配置文件中获取路由信息,是Zuul路由配置的核心

DiscoveryClientRouteLocator

继承了SimpleRouteLocator,能够从DiscoveryClient中获取配置并添加到ZuulProperties

路由刷新

调用RouteLocatorrefresh()方法,会将ZuulProperties中的路由信息替换RouteLocator的私有属性Map

Zuul提供了ZuulRefreshListener监听刷新事件,自动调用RouteLocatorrefresh()方法

路由匹配

PreDecorationFilter

调用RouteLocator对路由信息进行匹配和预处理

RibbonRoutingFilter

当ServiceId不为空时使用该过滤器,根据ServiceId和Ribbon拿到具体的服务实例地址,进行转发。

SimpleHostRoutingFilter

RouteHost不为空时使用该过滤器

你可能感兴趣的:(SpringCloud)