Zuul源码解析

目录

版本说明

入口@EnableZuulProxy

ZuulProxyMarkerConfiguration类

spring.factories

ZuulServerAutoConfiguration类

ZuulProxyAutoConfiguration类

ZuulFilterInitializer类

FilterRegistry类-Filters存储

FilterLoader类-Filters封装

ZuulServlet类-路由控制器

FilterProcessor类-路由实现

内置过滤器列表

以RibbonRoutingFilter实现为例

1、按order依次执行各类Filter

2、进入RibbonRoutingFilter路由

3、初始化RibbonCommand

4、选择ribbonCommandFactory,决定是由发个httpClient端发送请求,设置负载均衡器(可配置)

5、在RibbonLoadBalancingHttpClient过程中,通过Eureka client客户端ribbonServerList获取服务实例信息

6、Future支持并发,由HystrixCommand线程控制

7、调用到实例接口


版本说明

版本2.2.4.RELASE

其中zuul-core:1.3.1

ps:spring-cloud-netflix-zuul已经进入维护模式,可启用spring-cloud-gateway代替。

入口@EnableZuulProxy

@EnableCircuitBreaker      //熔断启动
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({ZuulProxyMarkerConfiguration.class}) //Import 
public @interface EnableZuulProxy {
}

ZuulProxyMarkerConfiguration类

@Configuration
public class ZuulProxyMarkerConfiguration {
    public ZuulProxyMarkerConfiguration() {
    }

        //只是实例化一个Marker,结合spring.factories知道目标:ZuulServerAutoConfiguration,ZuulProxyAutoConfiguration
    @Bean
    public ZuulProxyMarkerConfiguration.Marker zuulProxyMarkerBean() {
        return new ZuulProxyMarkerConfiguration.Marker();
    }

    class Marker {
        Marker() {
        }
    }
}

spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration,\
org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration

ZuulServerAutoConfiguration类

@Configuration
@EnableConfigurationProperties({ZuulProperties.class})
@ConditionalOnClass({ZuulServlet.class, ZuulServletFilter.class})//核心实现,见下
@ConditionalOnBean({Marker.class}) //在此
public class ZuulServerAutoConfiguration {
    ...
    @Bean
    public HasFeatures zuulFeature() {
        return HasFeatures.namedFeature("Zuul (Simple)", ZuulServerAutoConfiguration.class);
    }

    @Bean
    @Primary
    public CompositeRouteLocator primaryRouteLocator(Collection<RouteLocator> routeLocators) {
        return new CompositeRouteLocator(routeLocators);
    }

    @Bean
    @ConditionalOnMissingBean({SimpleRouteLocator.class})
    public SimpleRouteLocator simpleRouteLocator() {
        return new SimpleRouteLocator(this.server.getServlet().getContextPath(), this.zuulProperties);
    }

    @Bean
    public ZuulController zuulController() {
        return new ZuulController();
    }

    @Bean
    public ZuulHandlerMapping zuulHandlerMapping(RouteLocator routes) {
        ZuulHandlerMapping mapping = new ZuulHandlerMapping(routes, this.zuulController());
        mapping.setErrorController(this.errorController);
        mapping.setCorsConfigurations(this.getCorsConfigurations());
        return mapping;
    }

    protected final Map<String, CorsConfiguration> getCorsConfigurations() {
        if (this.corsConfigurations == null) {
            ZuulServerAutoConfiguration.ZuulCorsRegistry registry = new ZuulServerAutoConfiguration.ZuulCorsRegistry();
            this.configurers.forEach((configurer) -> {
                configurer.addCorsMappings(registry);
            });
            this.corsConfigurations = registry.getCorsConfigurations();
        }

        return this.corsConfigurations;
    }

        //加入spring Listener用于刷新配置
    @Bean
    public ApplicationListener<ApplicationEvent> zuulRefreshRoutesListener() {
        return new ZuulServerAutoConfiguration.ZuulRefreshListener();
    }

    //初始化zuulServlet
    @Bean
    @ConditionalOnMissingBean(
        name = {"zuulServlet"}
    )
    @ConditionalOnProperty(
        name = {"zuul.use-filter"},
        havingValue = "false",
        matchIfMissing = true
    )
    public ServletRegistrationBean zuulServlet() {
        ServletRegistrationBean<ZuulServlet> servlet = new ServletRegistrationBean(new ZuulServlet(), new String[]{this.zuulProperties.getServletPattern()});
        servlet.addInitParameter("buffer-requests", "false");
        return servlet;
    }

