在gateway的filter中修改request uri的serviceId进行路由

在工作中遇到一个场景,具体如下:

实现多租户的数据隔离。

方案有逻辑隔离与物理隔离,但是在考虑SAAS平台数据体量与数据安全的情况下,最终选择使用物理隔离。

每个租户都有专属的后台处理服务,后台服务在打包时将该租户的数据库连接与serviceId的信息打包进工程,前端在发出请求时不需要关注租户的serviceId,在网关层根据每次请求中request header中的token进行serviceI的的替换实现“租户与租户之间的数据物理隔离,业务与业务隔离”。

在百度上翻了很久,均是只要修改serviceId就会404,最终还是在谷歌上找到了。

上代码

package com.xxx.gateway.filter;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.addOriginalRequestUrl;

import java.net.URI;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.support.DelegatingServiceInstance;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.crcc.gateway.cach.RedisService;
import com.crcc.gateway.sign.CheckSignHelpBean;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

/**
*    需求:例如前端请求地址为http://localhost:7002/demo/test/test1
*    根据某些规则改为 http://localhost:7002/demo111/test/test1
*/


@Component
@Slf4j
public class RequestCoverFilter implements GlobalFilter, Ordered {

    private static final Logger logger = LoggerFactory.getLogger(RequestCoverFilter.class);


    private final LoadBalancerClient loadBalancer;
    
    public RequestCoverFilter(LoadBalancerClient loadBalancer) {
        this.loadBalancer = loadBalancer;
    }
    
    @Override
    public int getOrder() {
        return 10100;
    }

    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        
        URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
        String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);
        //preserve the original url
        addOriginalRequestUrl(exchange, url);
 
        log.info("LoadBalancerClientFilter url before: " + url);
        System.out.println(url.getHost());
        //参数为想要替换的serviceId
        final ServiceInstance instance = loadBalancer.choose("demo111");
 
        if (instance == null) {
            throw new NotFoundException("Unable to find instance for " + url.getHost());
        }
 
        URI uri = exchange.getRequest().getURI();
        System.out.println(uri);
        
        URI u = new URI("http://localhost:7002/demo111/test/test1");
        // if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,
        // if the loadbalancer doesn't provide one.
        String overrideScheme = null;
        if (schemePrefix != null) {
            overrideScheme = u.getScheme();
        }
 
        URI requestUrl = loadBalancer.reconstructURI(new DelegatingServiceInstance(instance, overrideScheme), u);
 
        log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
        exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
        return chain.filter(exchange);
    }

}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值