RibbonRoutingFilter是如何工作的

在讲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地址是如何完成映射的?
那就需要查看路由加载器的实现。这个会在后面说到

posted @ 2023-02-10 10:11  好奇成传奇  阅读(69)  评论(0编辑  收藏  举报