1. 程式人生 > >Spring Cloud Zuul原始碼分析

Spring Cloud Zuul原始碼分析

如何使用Spring Cloud Zuul?

之前的文章中,我們學習了Spring Cloud Zuul如何使用,這裡再回顧下:
1.引入依賴,在啟動類中新增@EnableZuulProxy,宣告這是一個Zuul代理。
2.註冊到Eureka Server,啟動服務,訪問這個埠,url中帶上要請求的服務名。

Spring Cloud Zuul原始碼分析

既然是添加了@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 * * @author Spencer Gibb * @author Dave Syer */
@EnableCircuitBreaker @EnableDiscoveryClient @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Import(ZuulProxyConfiguration.class) public @interface EnableZuulProxy { }

從註釋中可以看到,這個註解會啟動一個Zuul server,並且給這個Zuul server裝配一些代理過濾器,下面還提到了一個@EnableZuulServer註解,這個註解可以開啟一個Zuul server,但是不配置代理。@EnableZuulProxy可以看成是@EnableZuulServer的增強版。

@EnableZuulProxy註解上import了ZuulProxyConfiguration類,從名字上看,這個就是zuul代理的配置類,這個類中,定義了DiscoveryClient和其他一些負載均衡相關的類,還初始化了一些Filter。
ZuulProxyConfiguration類繼承了ZuulConfiguration,這個配置類就是對zuul進行一些配置的,裡面可以看到會初始化ZuulServlet和其他一些Zuul的bean以及Filter。

在ZuulConfiguration中,還有個ZuulFilterConfiguration內部類,這個內部類中會初始化ZuulFilterInitializer,存放所有的Filters。

Zuul定義了四種類型的過濾器:
1.Pre Filter
2.Route Filter
3.Post Filter
4.Error Filter

Pre過濾器是請求路由到具體的服務之前執行的,可以用來做安全驗證,引數驗證等操作。
Route過濾器是用來將請求路由到具體的服務上。
Post過濾器是請求已經被路由到微服務之後執行的。
如果Pre,Route和Post過濾器在執行過程中發生了異常,會由Error過濾器處理。
下面是這四種過濾器的執行順序:
這裡寫圖片描述

請求會先經過per filters,然後到routing filters,再去請求到具體的服務上,返回response之後,就經過post filters。如果發生異常,交給error filters。還可以自己自己定義filters。

自己定義filter,需要繼承ZuulFilter抽象類,重寫下面這四個方法:

public class MyFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return false;
    }

    @Override
    public Object run() {
        return null;
    }
}

其中,filterType方法,返回這個filter的型別,比如是pre型別的過濾器。
filterOrder是定義這個過濾器的執行順序,值越小,越先執行。
shouldFIlter返回該過濾器是否開啟,返回false,表示不執行這個過濾器。
run就是具體過濾器中需要執行的方法。

接下來再看下ZuulServlet:

@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 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(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();
        }
    }

從ZuulServlet中,也可以看出這個執行的邏輯。Zuul的主要功能,就是在這些Filter中了。