Soul网关源码学习(12)- 对下游 Http 服务的请求和响应处理

前言

在上一篇文章《Soul网关源码学习(11)- Http代理的负载均衡:DividePlugin 和 SpringCloudPlugin》 中,我们分析了 Soul 对于负载均的实现,下一步就是发起对目标服务的请求了,那么本篇文章,我们就来分析 Http 代理转发的最后两站 WebClientPlugin 和 WebClientResponsePlugin。

WebClientPlugin

WebClientPlugin 是一个 Http 客户端,用来向目标服务器发起请求,其源码的逻辑也很简单,这里就和大家简单分析一下。WebClientPlugin 并没有继承模板类 AbstractSoulPlugin,而是自己实现了接口方法 execute:

    public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
        ...
        String urlPath = exchange.getAttribute(Constants.HTTP_URL);
       	...
        HttpMethod method = HttpMethod.valueOf(exchange.getRequest().getMethodValue());
        //构建请求
        WebClient.RequestBodySpec requestBodySpec = webClient.method(method).uri(urlPath);
        //发起请求
        return handleRequestBody(requestBodySpec, exchange, timeout, retryTimes, chain);
    }

从上面的代码可看到,真正发起请求的方法是 handleRequestBody ,我们再来看一下这个方法:

    private Mono<Void> handleRequestBody(...) {
        return requestBodySpec
        		...
                .contentType(buildMediaType(exchange))
                .body(BodyInserters.fromDataBuffers(exchange.getRequest().getBody()))
                .exchange()
                ...
                .flatMap(e -> doNext(e, exchange, chain));
    }
    
    private Mono<Void> doNext(final ClientResponse res, final ServerWebExchange exchange, final SoulPluginChain chain) {
		...
        exchange.getAttributes().put(Constants.CLIENT_RESPONSE_ATTR, res);
        return chain.execute(exchange);
    }

上面的代码也非常的简单,exchage() 发起请求,doNext() 处理返回,然后把响应存储到请求上下文 ServerWebExchange 中,然后进入下一个插件的处理。

WebClientResponsePlugin

WebClientResponsePlugin 顾名思义,就是处理上一步的请求响应的,和 WebClientPlugin 一样,其也是直接实现了 execute 方法:

    public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
        return chain.execute(exchange).then(Mono.defer(() -> {
            ServerHttpResponse response = exchange.getResponse();
            ClientResponse clientResponse = exchange.getAttribute(Constants.CLIENT_RESPONSE_ATTR);
            //下面省略一些错误处理,其会使用 WebFluxResultUtils.result(exchange, error) 把错误信息写回给客户端。
            ...
            //下面是正常响应
            //把结果写回给上游的客户端
            response.setStatusCode(clientResponse.statusCode());
            response.getCookies().putAll(clientResponse.cookies());
            response.getHeaders().putAll(clientResponse.headers().asHttpHeaders());
            return response.writeWith(clientResponse.body(BodyExtractors.toDataBuffers()));
        }));
    }

上面的代码可以注意一下 then 方法,它会在 chain.execute 之后被调用,也就是说在真正写入响应给上游客户端之前,插件链还有可能会执行剩余的其他一些非功能性插件,比如 MonitorPlugin(假如你打开的话),只有这些插件都执行完毕后才会进入 then 方法。

总结

到这里,我们总体回顾一下前面所学的内容。第6、7章,我们梳理了代理转发流程的概览,简单来说就是一个请求从进入 soul 网关到离开 soul 网关,中间会经过哪些关键的类。第 8 ~ 12章,我们以 Http 请求为示例,跟踪并详细分析了其经过的每一个插件的底层原理和实现,让我们对整个代理转发流程有了更加深层次的理解。在进入下一部分内容之前,我们最后再通过一幅流程图来总结一下 Http 代理转发的流程:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值