聊聊spring-cloud-kubernetes-client-loadbalancer

本文主要研究一下spring-cloud-kubernetes-client-loadbalancer

ServiceInstanceListSupplier

org/springframework/cloud/loadbalancer/core/ServiceInstanceListSupplier.java

public interface ServiceInstanceListSupplier extends Supplier<Flux<List<ServiceInstance>>> {String getServiceId();default Flux<List<ServiceInstance>> get(Request request) {return get();}static ServiceInstanceListSupplierBuilder builder() {return new ServiceInstanceListSupplierBuilder();}}

spring-cloud-loadbalancer定义了ServiceInstanceListSupplier,它继承自Supplier,其泛型为Flux<List<ServiceInstance>>,它定义了getServiceId、get(Request)方法,并提供了builder静态方法

Request

org/springframework/cloud/client/loadbalancer/Request.java

public interface Request<C> {// Avoid breaking backward compatibilitydefault C getContext() {return null;}// TODO: define contents}

Request提供了getContext方法,默认返回null

DefaultRequest

org/springframework/cloud/client/loadbalancer/DefaultRequest.java

public class DefaultRequest<T> implements Request<T> {private T context;public DefaultRequest() {new DefaultRequestContext();}public DefaultRequest(T context) {this.context = context;}@Overridepublic T getContext() {return context;}public void setContext(T context) {this.context = context;}@Overridepublic String toString() {ToStringCreator to = new ToStringCreator(this);to.append("context", context);return to.toString();}@Overridepublic boolean equals(Object o) {if (this == o) {return true;}if (!(o instanceof DefaultRequest<?> that)) {return false;}return Objects.equals(context, that.context);}@Overridepublic int hashCode() {return Objects.hash(context);}}

DefaultRequest实现了Request,其定义的泛型为context的类型

ServiceInstanceListSupplier

spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServicesListSupplier.java

public abstract class KubernetesServicesListSupplier implements ServiceInstanceListSupplier {protected final Environment environment;protected final KubernetesDiscoveryProperties discoveryProperties;protected final KubernetesServiceInstanceMapper mapper;public KubernetesServicesListSupplier(Environment environment, KubernetesServiceInstanceMapper mapper,KubernetesDiscoveryProperties discoveryProperties) {this.environment = environment;this.discoveryProperties = discoveryProperties;this.mapper = mapper;}@Overridepublic String getServiceId() {return environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);}@Overridepublic abstract Flux<List<ServiceInstance>> get();}

KubernetesServicesListSupplier声明实现ServiceInstanceListSupplier接口,它是一个抽象类,定义了get方法,这里忽略了get(Request),没有将Request传递下来

KubernetesClientServicesListSupplier

spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServicesListSupplier.java

public class KubernetesClientServicesListSupplier extends KubernetesServicesListSupplier {private static final Log LOG = LogFactory.getLog(KubernetesClientServicesListSupplier.class);private CoreV1Api coreV1Api;private KubernetesClientProperties kubernetesClientProperties;private KubernetesNamespaceProvider kubernetesNamespaceProvider;public KubernetesClientServicesListSupplier(Environment environment, KubernetesServiceInstanceMapper mapper,KubernetesDiscoveryProperties discoveryProperties, CoreV1Api coreV1Api,KubernetesNamespaceProvider kubernetesNamespaceProvider) {super(environment, mapper, discoveryProperties);this.coreV1Api = coreV1Api;this.kubernetesNamespaceProvider = kubernetesNamespaceProvider;}private String getNamespace() {return kubernetesNamespaceProvider != null ? kubernetesNamespaceProvider.getNamespace(): kubernetesClientProperties.namespace();}@Overridepublic Flux<List<ServiceInstance>> get() {LOG.info("Getting services with id " + this.getServiceId());List<ServiceInstance> result = new ArrayList<>();List<V1Service> services;try {if (discoveryProperties.allNamespaces()) {services = coreV1Api.listServiceForAllNamespaces(null, null, "metadata.name=" + this.getServiceId(),null, null, null, null, null, null, null, null).getItems();}else {services = coreV1Api.listNamespacedService(getNamespace(), null, null, null,"metadata.name=" + this.getServiceId(), null, null, null, null, null, null, null).getItems();}services.forEach(service -> result.add(mapper.map(service)));}catch (ApiException e) {LOG.warn("Error retrieving service with name " + this.getServiceId(), e);}LOG.info("Returning services: " + result);return Flux.defer(() -> Flux.just(result));}}

KubernetesClientServicesListSupplier继承了KubernetesServicesListSupplier,其构造器依赖KubernetesServiceInstanceMapper、KubernetesDiscoveryProperties、CoreV1Api、KubernetesNamespaceProvider;其get方法使用coreV1Api.listServiceForAllNamespaces或者coreV1Api.listNamespacedService来返回指定serviceId的V1Service信息,之后通过mapper转换为ServiceInstance

V1Service

io/kubernetes/client/openapi/models/V1Service.java

public class V1Service implements io.kubernetes.client.common.KubernetesObject {public static final String SERIALIZED_NAME_API_VERSION = "apiVersion";@SerializedName(SERIALIZED_NAME_API_VERSION)private String apiVersion;public static final String SERIALIZED_NAME_KIND = "kind";@SerializedName(SERIALIZED_NAME_KIND)private String kind;public static final String SERIALIZED_NAME_METADATA = "metadata";@SerializedName(SERIALIZED_NAME_METADATA)private V1ObjectMeta metadata;public static final String SERIALIZED_NAME_SPEC = "spec";@SerializedName(SERIALIZED_NAME_SPEC)private V1ServiceSpec spec;public static final String SERIALIZED_NAME_STATUS = "status";@SerializedName(SERIALIZED_NAME_STATUS)private V1ServiceStatus status;//......
}  

V1Service定义了apiVersion、kind、metadata、spec、status属性

KubernetesServiceInstanceMapper

spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/loadbalancer/KubernetesServiceInstanceMapper.java

public interface KubernetesServiceInstanceMapper<T> {KubernetesServiceInstance map(T service);static String createHost(String serviceName, String namespace, String clusterDomain) {return String.format("%s.%s.svc.%s", serviceName, StringUtils.hasText(namespace) ? namespace : "default",clusterDomain);}static boolean isSecure(Map<String, String> labels, Map<String, String> annotations, String servicePortName,Integer servicePort) {if (labels != null) {final String securedLabelValue = labels.getOrDefault("secured", "false");if (securedLabelValue.equals("true")) {return true;}}if (annotations != null) {final String securedAnnotationValue = annotations.getOrDefault("secured", "false");if (securedAnnotationValue.equals("true")) {return true;}}return (servicePortName != null && servicePortName.endsWith("https")) || servicePort.toString().endsWith("443");}static Map<String, String> getMapWithPrefixedKeys(Map<String, String> map, String prefix) {if (map == null) {return new HashMap<>();}if (!StringUtils.hasText(prefix)) {return map;}final Map<String, String> result = new HashMap<>();map.forEach((k, v) -> result.put(prefix + k, v));return result;}}

KubernetesServiceInstanceMapper接口定义了map方法,它提供了createHost、isSecure、getMapWithPrefixedKeys静态方法

KubernetesClientServiceInstanceMapper

spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientServiceInstanceMapper.java

public class KubernetesClientServiceInstanceMapper implements KubernetesServiceInstanceMapper<V1Service> {private KubernetesLoadBalancerProperties properties;private KubernetesDiscoveryProperties discoveryProperties;public KubernetesClientServiceInstanceMapper(KubernetesLoadBalancerProperties properties,KubernetesDiscoveryProperties discoveryProperties) {this.properties = properties;this.discoveryProperties = discoveryProperties;}@Overridepublic KubernetesServiceInstance map(V1Service service) {final V1ObjectMeta meta = service.getMetadata();final List<V1ServicePort> ports = service.getSpec().getPorts();V1ServicePort port = null;if (ports.size() == 1) {port = ports.get(0);}else if (ports.size() > 1 && StringUtils.hasText(this.properties.getPortName())) {Optional<V1ServicePort> optPort = ports.stream().filter(it -> properties.getPortName().endsWith(it.getName())).findAny();if (optPort.isPresent()) {port = optPort.get();}}if (port == null) {return null;}final String host = KubernetesServiceInstanceMapper.createHost(service.getMetadata().getName(),service.getMetadata().getNamespace(), properties.getClusterDomain());final boolean secure = KubernetesServiceInstanceMapper.isSecure(service.getMetadata().getLabels(),service.getMetadata().getAnnotations(), port.getName(), port.getPort());return new DefaultKubernetesServiceInstance(meta.getUid(), meta.getName(), host, port.getPort(),getServiceMetadata(service), secure);}private Map<String, String> getServiceMetadata(V1Service service) {final Map<String, String> serviceMetadata = new HashMap<>();KubernetesDiscoveryProperties.Metadata metadataProps = this.discoveryProperties.metadata();if (metadataProps.addLabels()) {Map<String, String> labelMetadata = KubernetesServiceInstanceMapper.getMapWithPrefixedKeys(service.getMetadata().getLabels(), metadataProps.labelsPrefix());serviceMetadata.putAll(labelMetadata);}if (metadataProps.addAnnotations()) {Map<String, String> annotationMetadata = KubernetesServiceInstanceMapper.getMapWithPrefixedKeys(service.getMetadata().getAnnotations(), metadataProps.annotationsPrefix());serviceMetadata.putAll(annotationMetadata);}return serviceMetadata;}}

KubernetesClientServiceInstanceMapper实现了KubernetesServiceInstanceMapper接口,其泛型为V1Service,其map方法先通过service.getSpec().getPorts()获取port信息,之后通过createHost返回svc的短域名<servicename>.<namespace>.svc.<clusterdomain>,例如service-a.default.svc.cluster.local,最后创建DefaultKubernetesServiceInstance

KubernetesClientLoadBalancerClientConfiguration

spring-cloud-kubernetes-client-loadbalancer/src/main/java/org/springframework/cloud/kubernetes/client/loadbalancer/KubernetesClientLoadBalancerClientConfiguration.java

public class KubernetesClientLoadBalancerClientConfiguration {@Bean@ConditionalOnProperty(name = "spring.cloud.kubernetes.loadbalancer.mode", havingValue = "SERVICE")ServiceInstanceListSupplier kubernetesServicesListSupplier(Environment environment, CoreV1Api coreV1Api,KubernetesClientServiceInstanceMapper mapper, KubernetesDiscoveryProperties discoveryProperties,KubernetesNamespaceProvider kubernetesNamespaceProvider, ConfigurableApplicationContext context) {return ServiceInstanceListSupplier.builder().withBase(new KubernetesClientServicesListSupplier(environment,mapper, discoveryProperties, coreV1Api, kubernetesNamespaceProvider)).withCaching().build(context);}}

KubernetesClientLoadBalancerClientConfiguration在spring.cloud.kubernetes.loadbalancer.mode设置为SERVICE的时候会自动创建kubernetesServicesListSupplier

小结

spring-cloud-loadbalancer定义了ServiceInstanceListSupplier,它继承自Supplier,其泛型为Flux<List<ServiceInstance>>,它定义了getServiceId、get(Request)方法,并提供了builder静态方法;KubernetesServicesListSupplier声明实现ServiceInstanceListSupplier接口,它是一个抽象类,定义了get方法;KubernetesClientServicesListSupplier继承了KubernetesServicesListSupplier,其构造器依赖KubernetesServiceInstanceMapper、KubernetesDiscoveryProperties、CoreV1Api、KubernetesNamespaceProvider;其get方法使用coreV1Api.listServiceForAllNamespaces或者coreV1Api.listNamespacedService来返回指定serviceId的V1Service信息,之后通过mapper转换为ServiceInstance。

