当前位置: 首页 > news >正文

Java在SpringCloud中自定义Gateway负载均衡策略

Java在SpringCloud中自定义Gateway负载均衡策略

一、前言

spring-cloud-starter-netflix-ribbon已经不再更新了,最新版本是2.2.10.RELEASE,最后更新时间是2021年11月18日,详细信息可以看maven官方仓库:org.springframework.cloud/spring-cloud-starter-netflix-ribbon,SpringCloud官方推荐使用spring-cloud-starter-loadbalancer进行负载均衡。

背景:大文件上传做切片文件上传;

流程:将切片文件上传到服务器,然后进行合并任务,合并完成之后上传到对象存储;现在服务搞成多节点以后,网关默认走轮循,但是相同的服务在不同的机器上,这样就会导致切片文件散落在不同的服务器上,会导致文件合并失败;所以根据一个标识去自定义gateway对应服务的负载均衡策略,可以解决这个问题;

我的版本如下:

<spring-boot.version>2.7.3</spring-boot.version>
        <spring-cloud.version>2021.0.4</spring-cloud.version>
        <spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>

二、参考默认实现

springCloud原生默认的负载均衡策略是这个类:

org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer

我们参考这个类实现自己的负载均衡策略即可,RoundRobinLoadBalancer实现了ReactorServiceInstanceLoadBalancer这个接口,实现了choose这个方法,如下图:

在choose方法中调用了processInstanceResponse方法,processInstanceResponse方法中调用了getInstanceResponse方法,所以我们我们可以复制RoundRobinLoadBalancer整个类,只修改getInstanceResponse这个方法里的内容就可以实现自定义负载均衡策略。

三、实现代码

原理:根据请求头当中设备的唯一标识传递到下游,唯一标识做哈希取余,可以指定对应的服务器节点,需要的服务设置自定义负载策略,不需要的服务设置默认的轮循机制即可.我这里是根据单独的接口请求地址去自定义,也可以根据服务名称自定义