    //初始化zuulServletFilter
    @Bean
    @ConditionalOnMissingBean(
        name = {"zuulServletFilter"}
    )
    @ConditionalOnProperty(
        name = {"zuul.use-filter"},
        havingValue = "true",
        matchIfMissing = false
    )
    public FilterRegistrationBean zuulServletFilter() {
        FilterRegistrationBean<ZuulServletFilter> filterRegistration = new FilterRegistrationBean();
        filterRegistration.setUrlPatterns(Collections.singleton(this.zuulProperties.getServletPattern()));
        filterRegistration.setFilter(new ZuulServletFilter());
        filterRegistration.setOrder(2147483647);
        filterRegistration.addInitParameter("buffer-requests", "false");
        return filterRegistration;
    }

        //各类过滤器-per
    @Bean
    public ServletDetectionFilter servletDetectionFilter() {
        return new ServletDetectionFilter();
    }

    @Bean
    public FormBodyWrapperFilter formBodyWrapperFilter() {
        return new FormBodyWrapperFilter();
    }

    @Bean
    public DebugFilter debugFilter() {
        return new DebugFilter();
    }

    @Bean
    public Servlet30WrapperFilter servlet30WrapperFilter() {
        return new Servlet30WrapperFilter();
    }
    //各类过滤器-post
    @Bean
    public SendResponseFilter sendResponseFilter(ZuulProperties properties) {
        return new SendResponseFilter(this.zuulProperties);
    }

    @Bean
    public SendErrorFilter sendErrorFilter() {
        return new SendErrorFilter();
    }

    @Bean
    public SendForwardFilter sendForwardFilter() {
        return new SendForwardFilter();
    }

    @Bean
    @ConditionalOnProperty({"zuul.ribbon.eager-load.enabled"})
    public ZuulRouteApplicationContextInitializer zuulRoutesApplicationContextInitiazer(SpringClientFactory springClientFactory) {
        return new ZuulRouteApplicationContextInitializer(springClientFactory, this.zuulProperties);
    }

    private static class ZuulCorsRegistry extends CorsRegistry {
        private ZuulCorsRegistry() {
        }

        protected Map<String, CorsConfiguration> getCorsConfigurations() {
            return super.getCorsConfigurations();
        }
    }

        //Listener实现
    private static class ZuulRefreshListener implements ApplicationListener<ApplicationEvent> {
        @Autowired
        private ZuulHandlerMapping zuulHandlerMapping;
        private HeartbeatMonitor heartbeatMonitor;

        private ZuulRefreshListener() {
            this.heartbeatMonitor = new HeartbeatMonitor();
        }

        public void onApplicationEvent(ApplicationEvent event) {
            if (!(event instanceof ContextRefreshedEvent) && !(event instanceof RefreshScopeRefreshedEvent) && !(event instanceof RoutesRefreshedEvent) && !(event instanceof InstanceRegisteredEvent)) {
                if (event instanceof ParentHeartbeatEvent) {
                    ParentHeartbeatEvent e = (ParentHeartbeatEvent)event;
                    this.resetIfNeeded(e.getValue());
                } else if (event instanceof HeartbeatEvent) {
                    HeartbeatEvent e = (HeartbeatEvent)event;
                    this.resetIfNeeded(e.getValue());
                }
            } else {
                this.reset();
            }

        }

        private void resetIfNeeded(Object value) {
            if (this.heartbeatMonitor.update(value)) {
                this.reset();
            }

        }

        private void reset() {
            this.zuulHandlerMapping.setDirty(true);
        }
    }

...
    
    //初始化ZuulFilterInitializer类,将所有的filter向FilterRegistry注册
    @Configuration
    protected static class ZuulFilterConfiguration {
        @Autowired
        private Map<String, ZuulFilter> filters;

        protected ZuulFilterConfiguration() {
        }

        @Bean
        public ZuulFilterInitializer zuulFilterInitializer(CounterFactory counterFactory, TracerFactory tracerFactory) {
            FilterLoader filterLoader = FilterLoader.getInstance();
            FilterRegistry filterRegistry = FilterRegistry.instance();
            //ZuulFilterInitializer实例化,初始化FilterLoader FilterRegistry核心功能
            return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory, filterLoader, filterRegistry);
        }
    }
}