整体来看spring-cloud-kubernetes-client-loadbalancer目前仅支持spring.cloud.kubernetes.loadbalancer.mode为SERVICE的模式,其实内部还是走的k8s的service的域名解析及负载均衡,无法细粒度到个性化的负载均衡。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/705490.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Leetcode每日一题】二分查找 - 寻找峰值(难度⭐⭐)(20)

1. 题目解析 Leetcode链接&#xff1a;162. 寻找峰值 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 核心在于找到题目中所说的峰值并返回他们的下标即可。 2. 算法原理 分析峰顶及其两旁数据的特点 峰顶数据特点&#xff1a;峰…

windows 11+docker desktop+grafana+influxDB+python写入

下载安装docker desktop 出现WSL相关的错误。WSL是一个linux内核的子系统&#xff0c;docker是基于linux内核的&#xff0c;所以运行docker需要WSL。 以管理员权限打开powershell&#xff0c;查看WSL状态 wsl --status 我遇到的错误是因为我关闭了windows的某些更新 执行上…

Android自定义View实现数字密码锁

最近项目上用到一个密码加锁功能&#xff0c;需要一个数字密码界面&#xff0c;就想着封装成一个View来方便管理和使用。 废话不多说&#xff0c;先上最终效果图&#xff1a; 思路 整体可分为2个部分来实现&#xff0c;1.顶部是4个密码位的填充&#xff1b;2.数字键盘部分。整…

VUE基础知识九 ElementUI项目

ElementUI官网 一 项目 最终完成的效果&#xff1a; 切换上边的不同按钮&#xff0c;下方显示不同的表格数据 在src/components下新建不同业务组件的文件夹 1.1 搭建项目 使用脚手架搭建项目后&#xff0c;引入ElementUI&#xff08;搭建、引入ElementUI步骤在第七节里已…

旧衣服回收小程序开发:企业、创业者收益新模式

近年来&#xff0c;我国旧衣回收行业发展迅速。随着大众对衣物的更新需求增加&#xff0c;闲置衣物便也不断增加&#xff0c;我国的旧衣回收行业的市场规模随之增加。 当下&#xff0c;旧衣回收产业链较为完善&#xff0c;主要以出口为主&#xff0c;回收利润较高。与其他行业…

XXL-JOB面试问题

⭐ 作者简介&#xff1a;码上言 ⭐ 代表教程&#xff1a;Spring Boot vue-element 开发个人博客项目实战教程 ⭐专栏内容&#xff1a;个人博客系统 ⭐我的文档网站&#xff1a;http://xyhwh-nav.cn/ 文章目录 XXL-JOB面试问题1. 什么是XXL-Job2. XXL-Job的核心组件是什么3…

【Pytorch深度学习开发实践学习】Pytorch实现LeNet神经网络(1)

1.model.py import torch.nn as nn import torch.nn.functional as F引入pytorch的两个模块 关于这两个模块的作用&#xff0c;可以参考下面 Pytorch官方文档 torch.nn包含了构成计算图的基本模块 torch,nn.function包括了计算图中的各种主要函数&#xff0c;包括&#…

2.23号qt

4.3 颜色对话框 QColorDialog 该类给用户提供了一个颜色对话框&#xff0c;直接调用该类的一个静态成员函数getColor()即可直接弹出颜色对话框。 [static] QColor //返回值类型 返回的是用户选中的颜色 静态函数 QColorDialog::getColor(//函数名 const QColor …

python Matplotlib Tkinter--pack 框架案例

环境 python:python-3.12.0-amd64 包: matplotlib 3.8.2 pillow 10.1.0 版本一 import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk import tkinter as tk import tkinter.messagebox as messagebox…

优思学院|精益生产管理在中国的发展前景

在这个快速变化的世界里&#xff0c;有一个管理理念悄然崛起&#xff0c;它就是精益生产。 这个概念最早由詹姆斯P沃麦克、丹尼尔T琼斯和丹尼尔鲁斯在他们的著作《改变世界的机器》中提出&#xff0c;后来在丰田汽车公司的成功实践中得到了广泛的认可。 这本书不仅风靡全球&a…