package com.wondertek.gateway.loadBalancer;import cn.hutool.core.util.ObjectUtil;
import com.wondertek.web.exception.enums.HttpRequestHeaderEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Slf4j
@Component
public class RequestFilter implements GlobalFilter, Ordered {@Overridepublic int getOrder() {// 应该小于LoadBalancerClientFilter的顺序值return Ordered.HIGHEST_PRECEDENCE;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();String clientDeviceUniqueCode = request.getHeaders().getFirst(HttpRequestHeaderEnum.CLIENT_DEVICE_UNIQUE_CODE.getCode());// 存入Reactor上下文String resultCode = clientDeviceUniqueCode;//路径String pathUrl = request.getURI().getPath();/*** ^ 锚点匹配输入字符串的开始位置。*  /(oms-api|unity-api|cloud-api) 匹配以 /oms-api 或 /unity-api 或 /cloud-api 开始的任何字符串。*  replaceFirst() 方法用空字符串替换第一次匹配的内容,也就是我们想要去掉的服务名称。*/String resultPathUrl = pathUrl.replaceFirst("^/(oms-api|unity-api|cloud-api)", "");return chain.filter(exchange).contextWrite(context -> {if (ObjectUtil.isNotEmpty(resultCode) && ObjectUtil.isNotEmpty(resultPathUrl)) {log.info("开始将request中的唯一标识封装到上下游中:{},请求path是:{}", resultCode, resultPathUrl);return context.put("identification", resultCode).put("pathUrl", resultPathUrl);} else {//根据需求进行其他处理return context;}});}
}
package com.wondertek.gateway.loadBalancer;import cn.hutool.core.util.ObjectUtil;
import com.wondertek.center.constants.BusinessCenterApi;
import lombok.extern.slf4j.Slf4j;
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.Response;
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.SelectedInstanceCallback;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Mono;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;@Slf4j
public class ClientDeviceUniqueCodeInstanceLoadBalancer implements ReactorServiceInstanceLoadBalancer {private final String serviceId;final AtomicInteger position;private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;public ClientDeviceUniqueCodeInstanceLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, AtomicInteger position) {this.serviceId = serviceId;this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;this.position = position;}@Overridepublic Mono<Response<ServiceInstance>> choose(Request request) {//在 choose 方法中,使用 deferContextual 方法来访问上下文并提取客户端标识。这里的 getOrDefault 方法尝试从上下文中获取一个键为 "identification" 的值,如果不存在则返回 "default-identification"return Mono.deferContextual(contextView -> {String identification = contextView.getOrDefault("identification", "");log.info("上下游获取到的identification的值为:{}", identification);String pathUrl = contextView.getOrDefault("pathUrl", "");log.info("上下游获取到的pathUrl的值为:{}", pathUrl);ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);return supplier.get(request).next().map(serviceInstances -> processInstanceResponse(supplier, serviceInstances, identification, pathUrl));});}private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier, List<ServiceInstance> serviceInstances, String identification, String pathUrl) {Response<ServiceInstance> serviceInstanceResponse;//特定接口走自定义负载策略Boolean status = ObjectUtil.isNotEmpty(identification) && ObjectUtil.isNotEmpty(pathUrl) &&(pathUrl.contains(BusinessCenterApi.WEB_UPLOAD_SLICE_FILE) ||pathUrl.contains(BusinessCenterApi.WEB_MERGE_SLICE_FILE) ||pathUrl.contains(BusinessCenterApi.UNITY_UPLOAD_SLICE_FILE) ||pathUrl.contains(BusinessCenterApi.UNITY_MERGE_SLICE_FILE) ||pathUrl.contains(BusinessCenterApi.CLOUD_UPLOAD_SLICE_FILE) ||pathUrl.contains(BusinessCenterApi.CLOUD_MERGE_SLICE_FILE));if (status) {serviceInstanceResponse = this.getIpInstanceResponse(serviceInstances, identification);} else {serviceInstanceResponse = this.getInstanceResponse(serviceInstances);}if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {((SelectedInstanceCallback) supplier).selectedServiceInstance((ServiceInstance) serviceInstanceResponse.getServer());}return serviceInstanceResponse;}private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {if (instances.isEmpty()) {if (log.isWarnEnabled()) {log.warn("No servers available for service: " + this.serviceId);}return new EmptyResponse();} else {//创建一个新的列表以避免在原始列表上排序,避免了修改共享状态可能带来的线程安全问题List<ServiceInstance> sortedInstances = new ArrayList<>(instances);// 现在对新列表进行排序,保持原始列表的顺序不变Collections.sort(sortedInstances, Comparator.comparing(ServiceInstance::getHost));//log.info("获取到的实例个数的值为:{}", sortedInstances.size());sortedInstances.forEach(instance -> log.info("排序后的实例: {},{}", instance.getHost(), instance.getPort()));int pos = Math.abs(this.position.incrementAndGet());//log.info("默认轮循机制,pos递加后的值为:{}", pos);int positionIndex = pos % instances.size();//log.info("取余后的positionIndex的值为:{}", positionIndex);ServiceInstance instance = instances.get(positionIndex);//log.info("instance.getUri()的值为:{}", instance.getUri());log.info("特殊服务,默认轮循机制,routed to instance: {}:{}", instance.getHost(), instance.getPort());return new DefaultResponse(instance);}}private Response<ServiceInstance> getIpInstanceResponse(List<ServiceInstance> instances, String identification) {if (instances.isEmpty()) {log.warn("No servers available for service: " + this.serviceId);return new EmptyResponse();} else {//创建一个新的列表以避免在原始列表上排序,避免了修改共享状态可能带来的线程安全问题List<ServiceInstance> sortedInstances = new ArrayList<>(instances);// 现在对新列表进行排序,保持原始列表的顺序不变Collections.sort(sortedInstances, Comparator.comparing(ServiceInstance::getHost));//log.info("获取到的实例个数的值为:{}", sortedInstances.size());sortedInstances.forEach(instance -> log.info("排序后的实例: {},{}", instance.getHost(), instance.getPort()));//log.info("多个服务实例,使用客户端 identification 地址的哈希值来选择服务实例");// 使用排序后的列表来找到实例int ipHashCode = Math.abs(identification.hashCode());//log.info("identificationHashCode的值为:{}", ipHashCode);int instanceIndex = ipHashCode % sortedInstances.size();//log.info("instanceIndex的值为:{}", instanceIndex);ServiceInstance instanceToReturn = sortedInstances.get(instanceIndex);//log.info("instanceToReturn.getUri()的值为:{}", instanceToReturn.getUri());log.info("特殊服务,自定义identification负载机制,Client identification: {} is routed to instance: {}:{}", identification, instanceToReturn.getHost(), instanceToReturn.getPort());return new DefaultResponse(instanceToReturn);}}}
package com.wondertek.gateway.loadBalancer;import lombok.extern.slf4j.Slf4j;
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.Response;
import org.springframework.cloud.loadbalancer.core.NoopServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.SelectedInstanceCallback;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Mono;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;@Slf4j
public class DefaultInstanceLoadBalancer implements ReactorServiceInstanceLoadBalancer {private final String serviceId;private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;final AtomicInteger position;public DefaultInstanceLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, AtomicInteger position) {this.serviceId = serviceId;this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;this.position = position;}@Overridepublic Mono<Response<ServiceInstance>> choose(Request request) {ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);return supplier.get(request).next().map(serviceInstances -> processInstanceResponse(supplier, serviceInstances));}private Response<ServiceInstance> processInstanceResponse(ServiceInstanceListSupplier supplier,List<ServiceInstance> serviceInstances) {Response<ServiceInstance> serviceInstanceResponse = getInstanceResponse(serviceInstances);if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());}return serviceInstanceResponse;}private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {if (instances.isEmpty()) {if (log.isWarnEnabled()) {log.warn("No servers available for service: " + serviceId);}return new EmptyResponse();}//创建一个新的列表以避免在原始列表上排序,避免了修改共享状态可能带来的线程安全问题List<ServiceInstance> sortedInstances = new ArrayList<>(instances);// 现在对新列表进行排序,保持原始列表的顺序不变Collections.sort(sortedInstances, Comparator.comparing(ServiceInstance::getHost));//log.info("获取到的实例个数的值为:{}", sortedInstances.size());sortedInstances.forEach(instance -> log.info("排序后的实例: {},{}", instance.getHost(), instance.getPort()));int pos = Math.abs(this.position.incrementAndGet());//log.info("默认轮循机制,pos递加后的值为:{}", pos);int positionIndex = pos % instances.size();//log.info("取余后的positionIndex的值为:{}", positionIndex);ServiceInstance instance = instances.get(positionIndex);//log.info("instance.getUri()的值为:{}", instance.getUri());log.info("默认轮循机制,routed to instance: {}:{}",instance.getHost(), instance.getPort());return new DefaultResponse(instance);}}
package com.wondertek.gateway.loadBalancer;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;import java.util.concurrent.atomic.AtomicInteger;@Configuration
//单台服务
//@LoadBalancerClient(name = "oms-api", configuration = CustomLoadBalancerConfig.class)
//多台服务
@LoadBalancerClients({@LoadBalancerClient(name = "oms-api", configuration = CustomLoadBalancerConfig.class),@LoadBalancerClient(name = "unity-api", configuration = CustomLoadBalancerConfig.class),@LoadBalancerClient(name = "cloud-api", configuration = CustomLoadBalancerConfig.class),@LoadBalancerClient(name = "open-api", configuration = CustomLoadBalancerConfig.class),@LoadBalancerClient(name = "server-api", configuration = CustomLoadBalancerConfig.class),@LoadBalancerClient(name = "center-service", configuration = CustomLoadBalancerConfig.class),
})
@Slf4j
public class CustomLoadBalancerConfig {// 定义一个Bean来提供AtomicInteger的实例@Beanpublic AtomicInteger positionTracker() {// 这将在应用上下文中只初始化一次return new AtomicInteger(0);}//自定义优先级负载均衡器@Beanpublic ReactorServiceInstanceLoadBalancer customPriorityLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider,Environment environment,AtomicInteger positionTracker) {String serviceId = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);//目的为解决文件上传切片文件分散上传的问题if ("oms-api".equals(serviceId)||"unity-api".equals(serviceId)||"cloud-api".equals(serviceId)){//log.info("服务名称:serviceId:{},走自定义clientDeviceUniqueCode负载模式", serviceId);return new ClientDeviceUniqueCodeInstanceLoadBalancer(serviceInstanceListSupplierProvider, serviceId, positionTracker);}//log.info("服务名称:serviceId:{},走默认负载模式", serviceId);return new DefaultInstanceLoadBalancer(serviceInstanceListSupplierProvider, serviceId,positionTracker);}
}

【SpringCloud系列】开发环境下重写Loadbalancer实现自定义负载均衡

相关文章:

Java在SpringCloud中自定义Gateway负载均衡策略

Java在SpringCloud中自定义Gateway负载均衡策略 一、前言 spring-cloud-starter-netflix-ribbon已经不再更新了&#xff0c;最新版本是2.2.10.RELEASE&#xff0c;最后更新时间是2021年11月18日&#xff0c;详细信息可以看maven官方仓库&#xff1a;org.springframework.clou…...

前端 js 基础(1)

js 结果输出 &#xff08;点击按钮修改文字 &#xff09; <!DOCTYPE html> <html> <head></head><body><h2>Head 中的 JavaScript</h2><p id"demo">一个段落。</p><button type"button" onclic…...

Android : 使用GestureOverlayView进行手势识别—简单应用

示例图&#xff1a; GestureOverlayView介绍&#xff1a; GestureOverlayView 是 Android 开发中用于识别和显示手势的视图组件。它允许用户在屏幕上绘制手势&#xff0c;并且应用程序可以检测和响应这些手势。以下是关于 GestureOverlayView 的主要特点&#xff1a; 手势识别…...

API集群负载统计 (100%用例)C卷 (JavaPythonNode.jsC语言C++)

某个产品的RESTful API集合部署在服务器集群的多个节点上, 近期对客户端访问日志进行了采集,需要统计各个API的访问频次, 根据热点信息在服务器节点之间做负载均衡,现在需要实现热点信息统计查询功能。 RESTful API的由多个层级构成,层级之间使用/连接,如/A/B/C/D这个地址…...

小梅哥Xilinx FPGA学习笔记18——专用时钟电路 PLL与时钟向导 IP

目录 一&#xff1a;IP核简介&#xff08;具体可参考野火FPGA文档&#xff09; 二&#xff1a; 章节导读 三&#xff1a;PLL电路原理 3.1 PLL基本实现框图 3.2 PLL倍频实现 3.3 PLL分频实现 四: 基于 PLL 的多时钟 LED 驱动设计 4.1 配置 Clocking Wizard 核 4.2 led …...

低代码平台在金融银行中的应用场景

随着数字化转型的推进&#xff0c;商业银行越来越重视技术在业务发展中的作用。在这个背景下&#xff0c;白码低代码平台作为一种新型的开发方式&#xff0c;正逐渐受到广大商业银行的关注和应用。白码低代码平台能够快速构建各类应用程序&#xff0c;提高开发效率&#xff0c;…...

Css基础内容

<!DOCTYPE html> <html> <head> <meta charset"UTF-8" /> <title>CSS</title> <!-- <link rel"stylesheet" href"Html5与Css3\CSS\my.css"> --> <!-- link引入外部样式表&#xff1a;rel&…...

微服务(11)

目录 51.pod的重启策略是什么&#xff1f; 52.描述一下pod的生命周期有哪些状态&#xff1f; 53.创建一个pod的流程是什么&#xff1f; 54.删除一个Pod会发生什么事情&#xff1f; 55.k8s的Service是什么&#xff1f; 51.pod的重启策略是什么&#xff1f; 可以通过命令kub…...

连锁门店管理需要信息化系统

连锁门店管理的信息化系统可以提供以下功能&#xff0c;以满足连锁企业日常管理的需求&#xff1a; 1. 连锁线下收银&#xff1a;信息化系统可以提供线下收银功能&#xff0c;包括商品扫码、价格结算、支付方式选择等。通过系统记录每笔交易数据&#xff0c;方便对销售情况进行…...

UTF-8编码:打破字符编码的国界

UTF-8编码&#xff1a;打破字符编码的国界 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;让我们一同探讨编程世界中一项至关重要的技术——“UTF-…...

HTML进阶

列表、表格、表单 文章目录 列表、表格、表单01-列表无序列表有序列表定义列表 02-表格表格结构标签-了解合并单元格 03-表单input 标签input 标签占位文本单选框上传文件多选框下拉菜单文本域label 标签按钮 04-语义化无语义的布局标签有语义的布局标签 05-字符实体 01-列表 …...

基于策略模式和简单工厂模式实现zip、tar、rar、7z四种压缩文件格式的解压

推荐语 这篇技术文章深入探讨了基于策略模式和简单工厂模式实现四种常见压缩文件格式的解压方法。通过阅读该文章&#xff0c;你将了解到如何利用这两种设计模式来实现灵活、可扩展的解压功能&#xff0c;同时适应不同的压缩文件格式。如果你对设计模式和文件处理感兴趣或刚好…...

修改jenkins的目录(JENKINS_HOME)

默认JENKINS_HOME是/var/lib/jenkins/ 现要修改为/home/jenkins_data/jenkins 最开始 sudo cp -a /var/lib/jenkins/ /home/jenkins_data/ 然后如下操作&#xff1a; 1、首先 /etc/sysconfig/jenkins&#xff1a;jenkins配置文件&#xff0c;“端口”&#xff0c;“JENKIN…...

Bytebase:统一数据库 CI/CD 解决方案 | 开源日报 No.128

bytebase/bytebase Stars: 7.9k License: NOASSERTION Bytebase 是一个数据库 CI/CD 解决方案&#xff0c;为开发人员和 DBA 提供统一的工具来管理不同数据库系统的开发生命周期。其主要功能包括标准化操作流程、SQL 代码审查、GitOps 集成以及数据访问控制等。关键特性和核心…...

History对象常用方法

文章目录 一、什么是History对象二、使用History对象 一、什么是History对象 history 对象来保存浏览器历史记录信息&#xff0c;也就是用户访问的页面。浏览器的前进与后退功能本质上就是 history 的操作。history 对象记录了用户浏览过的页面&#xff0c;通过该对象提供的 A…...

修改源码,element的el-table合并,处理合并产生的hover样式问题

1、确认自己element-ui的版本号 2、此element-ui下的lib包是修改过hover样式的包,如何替换自己文件下的node_modules中的包 修改后将lib文件夹中文件替换你项目中/node_module/element-ui/Lib中的文件问题??如果替换开发环境中的node_module的包无法升级到测试环境,因为nod…...

IoT 物联网常用协议

物联网协议是指在物联网环境中用于设备间通信和数据传输的协议。根据不同的作用&#xff0c;物联网协议可分为传输协议、通信协议和行业协议。 传输协议&#xff1a;一般负责子网内设备间的组网及通信。例如 Wi-Fi、Ethernet、NFC、 Zigbee、Bluetooth、GPRS、3G/4G/5G等。这些…...

使用java备份和恢复SQLServer表数据

需求 近来工作中遇到一个问题&#xff0c;内网办公系统中的数据需要导出到外网中进行查询&#xff0c;外网的数据库中还有一些表存储外网的数据&#xff0c;因此无法使用全库备份恢复功能来满足需求。即只从内网数据库中导出若干表的内容至外网数据库的对应表。 其他解决方案…...

27 UVM queue

uvm_queue类构建一个动态队列&#xff0c;该队列将按需分配并通过引用传递。 uvm_queue类声明&#xff1a; class uvm_queue #( type T int ) extends uvm_object 1 uvm_queue class hierarchy 2 uvm_queue class Methods 3 UVM Queue Example 在下面的示例中&#xff0c;…...

聊聊自动化测试的分层实践

技术群里&#xff0c;有同学聊起了各自在实践自动化测试时遇到的各种问题&#xff0c;最典型的就是落地难度和投入产出比。毕竟在当前这个时间节点&#xff0c;单纯的技术实践如果不能带来实际可见的业务价值&#xff0c;确实很影响个人绩效和团队产出。 这篇文章&#xff0c;…...

LVS那点事

LVS 原理 IPVS LVS 的 IP 负载均衡技术是通过 IPVS 模块来实现的&#xff0c;IPVS 是 LVS 集群系统的核心软件&#xff0c;它的主要作用是&#xff1a;安装在 Director Server 上&#xff0c;同时在 Director Server 上虚拟出一个 IP 地址&#xff0c;用户必须通过这个虚拟的…...

2022-2023年度广东省职业院校学生专业技能大赛“软件测试”赛项接口测试训练题目

接口测试 新增接口脚本编写和执行测试,并执行脚本。 (1)商品单位添加接口描述如下: 接口功能:提供商品单位新增处理。 接口地址(根据实际系统IP及端口自行替换): http://XX.XX.XX.XX:XXXX/prod-api/manager/category/add。 请求方式:POST。 请求参数:...

[Python][LeetCode]28. 找出字符串中第一个匹配项的下标

给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。 示例 1&#xff1a; 输入&#xff1a;haystack &quo…...

Prometheus监控mysql

docker-compose.yml 创建mysql mkdir/data/mysql -pcat > /data/mysql/docker-compose.yml << EOF version: 3.1 services:db:image: mysql:8.0restart: alwayscontainer_name: mysqlenvironment:TZ: Asia/ShanghaiLANG: en_US.UTF-8MYSQL_ROOT_PASSWORD: 123456comm…...

骑砍战团MOD开发(30)-游戏大地图map.txt

骑砍1战团mod开发-大地图制作方法_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1rz4y1c7wH/ 一.骑砍游戏大地图 骑砍RTS视角游戏大地图 大地图静态模型(map.txt) 军团/城镇图标(module_parties.py). 骑砍大地图的战争迷雾和天气通过API进行管理和控制: # Weather-h…...

关于 bringup sensor 时,曝光时间异常的问题排查

1、问题背景 这两天在配置 sc223a 这颗 sensor 的驱动&#xff0c;按 datasheet 的要求配置 sensor 的曝光后&#xff0c;发现最大曝光时间增加了一倍&#xff0c; sensor setting 用的是30fps &#xff0c;理论上最大的绝对曝光时间应该是 33ms 才正确&#xff0c;但实际用 …...

linux用户态与内核态通过字符设备交互

linux用户态与内核态通过字符设备交互 简述 Linux设备分为三类&#xff0c;字符设备、块设备、网络接口设备。字符设备只能一个字节一个字节读取&#xff0c;常见外设基本都是字符设备。块设备一般用于存储设备&#xff0c;一块一块的读取。网络设备&#xff0c;Linux将对网络…...

如何高效查询文件:Linux 下的多种方法详解

如何高效查询文件&#xff1a;Linux 下的多种方法详解 在日常工作中&#xff0c;我们经常需要查找文件&#xff0c;无论是寻找特定的代码文件、配置文件还是其他文档。Linux 提供了多种强大的命令和工具&#xff0c;通过巧妙地使用管道符&#xff0c;我们可以将这些命令组合起来…...

记矩阵基础概念

转自up&#xff1a;Naruto_Qcsdn&#xff1a;三维空间几何变换矩阵 先贴个站里分享的基础概念。 learn form 肥猫同学VFX b站&#xff1a;会用transform就会用矩阵 移动 旋转 缩放 1.transofrm ——输出变化矩阵 可以移动transform查看变化去理解 位移 缩放 旋转 由此—…...

用html,js和layui写一个简单的点击打怪小游戏

介绍&#xff1a; 一个简单的打怪小游戏&#xff0c;点击开始游戏后&#xff0c;出现攻击按钮&#xff0c;击败怪物后可以选择继续下一关和结束游戏。 继续下一个怪兽的血量会增加5点&#xff0c;攻击按钮会随机变色。 效果图&#xff1a; html代码&#xff1a; <!DOCTYPE…...

[线代]不挂科猴博士

行列式的性质 行列式的计算及应用 矩阵的运算上(加减,相乘,取行列式) 矩阵的运算下(转置,逆,秩) 向量组与线性空间 解方程组...

扩散式过滤器 水泵角通除污器 0阻力过滤器直角过滤器工作原理

​ 1&#xff1a;扩散式除污器过滤器介绍 扩散除污器是一种在多个领域都有应用的设备&#xff0c;例如在泵站中用于拦截介质中的杂质&#xff0c;净化介质&#xff0c;保护管路&#xff0c;提高水泵效率&#xff0c;延长水泵寿命等。它还可以方便地进行变径处理&#xff0c;可以…...

MetalLB:本地Kubernetes集群的LoadBalancer负载均衡利器

背景 在本地集群进行测试时&#xff0c;我们常常面临一个棘手的问题&#xff1a;Service Type不支持LoadBalancer&#xff0c;而我们只能选择使用NodePort作为替代。这种情况下&#xff0c;我们通常会配置Service为NodePort&#xff0c;并使用externalIPs将流量导入Kubernetes…...

C++判定终端ip和目标ip是否在同一局域网内

程序如下&#xff1a;用于判断给定的终端 IP、子网掩码和目标 IP 是否在同一局域网内。请注意&#xff0c;这个程序假设 IP 地址是用整数表示的。 #include <iostream> #include <sstream> #include <vector> #include <bitset>// Function to check …...

深入解析 可空值类型

前言&#xff1a; 问&#xff1a;为什么会有可空值类型的诞生&#xff1f; 答&#xff1a;应对在某些特定场景中获取的信息可能是不完整的。 C# 1中的可空值类型 在C#1中没有对应的表示Null值的方法。当时普遍都是采用其他方式。第一种在数据缺失的情况下给其一个默认值。第…...

esp32idf使用thingscloud例程

对于不同的消息类型&#xff0c;API 如下&#xff1a; 消息类型 HTTP Method HTTP URL 设备上报属性 POST /device/v1//attributes 设备获取属性 GET /device/v1//attributes 设备上报事件 POST /device/v1//event/report 您只需要将以上的 HTTP URL 和接入点拼接即可获得最终…...

记一次应急响应练习(Linux)

记一次应急响应练习(Linux) Linux&#xff1a; 请提交攻击者的IP地址 答&#xff1a; 192.168.31.132 思路&#xff1a; 通过查看历史命令和开放的8080端口看到这台主机上运行的是Tomcat服务。并且在历史命令中看到了Tomcat的安装路径。那么就算是找到了日志的查看点了&#x…...

Pandas教程(四)—— 分层索引及数据联合

1.分层索引 分层索引就是在一个轴上拥有多个&#xff08;两个及以上&#xff09;索引级别&#xff0c;能以低维度形式处理高维度数据。 行索引有两层 1.1 分层索引的创建 1.1.1 方式一&#xff1a;直接设置 1&#xff09;在创建series、dataframe或读取文件时时&#xff0c;行…...

小梅哥Xilinx FPGA学习笔记16——FSM(状态机)的学习

目录 一、 状态机导读 1.1 理论学习 1.2 状态机的表示 1.3 状态机编码 1.4 状态机描述方式 二 、实战演练一&#xff08;来自野火&#xff09; 2.1 实验目标 2.2 模块框图 2.3 状态转移图绘制 2.4 设计文件 2.5 仿真测试文件 2.6 仿真结果 三、 实战演练二&…...

vol----学习随记!!!

目录 一、代码生成1.先新建一个功能的对应的代码配置各项解释&#xff1a; 2.后设置配置菜单3.再点保存&#xff0c;生成vue页面&#xff0c;生成model&#xff0c;生成业务类4.再通过菜单设置编写系统菜单 一、代码生成 1.先新建一个功能的对应的代码配置 各项解释&#xff…...

HarmonyOS4.0系统性深入开发10卡片事件能力说明

卡片事件能力说明 ArkTS卡片中提供了postCardAction()接口用于卡片内部和提供方应用间的交互&#xff0c;当前支持router、message和call三种类型的事件&#xff0c;仅在卡片中可以调用。 接口定义&#xff1a;postCardAction(component: Object, action: Object): void 接口…...

openGauss学习笔记-181 openGauss 数据库运维-升级-升级流程

文章目录 openGauss学习笔记-181 openGauss 数据库运维-升级-升级流程 openGauss学习笔记-181 openGauss 数据库运维-升级-升级流程 本章介绍升级到该版本的主要升级过程。 图 1 升级流程图 说明&#xff1a; 本文档中描述的时间仅供参考&#xff0c;实际操作时间以现场情况…...

提前应对威胁

通过新的《2023-2028 年荷兰国际网络安全战略》&#xff0c;荷兰政府在面对国家和犯罪分子持续构成的网络威胁时展现了责任和机构。它渴望将民主、人权和规范放在首位&#xff0c;并寻求维护全球开放、自由和安全的互联网。该战略明确了政府在国内实施打击的意愿和能力&#xf…...

C语言与人生:数组交换和二分查找

少年们&#xff0c;大家好。我是博主那一脸阳光&#xff0c;今天和分享数组交换和二分查找。 前言&#xff1a;探索C语言中的数组交换操作与二分查找算法 在计算机编程领域&#xff0c;特别是以C语言为代表的低级编程语言中&#xff0c;对数据结构的理解和熟练运用是至关重要的…...

Python实现【亚马逊商品】数据采集

前言 亚马逊公司&#xff0c;是美国最大的一家网络电子商务公司&#xff0c;位于华盛顿州的西雅图 是网络上最早开始经营电子商务的公司之一&#xff0c;亚马逊成立于1994年 今天教大家用Python批量采集亚马逊平台商品数据&#xff08;完整代码放在文末&#xff09; 地址&#…...

Git使用教程 gittutorial

该教程对该文章的翻译&#xff1a;https://git-scm.com/docs/gittutorial 本文介绍怎用使用 Git 导入新的工程、修改文件及如何其他人同步开发。 首先&#xff0c; 可以使用以下指令获取文档帮助 git help log笔者注&#xff1a;不建议看这个文档&#xff0c;标准的语法介绍…...

有了向量数据库,我们还需 SQL 数据库吗?

“除了向量数据库外&#xff0c;我是否还需要一个普通的 SQL 数据库&#xff1f;” 这是我们经常被问到的一个问题。如果除了向量数据以外&#xff0c;用户还有其他标量数据信息&#xff0c;那么其业务可能需要在进行语义相似性搜索前先根据某种条件过滤数据&#xff0c;例如&a…...

信息网络协议基础-IPv6协议

文章目录 概述为什么引入IP服务模型IPv4的可扩展性问题解决方法***CIDR(Classless Inter-Domain Routing, 无类别域间寻路)前缀汇聚***前缀最长匹配***NAT(网络地址转换)存在的问题解决方案路由表配置***局限性IPv6协议头标IPv6地址表示前缀类型单播地址链路局部地址(Link-Loca…...

VC++ ado 实现单表CURD

继续修改前文的资产管理源码; 新建一个数据库sds;把代码中的数据库连接改为连接此库; 新建下图一个表; 把之前的资产类别管理对话框改为下图所示;对话框ID也改为下图; 资产类别管理菜单和ID改为下图; 直接修改资产类别管理对话框类不太方便,新建一个对话框类,没有关联…...

C#使用switch多路选择语句判断何为季节

目录 一、 switch语句 二、示例 三、生成 一、 switch语句 switch语句是多路选择语句&#xff0c;它通过一个表达式的值来使程序从多个分支中选取一个用于执行的分支。 switch表达式的值只可以是整型、字符串、枚举和布尔类型。 switch语句中多个case可以使用一个break。 在…...