There are some minor changes in the implementation of various versions of zuul, and the overall implementation idea has not changed. Take spring-cloud-netflix-core-1.3.6.RELEASE as an example.
1. Important initialization classes of zuul
org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration
org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration
org.springframework.cloud.netflix.zuul.ZuulFilterInitializer
org.springframework.cloud.netflix.zuul.RibbonCommandFactoryConfiguration
ZuulServerAutoConfiguration
Initialize routing rules
Initialize some important filters such as PreDecorationFilter, RibbonRoutingFilter
Initialize ZuulFilterInitializer
Initialize ZuulHandlerMapping
The code is as follows
//Routing rules @Bean @ConditionalOnMissingBean(DiscoveryClientRouteLocator.class) public DiscoveryClientRouteLocator discoveryRouteLocator() { return new DiscoveryClientRouteLocator(this.server.getServletPrefix(), this.discovery, this.zuulProperties, this.serviceRouteMapper); } // pre filters @Bean public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, ProxyRequestHelper proxyRequestHelper) { return new PreDecorationFilter(routeLocator, this.server.getServletPrefix(), this.zuulProperties, proxyRequestHelper); } // route filters @Bean public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper, RibbonCommandFactory<?> ribbonCommandFactory) { RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory, this.requestCustomizers); return filter; } @Configuration protected static class ZuulFilterConfiguration { @Autowired private Map<String, ZuulFilter> filters; @Bean public ZuulFilterInitializer zuulFilterInitializer( CounterFactory counterFactory, TracerFactory tracerFactory) { FilterLoader filterLoader = FilterLoader.getInstance(); FilterRegistry filterRegistry = FilterRegistry.instance(); return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory, filterLoader, filterRegistry); } } @Bean public ZuulController zuulController() { return new ZuulController(); } @Bean public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) { ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, zuulController()); mapping.setErrorController(this.errorController); return mapping; }ZuulProxyAutoConfiguration
zuulProxAutoConfiguration inherits ZuulServerAutoConfiguration and zuulServerAutoConfiguration
The main function is to add the configuration of RibbonCommandFactoryConfiguration, and initialize all methods to implement ribbon such as apache, okhttp.
ZuulFilterInitializer
The function of this class is mainly to register the initialized filter to zuul's FilterRegistry. FilterRegistry is a singleton used to initialize routing information and is used in ZuulRunner
RibbonCommandFactoryConfiguration
The main function is to configure forwarding, and the implementation mainly includes apache, okhttp
2. The forwarding implementation of zuul
First, the first step is to go to the lookupHandler method in ZuulHandlerMapping, and forward it to the zuulController
@Override protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { if (this.errorController != null && urlPath.equals(this.errorController.getErrorPath())) { return null; } String[] ignored = this.routeLocator.getIgnoredPaths().toArray(new String[0]); if (PatternMatchUtils.simpleMatch(ignored, urlPath)) { return null; } RequestContext ctx = RequestContext.getCurrentContext(); if (ctx.containsKey("forward.to")) { return null; } if (this.dirty) { synchronized (this) { if (this.dirty) { registerHandlers(); this.dirty = false; } } } return super.lookupHandler(urlPath, request); }The request rules are initialized as true when accessing the first time.
private void registerHandlers() { Collection<Route> routes = this.routeLocator.getRoutes(); if (routes.isEmpty()) { this.logger.warn("No routes found from RouteLocator"); } else { for (Route route : routes) { registerHandler(route.getFullPath(), this.zuul); } } }The second step of ZuulController inherits ServletWrappingController will transfer the request to ZuulServlet as follows
/** * @author Spencer Gibb */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(); } }}The third step is ZuulServlet's service method as follows: pre, route, and postRoute.
@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(); } }4. Finally, the SendResponseFilter executes the result and the filterOrder is 1000. Therefore, it is best to post filter not exceed 1000, otherwise the return result will be affected.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.