![JAR search and dependency download from the Maven repository](/logo.png)
com.taotao.cloud.openfeign.loadbalancer.VersionLoadBalancer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of taotao-cloud-starter-openfeign Show documentation
Show all versions of taotao-cloud-starter-openfeign Show documentation
taotao-cloud-starter-openfeign
/*
* Copyright (c) 2020-2030, Shuigedeng ([email protected] & https://blog.taotaocloud.top/).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.taotao.cloud.openfeign.loadbalancer;
import com.taotao.cloud.common.constant.CommonConstant;
import com.taotao.cloud.common.utils.log.LogUtils;
import com.taotao.cloud.openfeign.loadbalancer.chooser.IRuleChooser;
import com.taotao.cloud.openfeign.utils.QueryUtils;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.RequestData;
import org.springframework.cloud.client.loadbalancer.RequestDataContext;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Mono;
/**
* 自定义版本路由选择
*
* @author shuigedeng
* @version 2023.07
* @since 2023-07-06 09:34:42
*/
public class VersionLoadBalancer implements ReactorServiceInstanceLoadBalancer {
private static final String KEY_DEFAULT = "default";
private final ObjectProvider serviceInstanceListSuppliers;
private final String serviceId;
private final IRuleChooser ruleChooser;
/**
* 版本负载均衡器
*
* @param serviceInstanceListSuppliers 服务实例列表供应商
* @param serviceId 服务id
* @param ruleChooser 规则选择器
* @since 2023-07-06 09:34:42
*/
public VersionLoadBalancer(
ObjectProvider serviceInstanceListSuppliers,
String serviceId,
IRuleChooser ruleChooser) {
this.serviceInstanceListSuppliers = serviceInstanceListSuppliers;
this.serviceId = serviceId;
this.ruleChooser = ruleChooser;
}
/**
* 选择
*
* @param request 请求
* @return {@link Mono }<{@link Response }<{@link ServiceInstance }>>
* @since 2023-07-06 09:34:42
*/
@Override
public Mono> choose(Request request) {
// 从request中获取版本,兼容webflux方式
RequestData requestData = ((RequestDataContext) (request.getContext())).getClientRequest();
String version = getVersionFromRequestData(requestData);
LogUtils.debug("选择的版本号为:{}", version);
return serviceInstanceListSuppliers
.getIfAvailable()
.get(request)
.next()
.map(instanceList -> getInstanceResponse(instanceList, version));
}
/**
* 从请求数据获取版本
*
* @param requestData 请求数据
* @return {@link String }
* @since 2023-07-06 09:34:43
*/
private String getVersionFromRequestData(RequestData requestData) {
Map queryMap = QueryUtils.getQueryMap(requestData.getUrl());
if (MapUtils.isNotEmpty(queryMap)
&& queryMap.containsKey(CommonConstant.TTC_REQUEST_VERSION)
&& StringUtils.isNotBlank(queryMap.get(CommonConstant.TTC_REQUEST_VERSION))) {
return queryMap.get(CommonConstant.TTC_REQUEST_VERSION);
} else if (requestData.getHeaders().containsKey(CommonConstant.TTC_REQUEST_VERSION)) {
return requestData
.getHeaders()
.get(CommonConstant.TTC_REQUEST_VERSION)
.get(0);
}
return null;
}
/**
* 1. 先获取到拦截的版本,如果不为空的话就将service列表过滤,寻找metadata中哪个服务是配置的版本, 如果版本为空则不需要进行过滤直接提交给service选择器进行选择 2.
* 如果没有找到版本对应的实例,则找所有版本为空或者版本号为default的实例 3. 将instance列表提交到选择器根据对应的策略返回一个instance
*
* @param instances
*/
private Response getInstanceResponse(List instances, String version) {
List filteredServiceIstanceList = instances;
if (StringUtils.isNotBlank(version)) {
if (CollectionUtils.isNotEmpty(instances)) {
filteredServiceIstanceList = instances.stream()
.filter(item -> item.getMetadata().containsKey(CommonConstant.METADATA_VERSION)
&& version.equals(item.getMetadata().get(CommonConstant.METADATA_VERSION)))
.toList();
}
}
// 如果没有找到对应的版本实例时,选择版本号为空的或这版本为default的实例
if (CollectionUtils.isEmpty(filteredServiceIstanceList)) {
filteredServiceIstanceList = instances.stream()
.filter(item -> !item.getMetadata().containsKey(CommonConstant.METADATA_VERSION)
|| StringUtils.isBlank(item.getMetadata().get(CommonConstant.METADATA_VERSION))
|| "default".equals(item.getMetadata().get(CommonConstant.METADATA_VERSION)))
.toList();
}
// 经过两轮过滤后如果能找到的话就选择,不然返回空
if (CollectionUtils.isNotEmpty(filteredServiceIstanceList)) {
ServiceInstance serviceInstance = this.ruleChooser.choose(filteredServiceIstanceList);
if (!Objects.isNull(serviceInstance)) {
LogUtils.debug(
"使用serviceId为:{}服务, 选择version为:{}, 地址:{}:{},",
serviceId,
version,
serviceInstance.getHost(),
serviceInstance.getPort());
return new DefaultResponse(serviceInstance);
}
}
// 返回空的返回体
return new EmptyResponse();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy