Feign如何区分业务调用

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

前言

需求背景。我们有两个网关系统一个是内网使用的一个是外网使用。如果是内部系统使用调用的内网网关。但是作为网关管理平台需要和两个网关系统都进行交互。如果对外接口则和外部网关交互。
网关本身提供的restful接口便于使用我们使用OpenFeign进行调用。但是带来一个问题。调用的时候如何指定内网还是外网网关

方案一

写一个FeignClient地址是一台nginx。然后再加个Feign拦截器调用的时候判断该调内网网关的时候在path前加上/inner。
nginx做代理配置如果path前缀是/inner则将请求转到内网网关。
上代码

client

package com.org.demo.clients;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

/**
 * 网关app客户端
 *
 * @author dzh
 * @date 2022/12/2 16:37
 */
@FeignClient(url = "https://server.local", 
        name = "gatewayClient", 
        configuration = GatewayConfig.class,
        fallback = GatewayClientFallback.class)
public interface GatewayClient {
    
    // 用来标识调用哪个网关
    ThreadLocal<Boolean> out = new ThreadLocal<>();
    @GetMapping(value = "something/msg")
    String msg();
}

config

package com.org.demo.clients;

import feign.RequestInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;

/**
 * @author dzh
 * @date 2022/12/2 17:24
 */
@Slf4j
public class GatewayConfig {

    @Value("${gateway.auth}")
    private String auth;

    @Bean
    @Order(1000)
    public RequestInterceptor getRequestInterceptor() {
        return template -> {

            // 鉴权消息头
            template.header("Authorization", auth);
            String path = template.path();

            if (GatewayClient.out.get()) {
                GatewayClient.out.remove();
                template.uri("outside" + path);
            } else {
                GatewayClient.out.remove();
                template.uri("inside" + path);
            }
        };
    }
}

方案二

大家觉着第一个方案不太好还要依赖nginx但是碍于项目工期先那样上线了。所有有了后续的方案
写两个FeignClient。有个问题因为两个网关系统出了ip不同其他都是一样的写两个就会有冗余代码。那其实有个偷懒的办法。基于方案一得代码再写两个实现分别是内网和外网的客户端。
此方案不用依赖nginxurl直接配置对应网关系统的地址。
这个方案需要在调用的Service中注入两个client需要哪个调用哪个。
因为是基于之前的方案升级的不可能一下子全改了所以在使用@Resource GatewayClient gatewayClient的地方都需要制定beanId否则因为容器中有桑格GatewayClient实例启动会失败。
这样就实现了过度当都改成方案二的调用方式就可以删除多余的拦截器了

内网

package com.org.demo.clients;

import org.springframework.cloud.openfeign.FeignClient;

@FeignClient(url = "https://server.local",
        name = "gatewayInsideClient",
        qualifiers = "gatewayInsideClient",
        fallback = GatewayClientFallback.class)
public interface GatewayInsideClient extends GatewayClient {
}

外网

package com.org.demo.clients;

import org.springframework.cloud.openfeign.FeignClient;

@FeignClient(url = "https://server.local",
        name = "gatewayOutsideClient",
        qualifiers = "gatewayOutsideClient",
        fallback = GatewayClientFallback.class)
public interface GatewayOutsideClient extends GatewayClient {
}

方案三

以上两个方案已经实践过是么有问题的。方案三目前只停留在理论阶段。方案二因为指定的是ip地址而且只能指定一个所以存在风险如果服务器宕机那就糟了。
SpringCloud有服务发现的机制也可以将网关的服务注册到Nacos然后client做对应的修改问题就解决了。

后续

我比较了一下三中方案没有谁是最好的只是看合适不合适
方案一如果我们有十个八个网关使用该方案还是比较合适的
方案二如果少量的网关服务这个方案还是比较好的
方案三解决方案二单点的问题

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6