ZuulProxyAutoConfiguration类

对ZuulServerAutoConfiguration的扩展,主要是扩展router类型

@Configuration
@Import({RestClientRibbonConfiguration.class, OkHttpRibbonConfiguration.class, HttpClientRibbonConfiguration.class, HttpClientConfiguration.class})
@ConditionalOnBean({Marker.class})
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {
    @Autowired(
        required = false
    )
    private List<RibbonRequestCustomizer> requestCustomizers = Collections.emptyList();
    @Autowired(
        required = false
    )
    private Registration registration;
    @Autowired
    private DiscoveryClient discovery;
    @Autowired
    private ServiceRouteMapper serviceRouteMapper;

    public ZuulProxyAutoConfiguration() {
    }

    public HasFeatures zuulFeature() {
        return HasFeatures.namedFeature("Zuul (Discovery)", ZuulProxyAutoConfiguration.class);
    }

    //各类router实例化
    @Bean
    @ConditionalOnMissingBean({DiscoveryClientRouteLocator.class})
    public DiscoveryClientRouteLocator discoveryRouteLocator() {
        return new DiscoveryClientRouteLocator(this.server.getServlet().getContextPath(), this.discovery, this.zuulProperties, this.serviceRouteMapper, this.registration);
    }

    @Bean
    @ConditionalOnMissingBean({PreDecorationFilter.class})
    public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator, ProxyRequestHelper proxyRequestHelper) {
        return new PreDecorationFilter(routeLocator, this.server.getServlet().getContextPath(), this.zuulProperties, proxyRequestHelper);
    }

    @Bean
    @ConditionalOnMissingBean({RibbonRoutingFilter.class})
    public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper, RibbonCommandFactory<?> ribbonCommandFactory) {
        RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory, this.requestCustomizers);
        return filter;
    }

    @Bean
    @ConditionalOnMissingBean({SimpleHostRoutingFilter.class, CloseableHttpClient.class})
    public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper, ZuulProperties zuulProperties, ApacheHttpClientConnectionManagerFactory connectionManagerFactory, ApacheHttpClientFactory httpClientFactory) {
        return new SimpleHostRoutingFilter(helper, zuulProperties, connectionManagerFactory, httpClientFactory);
    }

    @Bean
    @ConditionalOnMissingBean({SimpleHostRoutingFilter.class})
    public SimpleHostRoutingFilter simpleHostRoutingFilter2(ProxyRequestHelper helper, ZuulProperties zuulProperties, CloseableHttpClient httpClient) {
        return new SimpleHostRoutingFilter(helper, zuulProperties, httpClient);
    }

    @Bean
    @ConditionalOnMissingBean({ServiceRouteMapper.class})
    public ServiceRouteMapper serviceRouteMapper() {
        return new SimpleServiceRouteMapper();
    }

}

ZuulFilterInitializer类

public class ZuulFilterInitializer {
    private static final Log log = LogFactory.getLog(ZuulFilterInitializer.class);
    private final Map<String, ZuulFilter> filters;
    private final CounterFactory counterFactory;
    private final TracerFactory tracerFactory;
    private final FilterLoader filterLoader;
    private final FilterRegistry filterRegistry;

    public ZuulFilterInitializer(Map<String, ZuulFilter> filters, CounterFactory counterFactory, TracerFactory tracerFactory, FilterLoader filterLoader, FilterRegistry filterRegistry) {
        this.filters = filters;
        this.counterFactory = counterFactory;
        this.tracerFactory = tracerFactory;
        this.filterLoader = filterLoader;
        this.filterRegistry = filterRegistry;
    }

    @PostConstruct
    public void contextInitialized() {
        log.info("Starting filter initializer");
        TracerFactory.initialize(this.tracerFactory);
        CounterFactory.initialize(this.counterFactory);
        Iterator var1 = this.filters.entrySet().iterator();
        //filterRegistry存储filters
        while(var1.hasNext()) {
            Entry<String, ZuulFilter> entry = (Entry)var1.next();
            this.filterRegistry.put((String)entry.getKey(), (ZuulFilter)entry.getValue());
        }

    }

