浅谈SpringCloud之zuul源码解析

网友投稿 319 2023-02-16


浅谈SpringCloud之zuul源码解析

zuul各版本实现存在一些微小的变化,总的实现思想未改变,以spring-cloud-netflix-core-1.3.6.RELEASE为例

一、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

初始化路由规则

初始化一些重要的filter如 PreDecorationFilter,RibbonRoutingFilter

初始化ZuulFilterInitializer

初始化ZuulHandlerMapping

代码如下

//路由规则

@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 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继承ZuulServerAutoConfiguration功能上和zuulServerAutoConfiguration

主要功能是增加了RibbonCommandFactoryConfiguration的配置,初始化所有的实现ribbon的方式如apache,okhttp。

ZuulFilterInitializer

该类的作用主要是把初始化的过滤器注册到zuul的FilterRegistry,FilterRegistry是一个单例用于初始化路由信息,在ZuulRunner中使用

RibbonCommandFactoryConfiguration

主要作用是配置转发的实现,实现主要有apache,okhttp

二、zuul的转发实现

首先第一步转到ZuulHandlerMapping中的lookupHandler方法,把转发转到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);

}

第一次访问时dirty为true会初始化一次请求规则如下

private void regiGJPgRhttJsterHandlers() {

Collection 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);

}

}

}

第二步ZuulController继承ServletWrappingController的会把请求转到ZuulServlet中如下

/**

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

}

}

}

第三步ZuulServlet的service方法如下主要执行pre,route,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();

}

}

四、最后由SendResponseFilter执行返回结果,filterOrder为1000所以最好post的filter不要超过1000否则影响返回结果


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Vue实现带进度条的文件拖动上传功能
下一篇:微信授权接口开发(微信开放平台授权书)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~