目录
4、选择ribbonCommandFactory,决定是由发个httpClient端发送请求,设置负载均衡器(可配置)
5、在RibbonLoadBalancingHttpClient过程中,通过Eureka client客户端ribbonServerList获取服务实例信息
6、Future支持并发,由HystrixCommand线程控制
版本说明
版本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实现类去处理。
内置过滤器列表
按order值从小到大,依次执行过滤器
过滤器 | order | 描述 | 类型 |
ServletDetectionFilter | -3 | 检测请求是用 DispatcherServlet还是 ZuulServlet | pre |
Servlet30WrapperFilter | -2 | 在Servlet 3.0 下,包装 requests | pre |
FormBodyWrapperFilter | -1 | 解析表单数据 | pre |
SendErrorFilter | 0 | 如果中途出现错误 | error |
DebugFilter | 1 | 设置请求过程是否开启debug | pre |
PreDecorationFilter | 5 | 根据uri决定调用哪一个route过滤器 | pre |
RibbonRoutingFilter | 10 | 如果写配置的时候用ServiceId则用这个route过滤器,该过滤器可以用Ribbon 做负载均衡,用hystrix做熔断 如:routes: xxx: path: /xxxx/** serviceId: xxx-server 或:routes: xxx-server: /xxxx/** | route |
SimpleHostRoutingFilter | 100 | 如果写配置的时候用url则用这个route过滤 如: routes: xxx.service: path: /xxx/** url: http://localhost:8080/ | route |
SendForwardFilter | 500 | 用RequestDispatcher请求转发 如: routes: config: path: /xxx/** url: forward:/xxx
| route |
SendResponseFilter | 1000 | 用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
2、进入RibbonRoutingFilter路由
3、初始化RibbonCommand
4、选择ribbonCommandFactory,决定是由发个httpClient端发送请求,设置负载均衡器(可配置)
默认使用HttpClientRibbonCommandFactory,在RibbonCommandFactoryConfiguration中初始化
RibbonCommand中 create构造一个RibbonLoadBalancingHttpClient,实现了IClient接口,负责真正发起请求的操作,有对应子类OkHttpLoadBalancingClient,RestClient,RibbonLoadBalancingHttpClient,都继承于AbstractLoadBalancerAwareClient。默认使用的是RibbonLoadBalancingHttpClient,在HttpClientRibbonConfiguration初始化。
RibbonCommand通过实现HystrixExecutable实现熔断,而负载均衡功能则是通过AbstractLoadBalancerAwareClient实现的
5、在RibbonLoadBalancingHttpClient过程中,通过Eureka client客户端ribbonServerList获取服务实例信息
在服务实例注册到eureka server时,ribbonclient接口已经实例化了。见eureka + ribbon源码解析
6、Future支持并发,由HystrixCommand线程控制
toObservable(),它是RxJava提供的类,表示一个可观察对象,它可以产生数据, 最后执行toBlocking().single()会阻塞直到产生第一个结果才返回。