    @PreDestroy
    public void contextDestroyed() {
        log.info("Stopping filter initializer");
        Iterator var1 = this.filters.entrySet().iterator();

        while(var1.hasNext()) {
            Entry<String, ZuulFilter> entry = (Entry)var1.next();
            this.filterRegistry.remove((String)entry.getKey());
        }

        this.clearLoaderCache();
        TracerFactory.initialize((TracerFactory)null);
        CounterFactory.initialize((CounterFactory)null);
    }

    private void clearLoaderCache() {
        Field field = ReflectionUtils.findField(FilterLoader.class, "hashFiltersByType");
        ReflectionUtils.makeAccessible(field);
        Map cache = (Map)ReflectionUtils.getField(field, this.filterLoader);
        cache.clear();
    }
}

FilterRegistry类-Filters存储

单例,ConcurrentHashMap存储filters

public class FilterRegistry {
    private static final FilterRegistry INSTANCE = new FilterRegistry();
    private final ConcurrentHashMap<String, ZuulFilter> filters = new ConcurrentHashMap();

    public static final FilterRegistry instance() {
        return INSTANCE;
    }

    private FilterRegistry() {
    }
}

FilterLoader类-Filters封装

用来操作FilterRegistry,但是用ZuulFilter封装,所以有实现自定义filter时,可以继承ZuulFilter来实现自定义filter功能

public class FilterLoader {
    static final FilterLoader INSTANCE = new FilterLoader();
    private static final Logger LOG = LoggerFactory.getLogger(FilterLoader.class);
    private final ConcurrentHashMap<String, Long> filterClassLastModified = new ConcurrentHashMap();
    private final ConcurrentHashMap<String, String> filterClassCode = new ConcurrentHashMap();
    private final ConcurrentHashMap<String, String> filterCheck = new ConcurrentHashMap();
    private final ConcurrentHashMap<String, List<ZuulFilter>> hashFiltersByType = new ConcurrentHashMap();
    private FilterRegistry filterRegistry = FilterRegistry.instance();
    static DynamicCodeCompiler COMPILER;
    static FilterFactory FILTER_FACTORY = new DefaultFilterFactory();

   ...
   //Filter获取 
    public ZuulFilter getFilter(String sCode, String sName) throws Exception {
        if (this.filterCheck.get(sName) == null) {
            this.filterCheck.putIfAbsent(sName, sName);
            if (!sCode.equals(this.filterClassCode.get(sName))) {
                LOG.info("reloading code " + sName);
                this.filterRegistry.remove(sName);
            }
        }

        ZuulFilter filter = this.filterRegistry.get(sName);
        if (filter == null) {
            Class clazz = COMPILER.compile(sCode, sName);
            if (!Modifier.isAbstract(clazz.getModifiers())) {
                filter = FILTER_FACTORY.newInstance(clazz);
            }
        }

        return filter;
    }

    //filter更新
    public boolean putFilter(File file) throws Exception {
        String sName = file.getAbsolutePath() + file.getName();
        if (this.filterClassLastModified.get(sName) != null && file.lastModified() != (Long)this.filterClassLastModified.get(sName)) {
            LOG.debug("reloading filter " + sName);
            this.filterRegistry.remove(sName);
        }

        ZuulFilter filter = this.filterRegistry.get(sName);
        if (filter == null) {
            Class clazz = COMPILER.compile(file);
            if (!Modifier.isAbstract(clazz.getModifiers())) {
                filter = FILTER_FACTORY.newInstance(clazz);
                List<ZuulFilter> list = (List)this.hashFiltersByType.get(filter.filterType());
                if (list != null) {
                    this.hashFiltersByType.remove(filter.filterType());
                }

                this.filterRegistry.put(file.getAbsolutePath() + file.getName(), filter);
                this.filterClassLastModified.put(sName, file.lastModified());
                return true;
            }
        }

        return false;
    }

