在讲RibbonRoutingFilter是如何工作之前,也有一些比较重要的类需要去提前了解。
重要的类
RequestContext
请求上下文,用于存储线程中对应的请求以及响应
public class RequestContext extends ConcurrentHashMap<String, Object> {
protected static final ThreadLocal<? extends RequestContext> threadLocal = new ThreadLocal<RequestContext>() {
public static RequestContext getCurrentContext() {
if (testContext != null) return testContext;
RequestContext context = threadLocal.get();
return context;
}
public void setRequest(HttpServletRequest request) {
put("request", request);
}
public HttpServletRequest getRequest() {
return (HttpServletRequest) get("request");
}
public void setResponse(HttpServletResponse response) {
set("response", response);
}
public HttpServletResponse getResponse() {
return (HttpServletResponse) get("response");
}
public void setRouteHost(URL routeHost) {
set("routeHost", routeHost);
}
public URL getRouteHost() {
return (URL) get("routeHost");
}
}
RibbonCommandContext
ribbon命令上下文,其实就是要用于封装ribbon命令的一个容器。
public class RibbonCommandContext {
服务的id
private final String serviceId;
请求的方法
private final String method;
路径
private final String uri;
是否运行重试
private final Boolean retryable;
请求头
private final MultiValueMap<String, String> headers;
路径上的入参
private final MultiValueMap<String, String> params;
}
RibbonRoutingFilter的工作原理
public class RibbonRoutingFilter extends ZuulFilter {
@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
this.helper.addIgnoredHeaders();
try {
1.将请求上下文转化成ribbon的命令上下文
RibbonCommandContext commandContext = buildCommandContext(context);
2.进行转发,获取响应---这一步的实现才是我们需要关注的。
ClientHttpResponse response = forward(commandContext);
setResponse(response);
3.返回响应
return response;
}
catch (ZuulException ex) {
throw new ZuulRuntimeException(ex);
}
catch (Exception ex) {
throw new ZuulRuntimeException(ex);
}
}
获取响应的方法如下,其实我最关注的是ribbon如何知道服务id所映射的真实地址。
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 {
ClientHttpResponse response = command.execute();
this.helper.appendDebug(info, response.getRawStatusCode(),
response.getHeaders());
return response;
}
catch (HystrixRuntimeException ex) {
return handleException(info, ex);
}
}
}
到最后其实生成请求,如何进行访问?
那么路由规则与真实host地址是如何完成映射的?
那就需要查看路由加载器的实现。这个会在后面说到