“This is the fourth day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

Principle of ZUul routing

 

The gateway processes the request and distributes it to the microservice application. After the microservice processes the request, the microservice returns the result to the gateway. The gateway is responding to the client.

 

How do we achieve the effect of Zuul?

User access -> preRouterFilter -> routerFilter -> PostRouterFilter -> Micro service

The core essence of Zuul is the filter. All functions of Zuul are implemented in the filter

Zuul parses our URL to determine which microservice we’re going to access, and this is a filter that Zuul sends requests to access the microservice, and this is also a filter that Zuul gives the user response data, and this is also a filter

1. The relationship between the four filters

This is a gateway filter that contains four filter types.

When a request comes in, it enters pre, then Routing, and finally the Post filter. If an exception occurs in any of the three filters, the error routing filter is entered

2. Share the RequestContext

All filters in Zuul share RequestContext in the same thread.

ZuulFilter shares accessed variables through RequestContext

User access to Zuul

To think about this, we can class springMVC. Where does the user request entry go in springMVC? DispatcherServlet.

So zuul is the same, its entry is also a servlet, called ZuulServlet

Let’s take a look at the core code of the Zuul-core package

 

Inside there is an HTTP folder, which handles requests from users in HTTP files

 

The entry point to Zuul is zuulServlet

In servlets, we know that the main method it executes is service. So let’s look at the main core method service()

public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {try {// Initialize the HTTP request this.init((HttpServletRequest)servletRequest, (HttpServletResponse) servletResponse); / / all request will create a RequestContent RequestContext context. = the RequestContext getCurrentContext (); // For the current access, set a processing engine context.setzuulengineran (); PreRoute = preRoute = preRoute = preRoute = preRoute = preRoute = preRoute = preRoute } catch (ZuulException var12) {this.error(var12); // After entering the post route filter, the user's response data is returned to the client through the post filter this.postroute (); return; } try {// The route filter is used to convert the user's request into a zuul request to access the micro-service this.route(); } catch (ZuulException var13) { this.error(var13); this.postRoute(); return; } try {// Return the data of the micro-service response to the client this.postroute (); } catch (ZuulException var11) { this.error(var11); } } catch (Throwable var14) { this.error(new ZuulException(var14, 500, "UNHANDLED_EXCEPTION_" + var14.getClass().getName())); } finally { RequestContext.getCurrentContext().unset(); }}Copy the code

Let’s look at the source code.

 

Source code flow as above

The following uses a prefilter as an example to illustrate the principle of filter execution

What are the key filters of Zuul?

Let’s see what filters spring has loaded.

Spring will automatically scan annotations, loading all the filters of the two classes ZuulProxyAutoConfiguration class to see the key core filter ZuulServerAutoConfiguration inside the key to the core of the filterCopy the code

This is registered in ZuulProxyAutoConfiguration filter

This is registered in ZuulServierAutoConfiguration filter

Summary:

Pre filter:

PreDecorationFilter
ServletDetectionFilter
FormBodyWrapperFilter
DebugFilter
Servlet30WrapperFilter
Copy the code

Routing filter

RibbonRoutingFilter
SimpleHostRoutingFilter
Copy the code

The post filter

SendResponseFilter
SendForwardFilter
Copy the code

The error filter

SendErrorFilter
Copy the code

In fact, there are so many filters, the error filter is not to say, there are exceptions that go into the error filter

Then the most important of the other filters are the following three.

After a user request is made, a prefilter first parses the connection and assembles the route.

The route filter is then executed to jump to the specified microservice

Finally, the POST filter is executed to return the results of the execution to the user

1. What does the preDecorationFilter do

By looking at the source code, we get the above information, in fact, here is the main thing to do, that is to sort out the back to jump to the micro service routing information

@Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); final String requestURI = this.urlPathHelper .getPathWithinApplication(ctx.getRequest()); Route route = this.routeLocator.getMatchingRoute(requestURI); if (route ! = null) { String location = route.getLocation(); if (location ! = null) { ctx.put(REQUEST_URI_KEY, route.getPath()); ctx.put(PROXY_KEY, route.getId()); if (! route.isCustomSensitiveHeaders()) { this.proxyRequestHelper.addIgnoredHeaders( this.properties.getSensitiveHeaders().toArray(new String[0])); } else { this.proxyRequestHelper.addIgnoredHeaders( route.getSensitiveHeaders().toArray(new String[0])); } if (route.getRetryable() ! = null) { ctx.put(RETRYABLE_KEY, route.getRetryable()); } if (location.startsWith(HTTP_SCHEME + ":") || location.startsWith(HTTPS_SCHEME + ":")) { ctx.setRouteHost(getUrl(location)); ctx.addOriginResponseHeader(SERVICE_HEADER, location); } else if (location.startsWith(FORWARD_LOCATION_PREFIX)) { ctx.set(FORWARD_TO_KEY, StringUtils.cleanPath( location.substring(FORWARD_LOCATION_PREFIX.length()) + route.getPath())); ctx.setRouteHost(null); return null; } else { // set serviceId for use in filters.route.RibbonRequest ctx.set(SERVICE_ID_KEY, location); ctx.setRouteHost(null); ctx.addOriginResponseHeader(SERVICE_ID_HEADER, location); } if (this.properties.isAddProxyHeaders()) { addProxyHeaders(ctx, route); String xforwardedfor = ctx.getRequest() .getHeader(X_FORWARDED_FOR_HEADER); String remoteAddr = ctx.getRequest().getRemoteAddr(); if (xforwardedfor == null) { xforwardedfor = remoteAddr; } else if (! xforwardedfor.contains(remoteAddr)) { // Prevent duplicates xforwardedfor += ", " + remoteAddr; } ctx.addZuulRequestHeader(X_FORWARDED_FOR_HEADER, xforwardedfor); } if (this.properties.isAddHostHeader()) { ctx.addZuulRequestHeader(HttpHeaders.HOST, toHostHeader(ctx.getRequest())); } } } else { log.warn("No route found for uri: " + requestURI); String forwardURI = getForwardUri(requestURI); ctx.set(FORWARD_TO_KEY, forwardURI); } return null; }Copy the code

2. RibbonRoutintFilter

 

 

This is a very important filter in Zuul, which performs routing to microservices. The specific process is described above

 

 

 

 

 

3. SendResponseFilter

This filter is the request that the microservice responds to back to the user

 

 

You can also look at the other filters and see the loading order between them.