    public List<ZuulFilter> getFiltersByType(String filterType) {
        List<ZuulFilter> list = (List)this.hashFiltersByType.get(filterType);
        if (list != null) {
            return list;
        } else {
            List<ZuulFilter> list = new ArrayList();
            Collection<ZuulFilter> filters = this.filterRegistry.getAllFilters();
            Iterator iterator = filters.iterator();

            while(iterator.hasNext()) {
                ZuulFilter filter = (ZuulFilter)iterator.next();
                if (filter.filterType().equals(filterType)) {
                    list.add(filter);
                }
            }

            Collections.sort(list);
            this.hashFiltersByType.putIfAbsent(filterType, list);
            return list;
        }
    }

ZuulServlet类-路由控制器

zuulServlet 继承HttpServlet,实现对所有请求的控制。

public class ZuulServlet extends HttpServlet {
    private static final long serialVersionUID = -3374242278843351500L;
    private ZuulRunner zuulRunner;

    public ZuulServlet() {
    }

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        String bufferReqsStr = config.getInitParameter("buffer-requests");
        boolean bufferReqs = bufferReqsStr != null && bufferReqsStr.equals("true");
        this.zuulRunner = new ZuulRunner(bufferReqs);
    }

    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        try {
            this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse);
            RequestContext context = RequestContext.getCurrentContext();
            context.setZuulEngineRan();
            //三类route路由
            try {
                this.preRoute();
            } catch (ZuulException var13) {
                this.error(var13);
                this.postRoute();
                return;
            }

            try {
                this.route();
            } catch (ZuulException var12) {
                this.error(var12);
                this.postRoute();
                return;
            }

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

    //由FilterProcessor提供三类路由实现
    void postRoute() throws ZuulException {
        this.zuulRunner.postRoute();
    }

    void route() throws ZuulException {
        this.zuulRunner.route();
    }

    void preRoute() throws ZuulException {
        this.zuulRunner.preRoute();
    }

    void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
        this.zuulRunner.init(servletRequest, servletResponse);
    }

    void error(ZuulException e) {
        RequestContext.getCurrentContext().setThrowable(e);
        this.zuulRunner.error();
    }
}

FilterProcessor类-路由实现

pre\route\post三类路由实现

public class FilterProcessor {
    static FilterProcessor INSTANCE = new FilterProcessor();
    protected static final Logger logger = LoggerFactory.getLogger(FilterProcessor.class);
    private FilterUsageNotifier usageNotifier = new FilterProcessor.BasicFilterUsageNotifier();

    public FilterProcessor() {
    }

    public static FilterProcessor getInstance() {
        return INSTANCE;
    }

    public static void setProcessor(FilterProcessor processor) {
        INSTANCE = processor;
    }

    public void postRoute() throws ZuulException {
        try {
            this.runFilters("post");
        } catch (ZuulException var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new ZuulException(var3, 500, "UNCAUGHT_EXCEPTION_IN_POST_FILTER_" + var3.getClass().getName());
        }
    }

    public void error() {
        try {
            this.runFilters("error");
        } catch (Throwable var2) {
            logger.error(var2.getMessage(), var2);
        }

    }

    public void route() throws ZuulException {
        try {
            this.runFilters("route");
        } catch (ZuulException var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new ZuulException(var3, 500, "UNCAUGHT_EXCEPTION_IN_ROUTE_FILTER_" + var3.getClass().getName());
        }
    }

    public void preRoute() throws ZuulException {
        try {
            this.runFilters("pre");
        } catch (ZuulException var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new ZuulException(var3, 500, "UNCAUGHT_EXCEPTION_IN_PRE_FILTER_" + var3.getClass().getName());
        }
    }

    public Object runFilters(String sType) throws Throwable {
        if (RequestContext.getCurrentContext().debugRouting()) {
            Debug.addRoutingDebug("Invoking {" + sType + "} type filters");
        }

        boolean bResult = false;
        //FilterLoader获取filters
        List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);
        if (list != null) {
            for(int i = 0; i < list.size(); ++i) {
                ZuulFilter zuulFilter = (ZuulFilter)list.get(i);
                Object result = this.processZuulFilter(zuulFilter);
                if (result != null && result instanceof Boolean) {
                    bResult |= (Boolean)result;
                }
            }
        }