Springboot中如何记录好日志

Springboot中如何记录日志 日志体系整体介绍 日志一直在系统中占据这十分重要的地位&#xff0c;他是我们在系统发生故障时用来排查问题的利器&#xff0c;也是我们做操作审计的重要依据。那么如何记录好日志呢&#xff1f;选择什么框架来记录日志&#xff0c;是不是日志打越…

Selenium 自动化遇见 shadow-root 元素怎么处理?

shadow-root是前端的特殊元素节点&#xff0c;其使用了一个叫做shadowDOM的技术做了封装&#xff0c;shadowDOM的作用可以理解为在默认的DOM结构中又嵌套了一个DOM结构&#xff08;和iframe有点类似&#xff0c;只不过iframe内嵌的是HTML&#xff09;&#xff0c;我们遇见shado…

MIPS汇编入门

MIPS汇编入门 寄存器种类指令种类寻址方式立即数寻址寄存器寻址基址寻址相对寻址伪直接寻址 指令总览 寄存器种类 MIPS共有32个通用寄存器在汇编中&#xff0c;寄存器标志由$符号开头寄存器表示共有两种方法 直接使用该寄存器对应编号&#xff0c;例如&#xff1a;$0,$31使用对…

管理心得--如何成为优秀的架构师

关注我&#xff0c;持续分享逻辑思维&管理思维&#xff1b; 可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导&#xff1b; 有意找工作的同学&#xff0c;请参考博主的原创&#xff1a;《面试官心得--面试前应该如何准备》&#xff0c;《面试官心得--面试时如何进行自…

LMDeploy 大模型量化部署

Weight Only量化是一种常见的模型优化技术&#xff0c;特别是在深度学习模型的部署中。这种技术仅对模型的权重进行量化&#xff0c;而不涉及激活&#xff08;即模型中间层的输出&#xff09;。选择采用Weight Only量化的原因主要包括以下几点&#xff1a; 减少模型大小 通过将…

VirtualBox虚拟机安装 Linux 系统

要想学习各种计算机技术&#xff0c;自然离不开Linux系统。并且目前大多数生产系统都是安装在Linux系统上。常用的Linux系统有 Redhat&#xff0c;Centos&#xff0c;OracleLinux 三种。 三者的区别简单说明如下&#xff1a; Red Hat Enterprise Linux (RHEL): RHEL 是由美国…

ICASSP2024 | MLCA-AVSR: 基于多层交叉注意力机制的视听语音识别

视听语音识别&#xff08;Audio-visual speech recognition, AVSR&#xff09;是指结合音频和视频信息对语音进行识别的技术。当前&#xff0c;语音识别&#xff08;ASR&#xff09;系统在准确性在某些场景下已经达到与人类相媲美的水平。然而在复杂声学环境或远场拾音场景&…

Qt应用软件【文件篇】XML文件增删查改

文章目录 1. XML文件简介2. XML文件的主要特点3. XML文件的应用场景4. Qt XML文件相关API汇总5. Qt读取XML文件代码示例6. Qt写入XML文件代码示例7. Qt修改XML文件代码示例8. 字符串转换为XML对象9. XML对象转换为字符串10.替换复杂的xml文件中属性,保持格式不变1. XML文件简介…

大语言模型推理加速技术:计算加速篇

原文&#xff1a;大语言模型推理加速技术&#xff1a;计算加速篇 - 知乎 目录 简介 Transformer和Attention 瓶颈 优化目标 计算加速 计算侧优化 KVCache Kernel优化和算子融合 分布式推理 内存IO优化 Flash Attention Flash Decoding Continuous Batching Page…

Go Run - Go 语言中的简洁指令

原文&#xff1a;breadchris - 2024.02.21 也许听起来有些傻&#xff0c;但go run是我最喜欢的 Go 语言特性。想要运行你的代码&#xff1f;只需go run main.go。它是如此简单&#xff0c;我可以告诉母亲这个命令&#xff0c;她会立即理解。就像 Go 语言的大部分功能一样&…