springcloud整合nacos实现相同版本实例相互调用

server/2024/9/23 9:22:50/

springcloud整合nacos实现相同版本实例相互调用

注: 本文为自己学习研究总结,仅供参考,若有侵权,请及时联系本人

业务场景

有时候一些新的业务或者修改后的功能只开放给部分人访问,那么可以新老版本都部署,对于大多数人访问老版本,部分人访问新版本。部分人请求的时候,http请求header添加特定的version值,结合nacos的服务元数据进行塞选服务实例,从而实现不同人访问相同的功能,对应不同的版本。

基础理论

(1)基于feign进行远程方法调用,首先FeignBlockingLoadBalancerClient会根据url中的serviceId,交给LoadBalancerClient#choose()方法拉取服务列表并且基于负载均衡算法选择一个服务实例,最后重构Uri发起请求
(2)RoundRobinLoadbalancer(轮询,springcloudloadbalance默认负载均衡实现,还有一个是随机负载均衡)为例,ServiceInstanceListSupplier#get()用于拉取服务实例,getInstanceResponse()用于负载均衡选择某个实例

coding

demo如下:

import com.google.common.collect.Lists;
import com.test.server.util.GreyThreadLocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.DelegatingServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Flux;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
public class SameVersionServiceInstanceListSupplier extends DelegatingServiceInstanceListSupplier {private final String VERSION = "version";public SameVersionServiceInstanceListSupplier(ServiceInstanceListSupplier delegate) {super(delegate);}@Overridepublic Flux<List<ServiceInstance>> get() {ServiceInstanceListSupplier delegate1 = getDelegate();Flux<List<ServiceInstance>> listFlux = delegate1.get();Flux<List<ServiceInstance>> map = listFlux.map(this::filteredByVersion);return map;}/*** 根据version进行过滤* @param serviceInstances* @return*/private List<ServiceInstance> filteredByVersion(List<ServiceInstance> serviceInstances) {List<ServiceInstance> filteredInstances = new ArrayList<>();for (ServiceInstance serviceInstance : serviceInstances) {String instanceVersion = getVersion(serviceInstance);if (GreyThreadLocalUtils.getVersion().equalsIgnoreCase(instanceVersion)) {filteredInstances.add(serviceInstance);}}if (filteredInstances.size() > 0) {return filteredInstances;}return Lists.newArrayList();}/*** 从元数据获取version值* @param serviceInstance* @return*/private String getVersion(ServiceInstance serviceInstance) {Map<String, String> metadata = serviceInstance.getMetadata();if (metadata != null) {return metadata.get(VERSION);}return null;}
}
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer;
import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.cloud.loadbalancer.support.SimpleObjectProvider;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;@Component
@Configuration(proxyBeanMethods = false)
public class LoadBalanceConfig {/*** 支持的服务实例* @param context* @return*/@Beanpublic ServiceInstanceListSupplier serviceInstanceListSupplier(ConfigurableApplicationContext context) {ServiceInstanceListSupplier supplier = ServiceInstanceListSupplier.builder().withBlockingDiscoveryClient().withCaching().build(context);return new SameVersionServiceInstanceListSupplier(supplier);}/*** 负载均衡方式* @param environment* @param serviceInstanceListSupplier* @return*/@Beanpublic ReactorLoadBalancer<ServiceInstance> reactorServiceInstanceLoadBalancer(Environment environment, ServiceInstanceListSupplier serviceInstanceListSupplier) {String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);return new RoundRobinLoadBalancer(new SimpleObjectProvider<>(serviceInstanceListSupplier), name);}
}
/*** 注入了spring容器*/
@Configuration(proxyBeanMethods = false)
@LoadBalancerClients(defaultConfiguration = LoadBalanceConfig.class)
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class,LoadBalancerBeanPostProcessorAutoConfiguration.class })
public class LoadBalanceAutoConfiguration {
}

参考资料

(1) https://mp.weixin.qq.com/s/rsRGMRiRb0atKclPl2K1zg
(2) 黑马程序员 java黑马商城项目微服务实战开发视频讲解


http://www.ppmy.cn/server/36904.html

相关文章

(三)JSP教程——JSP动作标签

JSP动作标签 用户可以使用JSP动作标签向当前输出流输出数据&#xff0c;进行页面定向&#xff0c;也可以通过动作标签使用、修改和创建对象。 <jsp:include>标签 <jsp:include>标签将同一个Web应用中静态或动态资源包含到当前页面中。资源可以是HTML、JSP页面和文…

three.js实现三维爆炸效果

主要是split函数 <template><div class"app"><div class"btns"><button click"split">{{ isSplit ? "组合" : "分解" }}</button></div><div ref"canvesRef" class&quo…

Vitis HLS 学习笔记--Schedule Viewer 调度查看器

目录 1. 简介 2. Schedule Viewer详解 2.1 视图说明 2.1.1 Operation\Control Step 2.1.2 周期关系图 2.1.3 Schedule Viewer 菜单栏 2.1.4 属性视图 2.2 内容说明 2.2.1 实参&#xff08;b&#xff09;解释 2.2.2 实参&#xff08;a&#xff09;解释 2.2.3 变量&am…

商米-android-使用NFC读IC卡,身份证云解和IC卡同时兼容

商米介绍地址&#xff1a;https://www.sunmi.com/ 商米是一个提供手持PDA的一个很好的解决方案厂商&#xff0c; 也有其他的一些桌面设备。 其中商米提供的软件服务中&#xff0c;比较特别的是 身份证云解功能。 此处重点说明一下&#xff0c;身份证云解功能。 以往市面上的身…

一键转换,MP4视频变为MP3音频,只需这一行代码!

想要将珍藏的视频配乐提取出来&#xff1f;想把喜欢的电影原声变成音频&#xff1f;现在&#xff0c;只需一行代码&#xff0c;就能轻松将MP4视频转换为MP3音频&#xff01; 这篇文章将带你一步步完成转换&#xff0c;并详细解释每一步的操作&#xff0c;即使你是新手也能轻松…

93. 复原 IP 地址

93. 复原 IP 地址 题目描述: 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址&…

贪心算法应用例题

最优装载问题 #include <stdio.h> #include <algorithm>//排序int main() {int data[] { 8,20,5,80,3,420,14,330,70 };//物体重量int max 500;//船容最大总重量int count sizeof(data) / sizeof(data[0]);//物体数量std::sort(data, data count);//排序,排完数…

大宋咨询消费者需求研究问卷如何设计

设计消费者需求研究问卷需要考虑清楚研究目标、问题和目标受众的特点。一个良好的问卷设计能够确保收集到准确、有用的消费者反馈。以下大宋咨询是设计消费者需求研究问卷的一些建议&#xff1a; 1. 确定研究目标和问题&#xff1a; 在设计问卷之前&#xff0c;明确你希望从问…