        return bResult;
    }

    public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
        //RequestContext由所有filter共享
        RequestContext ctx = RequestContext.getCurrentContext();
        boolean bDebug = ctx.debugRouting();
        String metricPrefix = "zuul.filter-";
        long execTime = 0L;
        String filterName = "";

        try {
            long ltime = System.currentTimeMillis();
            filterName = filter.getClass().getSimpleName();
            RequestContext copy = null;
            Object o = null;
            Throwable t = null;
            if (bDebug) {
                Debug.addRoutingDebug("Filter " + filter.filterType() + " " + filter.filterOrder() + " " + filterName);
                copy = ctx.copy();
            }
                        //由ZuulFilterResult来run,见下实现
            ZuulFilterResult result = filter.runFilter();
            ExecutionStatus s = result.getStatus();
            execTime = System.currentTimeMillis() - ltime;
            switch(s) {
            case FAILED:
                t = result.getException();
                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
                break;
            case SUCCESS:
                o = result.getResult();
                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.SUCCESS.name(), execTime);
                if (bDebug) {
                    Debug.addRoutingDebug("Filter {" + filterName + " TYPE:" + filter.filterType() + " ORDER:" + filter.filterOrder() + "} Execution time = " + execTime + "ms");
                    Debug.compareContextState(filterName, copy);
                }
            }

            if (t != null) {
                throw t;
            } else {
                this.usageNotifier.notify(filter, s);
                return o;
            }
        } catch (Throwable var15) {
            if (bDebug) {
                Debug.addRoutingDebug("Running Filter failed " + filterName + " type:" + filter.filterType() + " order:" + filter.filterOrder() + " " + var15.getMessage());
            }

            this.usageNotifier.notify(filter, ExecutionStatus.FAILED);
            if (var15 instanceof ZuulException) {
                throw (ZuulException)var15;
            } else {
                ZuulException ex = new ZuulException(var15, "Filter threw Exception", 500, filter.filterType() + ":" + filterName);
                ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
                throw ex;
            }
        }
    }
 }

ZuulFilterResult中实现由各类filter实现类去处理。

image.png

内置过滤器列表

按order值从小到大,依次执行过滤器

过滤器order描述类型
ServletDetectionFilter-3检测请求是用 DispatcherServlet还是 ZuulServletpre
Servlet30WrapperFilter-2在Servlet 3.0 下,包装 requestspre
FormBodyWrapperFilter-1解析表单数据pre
SendErrorFilter0如果中途出现错误error
DebugFilter1设置请求过程是否开启debugpre
PreDecorationFilter5根据uri决定调用哪一个route过滤器pre
RibbonRoutingFilter10

如果写配置的时候用ServiceId则用这个route过滤器,该过滤器可以用Ribbon 做负载均衡,用hystrix做熔断

