spring cloud gateway根据版本过滤可用实例

根据版本过滤实例:

复制代码
import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.RequestDataContext;
import org.springframework.cloud.loadbalancer.core.DelegatingServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.http.HttpHeaders;
import org.springframework.util.MultiValueMap;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class VersionServiceInstanceListSupplier extends DelegatingServiceInstanceListSupplier {
    private static final String VERSION = "version";

    public VersionServiceInstanceListSupplier(ServiceInstanceListSupplier delegate) {
        super(delegate);
    }


    @Override
    public Flux<List<ServiceInstance>> get() {
        return delegate.get();
    }

    @Override
    public Flux<List<ServiceInstance>> get(Request request) {
        return delegate.get(request).map(instances -> filteredByVersion(instances, getVersion(request.getContext())));
    }


    private List<ServiceInstance> filteredByVersion(List<ServiceInstance> instances, String requestVersion) {
        if(StringUtils.isEmpty(requestVersion)){
            return instances.stream()
                    .filter(instance -> StringUtils.isBlank(instance.getMetadata().get(VERSION)))
                    .collect(Collectors.toList());
        }

        log.info("request version is {}", requestVersion);
        List<ServiceInstance> filteredInstances = instances.stream()
                .filter(instance -> requestVersion.equalsIgnoreCase(instance.getMetadata().get(VERSION)))
                .collect(Collectors.toList());

        if (CollUtil.isEmpty(filteredInstances)) {
            filteredInstances = instances.stream()
                    .filter(instance -> StringUtils.isBlank(instance.getMetadata().get(VERSION)))
                    .collect(Collectors.toList());
        }
        return filteredInstances;

    }

    private String getVersion(Object requestContext) {
        if (requestContext == null) {
            return null;
        }
        String version = null;
        if (requestContext instanceof RequestDataContext) {
            version = getVersionFromHeader((RequestDataContext) requestContext);
        }
        return version;
    }

    private String getVersionFromHeader(RequestDataContext context) {
        if (context.getClientRequest() != null) {
            String version = null;
            HttpHeaders headers = context.getClientRequest().getHeaders();
            if (headers != null) {
                version = headers.getFirst(VERSION);
            }
            if (StringUtils.isBlank(version)) {
                MultiValueMap<String, String> cookies = context.getClientRequest().getCookies();
                if (cookies != null) {
                    List<String> cookieVersions = cookies.get(VERSION);
                    if (CollUtil.isNotEmpty(cookieVersions)) {
                        version = cookieVersions.get(0);
                    }
                }
            }
            return version;
        }
        return null;
    }

}
复制代码

注册Bean:

复制代码
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class VersionServiceInstanceListSupplierConfiguration {

    @Bean
    ServiceInstanceListSupplier serviceInstanceListSupplier(ConfigurableApplicationContext context) {
        ServiceInstanceListSupplier delegate = ServiceInstanceListSupplier.builder()
                .withDiscoveryClient()
                .withCaching()
                .build(context);
        return new VersionServiceInstanceListSupplier(delegate);
    }

}
复制代码

启动类上加:

@LoadBalancerClients(defaultConfiguration = VersionServiceInstanceListSupplierConfiguration.class)

以nacos注册中心为例,网关加入以上代码后,业务服务配置如下:

spring:
  cloud:
    nacos:
      discovery:
        # 本地调试时修改以下信息
        metadata:
          ## 版本号,唯一  避免与其他服务冲突
          version: V123

请求接口时header带上版本号,即可路由到自己的服务

posted @   浪天涯&*  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示