1.引入依赖,在启动类中添加@EnableZuulProxy,声明这是一个Zuul代理。
2.注册到Eureka Server,启动服务,访问这个端口,url中带上要请求的服务名。
//开启断路器(hystrix)
@EnableCircuitBreaker
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {
}
org.springframework.cloud.netflix.zuul.ZuulProxyMarkerConfiguration
//让ZuulProxyMarkerConfiguration 配置生效
@Configuration
public class ZuulProxyMarkerConfiguration {
//创建Marker 实例,让ZuulProxyMarkerConfiguration 配置生效
@Bean
public Marker zuulProxyMarkerBean() {
return new Marker();
}
class Marker {
}
}
org.springframework.cloud.netflix.zuul.ZuulProxyAutoConfiguration的父类是
org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration
org.springframework.boot.web.servlet.ServletRegistrationBean
//注册一个zuulServlet
@Bean
@ConditionalOnMissingBean(name = “zuulServlet”)
@ConditionalOnProperty(name = “zuul.use-filter”, havingValue = “false”, matchIfMissing = true)
public ServletRegistrationBean zuulServlet() {
ServletRegistrationBean
new ZuulServlet(), this.zuulProperties.getServletPattern());
// The whole point of exposing this servlet is to provide a route that doesn’t
// buffer requests.
servlet.addInitParameter(“buffer-requests”, “false”);
return servlet;
}
//注册一个zuulServletFilter
@Bean
@ConditionalOnMissingBean(name = “zuulServletFilter”)
@ConditionalOnProperty(name = “zuul.use-filter”, havingValue = “true”, matchIfMissing = false)
public FilterRegistrationBean zuulServletFilter() {
final FilterRegistrationBean
filterRegistration.setUrlPatterns(
Collections.singleton(this.zuulProperties.getServletPattern()));
filterRegistration.setFilter(new ZuulServletFilter());
filterRegistration.setOrder(Ordered.LOWESTPRECEDENCE);
// The whole point of exposing this servlet is to provide a route that doesn’t
// buffer requests.
filterRegistration.addInitParameter(“buffer-requests”, “false”);
return filterRegistration;
}
Zuulfilter 有四种 pre(前置),route(路由定位),post(执行后),error(出错),执行流程如上图,执行代码如下面
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
try {
this.init((HttpServletRequest)servletRequest, (HttpServletResponse)servletResponse);
RequestContext context = RequestContext.getCurrentContext();
context.setZuulEngineRan();
try {
//执行前置过滤器
this.preRoute();
} catch (ZuulException var12) {
//实现前置过滤器出错,则执行出错过滤器
this.error(var12);
//执行后置过滤
this.postRoute();
return;
}
try {
this.route();
} catch (ZuulException var13) {
this.error(var13);
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();
}
}
不管是哪一种过滤器,最后都会落到
com.netflix.zuul.FilterProcessor#runFilters
public Object runFilters(String sType) throws Throwable {
if(RequestContext.getCurrentContext().debugRouting()) {
Debug.addRoutingDebug(“Invoking {“ + sType + “} type filters”);
}
boolean bResult = false;
//据filter类型,获取排过序的filter
List
if(list != null) {
for(int i = 0; i < list.size(); ++i) {
//处理filter执行
ZuulFilter zuulFilter = (ZuulFilter)list.get(i);
Object result = this.processZuulFilter(zuulFilter);
if(result != null && result instanceof Boolean) {
bResult |= ((Boolean)result).booleanValue();
}
}
}
return Boolean.valueOf(bResult);
}
public Object processZuulFilter(ZuulFilter filter) throws ZuulException {
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();
}
//真正执行ZuulFilter内存方法
ZuulFilterResult result = filter.runFilter();
ExecutionStatus s = result.getStatus();
execTime = System.currentTimeMillis() - ltime;
switch(null.$SwitchMap$com$netflix$zuul$ExecutionStatus[s.ordinal()]) {
case 1:
t = result.getException();
ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);
break;
case 2:
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;
}
}
}
com.netflix.zuul.ZuulFilter#runFilter
public ZuulFilterResult runFilter() {
ZuulFilterResult zr = new ZuulFilterResult();
if (!isFilterDisabled()) {
if (shouldFilter()) {
Tracer t = TracerFactory.instance().startMicroTracer(“ZUUL::” + this.getClass().getSimpleName());
try {
//执行,run方法就是具体filter 实现的run方法
Object res = run();
zr = new ZuulFilterResult(res, ExecutionStatus.SUCCESS);
} catch (Throwable e) {
t.setName(“ZUUL::” + this.getClass().getSimpleName() + “ failed”);
zr = new ZuulFilterResult(ExecutionStatus.FAILED);
zr.setException(e);
} finally {
t.stopAndLog();
}
} else {
zr = new ZuulFilterResult(ExecutionStatus.SKIPPED);
}
}
return zr;
}