如:routes:

         xxx:

           path: /xxxx/**

           serviceId: xxx-server

或:routes:

          xxx-server: /xxxx/**

route
SimpleHostRoutingFilter100

如果写配置的时候用url则用这个route过滤

如:

 routes:       

  xxx.service:

        path: /xxx/**

        url: http://localhost:8080/

route
SendForwardFilter500

用RequestDispatcher请求转发

如:

    routes:

        config:

            path: /xxx/**

            url: forward:/xxx

 

route
SendResponseFilter1000用RequestDispatcher请求转发post

以RibbonRoutingFilter实现为例

RibbonRoutingFilter集成了Ribbon和hystrix组件,提供负载均衡和熔断等功能。

public class RibbonRoutingFilter extends ZuulFilter {
    private static final Log log = LogFactory.getLog(RibbonRoutingFilter.class);
    protected ProxyRequestHelper helper;
    protected RibbonCommandFactory<?> ribbonCommandFactory;
    protected List<RibbonRequestCustomizer> requestCustomizers;
    private boolean useServlet31;

    public RibbonRoutingFilter(ProxyRequestHelper helper, RibbonCommandFactory<?> ribbonCommandFactory, List<RibbonRequestCustomizer> requestCustomizers) {
        this.useServlet31 = true;
        this.helper = helper;
        this.ribbonCommandFactory = ribbonCommandFactory;
        this.requestCustomizers = requestCustomizers;

        try {
            HttpServletRequest.class.getMethod("getContentLengthLong");
        } catch (NoSuchMethodException var5) {
            this.useServlet31 = false;
        }

    }
...
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        return ctx.getRouteHost() == null && ctx.get("serviceId") != null && ctx.sendZuulResponse();
    }

    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        this.helper.addIgnoredHeaders(new String[0]);

        try {
                //从context中获取serviceId等信息
            RibbonCommandContext commandContext = this.buildCommandContext(context);
            //执行
            ClientHttpResponse response = this.forward(commandContext);
            this.setResponse(response);
            return response;
        } catch (ZuulException var4) {
            throw new ZuulRuntimeException(var4);
        } catch (Exception var5) {
            throw new ZuulRuntimeException(var5);
        }
    }

    protected RibbonCommandContext buildCommandContext(RequestContext context) {
        HttpServletRequest request = context.getRequest();
        MultiValueMap<String, String> headers = this.helper.buildZuulRequestHeaders(request);
        MultiValueMap<String, String> params = this.helper.buildZuulRequestQueryParams(request);
        String verb = this.getVerb(request);
        InputStream requestEntity = this.getRequestBody(request);
        if (request.getContentLength() < 0 && !verb.equalsIgnoreCase("GET")) {
            context.setChunkedRequestBody();
        }

        String serviceId = (String)context.get("serviceId");
        Boolean retryable = (Boolean)context.get("retryable");
        Object loadBalancerKey = context.get("loadBalancerKey");
        String uri = this.helper.buildZuulRequestURI(request);
        uri = uri.replace("//", "/");
        long contentLength = this.useServlet31 ? request.getContentLengthLong() : (long)request.getContentLength();
        return new RibbonCommandContext(serviceId, verb, uri, retryable, headers, params, requestEntity, this.requestCustomizers, contentLength, loadBalancerKey);
    }

    protected ClientHttpResponse forward(RibbonCommandContext context) throws Exception {
        Map<String, Object> info = this.helper.debug(context.getMethod(), context.getUri(), context.getHeaders(), context.getParams(), context.getRequestEntity());
        RibbonCommand command = this.ribbonCommandFactory.create(context);

        try {
            //由于robbon中robbin.eureka.enabled默认为true,会从eureka中根据serviceId获取服务实例等信息
            ClientHttpResponse response = (ClientHttpResponse)command.execute();
            this.helper.appendDebug(info, response.getRawStatusCode(), response.getHeaders());
            return response;
        } catch (HystrixRuntimeException var5) {
            return this.handleException(info, var5);
        }
    }

    protected ClientHttpResponse handleException(Map<String, Object> info, HystrixRuntimeException ex) throws ZuulException {
        int statusCode = HttpStatus.INTERNAL_SERVER_ERROR.value();
        Throwable cause = ex;
        String message = ex.getFailureType().toString();
        ClientException clientException = this.findClientException(ex);
        if (clientException == null) {
            clientException = this.findClientException(ex.getFallbackException());
        }

        if (clientException != null) {
            if (clientException.getErrorType() == ErrorType.SERVER_THROTTLED) {
                statusCode = HttpStatus.SERVICE_UNAVAILABLE.value();
            }

            cause = clientException;
            message = clientException.getErrorType().toString();
        }

        info.put("status", String.valueOf(statusCode));
        throw new ZuulException((Throwable)cause, "Forwarding error", statusCode, message);
    }

...
}

1、按order依次执行各类Filter

image.png

2、进入RibbonRoutingFilter路由

image.png

3、初始化RibbonCommand

image.png

image.png

 

4、选择ribbonCommandFactory,决定是由发个httpClient端发送请求,设置负载均衡器(可配置)

默认使用HttpClientRibbonCommandFactory,在RibbonCommandFactoryConfiguration中初始化

image.png

RibbonCommand中 create构造一个RibbonLoadBalancingHttpClient,实现了IClient接口,负责真正发起请求的操作,有对应子类OkHttpLoadBalancingClient,RestClient,RibbonLoadBalancingHttpClient,都继承于AbstractLoadBalancerAwareClient。默认使用的是RibbonLoadBalancingHttpClient,在HttpClientRibbonConfiguration初始化。

RibbonCommand通过实现HystrixExecutable实现熔断,而负载均衡功能则是通过AbstractLoadBalancerAwareClient实现的

image.png

 

5、在RibbonLoadBalancingHttpClient过程中,通过Eureka client客户端ribbonServerList获取服务实例信息

在服务实例注册到eureka server时,ribbonclient接口已经实例化了。见eureka + ribbon源码解析

image.png

6、Future支持并发,由HystrixCommand线程控制

toObservable(),它是RxJava提供的类,表示一个可观察对象,它可以产生数据, 最后执行toBlocking().single()会阻塞直到产生第一个结果才返回。

image.png

7、调用到实例接口

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值