依赖nacos实例动态创建线程池并监听服务上下线

版本

  • Spring Booot 版本 3.2.4
  • Spring Cloud 版本 2023.0.1
  • Spring Cloud Alibaba 版本 2023.0.1.2

依赖

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>

配置文件

  • bootstrap.yml配置
spring:application:name: ${app_name:${APP_NAME:demo}} cloud:nacos:username: ${config_username:${CONFIG_USERNAME:nacos}}password: ${config_password:${CONFIG_PASSWORD:nacos}}discovery:server-addr: ${config_server_uri:${CONFIG_SERVER_URI:10.244.36.167:8848}}namespace: ${config_profiles_active:${CONFIG_PROFILES_ACTIVE:dev}}group: ${config_group:${CONFIG_GROUP:demo}}service: ${spring.application.name}config:server-addr: ${config_server_uri:${CONFIG_SERVER_URI:10.244.36.167:8848}}namespace: ${config_profiles_active:${CONFIG_PROFILES_ACTIVE:dev}}group: ${config_group:${CONFIG_GROUP:demo}}file-extension: ymlrefresh-enabled: true # 开启配置自动刷新,默认开启,此处显示声明
  •  application-dev.yml配置
thread-pool:core-size: 2          # 核心线程数max-size: 2           # 最大线程数queue-capacity: 100   # 队列容量keep-alive-time: 60   # 空闲线程存活时间(秒)

配置类

  • NacosThreadPoolProperties
package com.xxx.xxx.amedia.media.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;/*** nacos 线程池配置类* @author xxx* @date 2025-5-23 13:54:21*/
@Data
@Configuration
@ConfigurationProperties(prefix = "thread-pool")
public class NacosThreadPoolProperties {/*** 核心线程数*/private int coreSize;/*** 最大线程数*/private int maxSize;/*** 队列容量*/private int queueCapacity;/*** 空闲线程活跃时间*/private int keepAliveTime;
}

  • NacosDiscoveryProperties
package com.xxx.xxx.amedia.media.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;/*** nacos discovery 配置类* @author xxx* @date 2025-5-23 13:54:21*/
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.cloud.nacos.discovery")
public class NacosDiscoveryProperties {/*** nacos服务地址*/private String serverAddr;/*** 命名空间*/private String namespace;/*** 分组*/private String group;
}
  • NacosTokenProperties
package com.xxx.xxx.amedia.media.properties;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;/*** nacos 线程池配置类* @author xxx* @date 2025-5-23 13:54:21*/
@Data
@Configuration
@ConfigurationProperties(prefix = "spring.cloud.nacos")
public class NacosTokenProperties {/*** 用户名*/private String username;/*** 密码*/private String password;
}

常量类

package com.xxx.xxx.amedia.media.constant;/*** nacos 常量类* @author xxx* @date 2025-5-26 10:07:23*/
public final class NacosConstants {private NacosConstants() {}/*** nacos配置 username*/public static final String USERNAME = "username";/*** nacos配置 password*/public static final String PASSWORD = "password";/*** nacos配置 server-addr*/public static final String SERVER_ADDR = "serverAddr";/*** nacos配置 namespace*/public static final String NAMESPACE = "namespace";/*** nacos配置 group*/public static final String GROUP = "group";}

nacos 核心类 NamingService 配置

package com.xxx.amedia.media.config;import com.xxx.amedia.media.constant.NacosConstants;
import com.xxx.amedia.media.properties.NacosDiscoveryProperties;
import com.xxx.amedia.media.properties.NacosTokenProperties;import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Properties;/*** nacos 核心类 NamingService 配置* @author xxx* @date 2025-5-23 15:18:24*/
@Configuration
public class NamingServiceConfig {@Autowiredprivate NacosTokenProperties nacosTokenProperties;@Autowiredprivate NacosDiscoveryProperties nacosDiscoveryProperties;@Beanpublic NamingService namingService() throws NacosException {Properties properties = new Properties();// nacos 服务器地址properties.put(NacosConstants.SERVER_ADDR, nacosDiscoveryProperties.getServerAddr());// 命名空间properties.put(NacosConstants.NAMESPACE, nacosDiscoveryProperties.getNamespace());properties.put(NacosConstants.GROUP, nacosDiscoveryProperties.getGroup());properties.put(NacosConstants.USERNAME, nacosTokenProperties.getUsername());properties.put(NacosConstants.PASSWORD, nacosTokenProperties.getPassword());return NacosFactory.createNamingService(properties);}
}

 nacos实例 线程池管理类

package com.xxx.amedia.media.manager;import com.xxx.amedia.media.properties.NacosDiscoveryProperties;
import com.xxx.amedia.media.properties.NacosThreadPoolProperties;
import com.xxx.amedia.rpc.config.MediaRpcProperties;import cn.hutool.core.thread.ThreadFactoryBuilder;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.Instance;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;/*** nacos实例 线程池管理类* @author xxx* @date 2025-5-23 10:30:21*/
@Slf4j
@Component
public class NacosThreadPoolManager {@Autowiredprivate MediaRpcProperties mediaRpcProperties;@Autowiredprivate NacosDiscoveryProperties nacosDiscoveryProperties;@Autowiredprivate NacosThreadPoolProperties nacosThreadPoolConfig;/*** 订阅服务上线和下线事件*/@Autowiredprivate NamingService namingService;/*** 存储 IP 和线程池的映射关系*/private final Map<String, ThreadPoolExecutor> ipThreadPoolMap = new ConcurrentHashMap<>();@PostConstructpublic void init() {// 注册监听器registerServiceListener(mediaRpcProperties.getServiceName());}/*** 注册服务监听器,监听指定服务的实例变化** @param serviceName 服务名称*/private void registerServiceListener(String serviceName) {try {namingService.subscribe(serviceName, nacosDiscoveryProperties.getGroup(), event -> {if (event instanceof NamingEvent namingEvent) {String serviceNameFromEvent = namingEvent.getServiceName();if (StringUtils.equals(serviceNameFromEvent, serviceName)) {handleInstanceChange(namingEvent);}}});} catch (NacosException ex) {// 处理异常,例如记录日志log.error("Register service listener occur exception.", ex);}}/*** 处理实例变化事件* @param event NamingEvent*/private void handleInstanceChange(NamingEvent event) {// 获取当前所有实例的 IPSet<String> currentIps = event.getInstances().stream().map(Instance::getIp).collect(Collectors.toSet());// 处理实例变化事件handleInstanceChange(currentIps);}/*** 处理实例变化事件* @param currentIps 当前所有实例的 IP*/private void handleInstanceChange(Set<String> currentIps) {// 旧实例IP集合Set<String> previousIps = new HashSet<>(ipThreadPoolMap.keySet());// 新增的 IPSet<String> newIps = new HashSet<>(currentIps);newIps.removeAll(previousIps);// 移除的 IPSet<String> removedIps = new HashSet<>(previousIps);removedIps.removeAll(currentIps);// 对新增的 IP 创建线程池for (String ip : newIps) {createThreadPoolForIp(ip);}// 对移除的 IP 销毁线程池for (String ip : removedIps) {destroyThreadPoolForIp(ip);}}/*** 创建指定 IP 的线程池* @param ip 实例 IP*/public ThreadPoolExecutor createThreadPoolForIp(String ip) {// ThreadFactoryBuilder 设置线程名称ThreadFactory customThreadFactory = new ThreadFactoryBuilder().setNamePrefix("nacos-pool-" + ip + "-thread-%d").setDaemon(false).setPriority(Thread.NORM_PRIORITY).build();// 创建线程池,超出队列长度由调用者执行ThreadPoolExecutor executor = new ThreadPoolExecutor(nacosThreadPoolConfig.getCoreSize(),nacosThreadPoolConfig.getMaxSize(),nacosThreadPoolConfig.getKeepAliveTime(),TimeUnit.SECONDS,new LinkedBlockingQueue<>(nacosThreadPoolConfig.getQueueCapacity()),customThreadFactory,new ThreadPoolExecutor.CallerRunsPolicy());log.info("Created thread pool for IP: {}", ip);ipThreadPoolMap.put(ip, executor);return executor;}/*** 销毁指定 IP 的线程池* @param ip 实例 IP*/private void destroyThreadPoolForIp(String ip) {ThreadPoolExecutor executor = ipThreadPoolMap.remove(ip);if (executor == null) {return;}executor.shutdown(); // 关闭线程池,不再接受新任务try {if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {executor.shutdownNow(); // 强制关闭}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}log.info("Destroyed thread pool for IP: {}", ip);}/*** 获取指定 IP 的线程池* @param ip 实例 IP* @return 对应的线程池,如果不存在则返回 null*/public ThreadPoolExecutor getThreadPoolForIp(String ip) {ThreadPoolExecutor executor = ipThreadPoolMap.get(ip);// 获取不到线程池手动创建if (executor == null) {executor = createThreadPoolForIp(ip);}return executor;}/*** 应用关闭时销毁所有线程池*/@PreDestroypublic void shutdownAllThreadPools() {for (Map.Entry<String, ThreadPoolExecutor> entry : ipThreadPoolMap.entrySet()) {String ip = entry.getKey();ThreadPoolExecutor executor = entry.getValue();executor.shutdown();try {if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}}ipThreadPoolMap.clear();log.info("succeed shutdown all thread pools.");}/*** 每分钟监控一次线程池的状态*/@Scheduled(fixedRate = 60000)public void monitorThreadPool() {for (Map.Entry<String, ThreadPoolExecutor> entry : ipThreadPoolMap.entrySet()) {String ip = entry.getKey();ThreadPoolExecutor executor = entry.getValue();log.info("Monitor thread pool. ip: {}, Active Threads: {}, Queue Size: {}",ip,executor.getActiveCount(),executor.getQueue().size());}}
}

执行线程任务 管理类 

package com.xxx.amedia.media.manager;import com.xxx.amedia.media.bo.FailureTaskBO;
import com.xxx.amedia.rpc.enums.RpcTypeEnum;
import com.xxx.amedia.rpc.model.RpcReloadResponse;
import com.xxx.amedia.rpc.proxy.RpcReloadProxy;
import com.xxx.amedia.system.api.NacosService;import cn.hutool.core.lang.Pair;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;/*** 执行线程任务 管理类* @author xxx* @date 2025-5-23 11:01:07*/
@Slf4j
@Service
public class RpcReloadManager {@Autowiredprivate NacosService nacosService;@Autowiredprivate RpcReloadProxy rpcReloadProxy;@Autowiredprivate NacosThreadPoolManager threadPoolManager;/*** 异步执行任务  所有节点  无参* @param rpcTypeEnum rpc类型枚举* @return 失败节点列表*/public List<FailureTaskBO> execute(RpcTypeEnum rpcTypeEnum) {return execute(rpcTypeEnum, Collections.emptyList());}/*** 异步执行任务  所有节点  无参* @param rpcTypeEnum rpc类型枚举* @param params rpc接口参数* @return 失败节点列表*/public List<FailureTaskBO> execute(RpcTypeEnum rpcTypeEnum, Object params) {List<String> ips = nacosService.getInstanceIps();List<FailureTaskBO> failureList = new ArrayList<>();if (CollectionUtils.isEmpty(ips)) {return failureList;}CountDownLatch countDownLatch = new CountDownLatch(ips.size());ips.forEach(execNodeIp -> {try {execute(execNodeIp, rpcTypeEnum, params, failureList);} catch (Exception ex) {FailureTaskBO failureTaskBO = FailureTaskBO.builder().ip(execNodeIp).code(500).msg("rpc任务执行失败").build();failureList.add(failureTaskBO);log.error("execute task occur exception: ip is {}, rpcTypeEnum is {}, msg is {}.", execNodeIp, rpcTypeEnum, ex.getMessage(), ex);} finally {countDownLatch.countDown();}});try {// 主线程等待所有任务完成countDownLatch.await();} catch (InterruptedException e) {// 恢复中断状态interrupt();}return failureList;}/*** 异步执行任务  指定节点列表* @param rpcTypeEnum rpc类型枚举* @param ips 指定节点列表* @return 失败节点列表*/public List<FailureTaskBO> executeForIps(RpcTypeEnum rpcTypeEnum, List<String> ips) {return executeForIps(rpcTypeEnum, ips, Collections.emptyList());}/*** 异步执行任务  指定节点列表* @param rpcTypeEnum rpc类型枚举* @param ips 指定节点列表* @param params rpc接口参数* @return 失败节点列表*/public List<FailureTaskBO> executeForIps( RpcTypeEnum rpcTypeEnum, List<String> ips, Object params) {List<FailureTaskBO> failureList = new ArrayList<>();if (CollectionUtils.isEmpty(ips)) {return failureList;}CountDownLatch countDownLatch = new CountDownLatch(ips.size());ips.forEach(execNodeIp -> {try {execute(execNodeIp, rpcTypeEnum, params, failureList);} catch (Exception ex) {FailureTaskBO failureTaskBO = FailureTaskBO.builder().ip(execNodeIp).code(500).msg("rpc reload error").build();failureList.add(failureTaskBO);log.error("execute task occur exception: ip is {}, rpcTypeEnum is {}, msg is {}.", execNodeIp, rpcTypeEnum, ex.getMessage(), ex);} finally {countDownLatch.countDown();}});try {// 主线程等待所有任务完成countDownLatch.await();} catch (InterruptedException e) {// 恢复中断状态interrupt();}return failureList;}/*** 恢复中断状态*/private void interrupt() {// 恢复中断状态Thread.currentThread().interrupt();log.info("Thread {} is interrupted.", Thread.currentThread().getName());}/*** 异步线程池执行rpc任务* @param execNodeIp 执行节点IP* @param rpcTypeEnum rpc类型枚举* @param failureList 失败节点信息* @throws ExecutionException 执行异常* @throws InterruptedException 中断异常*/private void execute(String execNodeIp, RpcTypeEnum rpcTypeEnum, Object params, List<FailureTaskBO> failureList)throws ExecutionException, InterruptedException {ThreadPoolExecutor executor = threadPoolManager.getThreadPoolForIp(execNodeIp);FutureTask<Pair<Boolean, RpcReloadResponse>> futureTask = new FutureTask<>(() -> {return rpcReloadProxy.reload(execNodeIp, rpcTypeEnum, params);});executor.submit(futureTask);Pair<Boolean, RpcReloadResponse> pair = futureTask.get();if (!pair.getKey()) {FailureTaskBO failureTaskBO = bulidFailureTaskBO(pair, execNodeIp);failureList.add(failureTaskBO);}}/*** 构建失败信息* @param pair rpc响应信息* @param execNodeIp 执行节点IP* @return FailureTaskBO*/private FailureTaskBO bulidFailureTaskBO(Pair<Boolean, RpcReloadResponse> pair, String execNodeIp) {RpcReloadResponse res = pair.getValue();FailureTaskBO failureTaskBO;if (res == null) {failureTaskBO = FailureTaskBO.builder().ip(execNodeIp).code(500).msg("rpc reload error").build();} else {failureTaskBO = FailureTaskBO.builder().ip(execNodeIp).code(res.getCode()).msg(res.getMsg()).build();}return failureTaskBO;}
}

nacos服务实例service类

package com.xxx.amedia.system.api;import com.xxx.amedia.system.converter.ServiceInstanceConverter;
import com.xxx.amedia.system.vo.ServiceInstanceVO;
import com.xxx.amedia.tool.common.constants.CommonConstants;import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;/*** nacos服务实例service类* @author xxx* @date 2025-5-17 11:38:22*/
@Service
public class NacosService{@Value("${media.rpc.service-name}")private String serviceName;@Autowiredprivate DiscoveryClient discoveryClient;@Autowiredprivate ServiceInstanceConverter serviceInstanceConverter;@Overridepublic List<ServiceInstanceVO> list() {List<ServiceInstance> serviceInstances = getInstances();return serviceInstanceConverter.toServiceInstanceVOList(serviceInstances);}/*** 从nacos获取指定服务名的实例IP集合* @return 实例IP集合*/@Overridepublic List<String> getInstanceIps() {List<ServiceInstance> instances = getInstances();if (CollectionUtils.isEmpty(instances)) {return Collections.emptyList();}List<String> instanceIps = new ArrayList<>(instances.size());instances.forEach(instance -> {instanceIps.add(instance.getHost());});return instanceIps;}/*** 检查icc-amedia-admin服务中是否存在指定 IP 的节点* @param instanceIps 获取 icc-amedia-rpc 服务的所有实例Ip* @param targetIp 目标 IP(如 10.199.1.1)* @return true 存在 / false 不存在*/@Overridepublic boolean checkNodeExists(List<String> instanceIps, String targetIp) {// 遍历实例,检查 IPfor (String instanceIp : instanceIps) {if (StringUtils.equals(targetIp, instanceIp)) {return true;}}return false;}/*** 从nacos获取指定服务名的实例集合* @return 实例集合*/private List<ServiceInstance> getInstances() {List<ServiceInstance> serviceInstances = discoveryClient.getInstances(serviceName);// 按host升序排列serviceInstances.sort(Comparator.comparing(ServiceInstance::getHost));return serviceInstances;}}

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

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

相关文章

全面指南:使用Node.js和Python连接与操作MongoDB

在现代Web开发中&#xff0c;数据库是存储和管理数据的核心组件。MongoDB作为一款流行的NoSQL数据库&#xff0c;以其灵活的数据模型、高性能和易扩展性广受开发者欢迎。无论是使用Node.js还是Python&#xff0c;MongoDB都提供了强大的官方驱动和第三方库&#xff0c;使得数据库…

LeetCode 3068.最大节点价值之和:脑筋急转弯+动态规划(O(1)空间)

【LetMeFly】3068.最大节点价值之和&#xff1a;脑筋急转弯动态规划&#xff08;O(1)空间&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/find-the-maximum-sum-of-node-values/ 给你一棵 n 个节点的 无向 树&#xff0c;节点从 0 到 n - 1 编号。树以长…

HTTPS加密通信详解及在Spring Boot中的实现

HTTPS&#xff08;Hyper Text Transfer Protocol Secure&#xff09;是HTTP的安全版本&#xff0c;通过SSL/TLS协议为通讯提供加密、身份验证和数据完整性保护。 一、HTTPS核心原理 1.加密流程概述 客户端发起HTTPS请求&#xff08;连接到服务器443端口&#xff09;服务器返…

解决线程安全问题

前言 昨天学习了如何去解决线程不安全的问题。一般方法都是通过加锁来处理&#xff0c;跟大家分享一波 。 解决线程安全问题 结语 希望可以帮助到大家~ byebye

网络常识:网线和光纤的区别

网络常识&#xff1a;网线和光纤的区别 一. 介绍二. 网线2.1 什么是网线&#xff1f;2.2 网线的主要类别2.3 网线的优势2.4 网线的劣势 三. 光纤3.1 什么是光纤&#xff1f;3.2 光纤的主要类别3.3 光纤的优势3.4 光纤的劣势 四. 网线 vs 光纤&#xff1a;谁更适合你&#xff1f…

win11 禁用/恢复 内置笔记本键盘(保证管用)

文章目录 禁用启用 禁用 1&#xff09;按下 win x&#xff0c;点击 设备管理器 2&#xff09;拔掉所有笔记本外设&#xff08;一定要都拔掉&#xff0c;不然后面禁用设备会混淆&#xff09;&#xff0c;然后右键点击 键盘 > HID Keyboard Device 2&#xff09;点击 更新…

Three.js搭建小米SU7三维汽车实战(5)su7登场

汽车模型加载 我们在sktechfab上下载的汽车是glb的文件格式&#xff0c;所以使用gltfLoader进行加载。这里将小车直接加载进来看看效果&#xff1b; import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js"; ....其余代码省略 const gltfLoader new GLT…

ETL怎么实现多流自定义合并?

随着信息技术的迅猛发展以及数据生成环境的多样化&#xff0c;互联网、物联网和社交媒体的广泛应用导致各种设备和平台不断产生大量数据&#xff0c;需要整合这些数据&#xff0c;从而进行数据融合。数据集成和管理平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;…

数据结构- 10种常见树:二叉树、平衡二叉树、完全二叉树

一、树 树型结构是一类重要的非线性数据结构。其中以树和二叉树最为常用&#xff0c;直观看来&#xff0c;树是以分支关系定义的层次结构。把它叫做“树”是因为它常看起来像一棵倒挂的树&#xff0c;也就是说它常是根朝上&#xff0c;而叶朝下的。 1.树的定义&#xff1a; 树…

Java常用加密方式

一&#xff0c;加密算法分类 对称加密&#xff1a;指加密和解密的密钥相同&#xff0c;优点就是加解密的效率高且易于实现。 非对称加密&#xff1a;指加密和解密的密钥不相同&#xff0c;也称为公私要加密。 不可逆加密&#xff1a;特征就是加密过程不需要密钥&#xff0c;…

SQLite软件架构与实现源代码浅析

概述 SQLite 是一个用 C 语言编写的库&#xff0c;它成功打造出了一款小型、快速、独立、具备高可靠性且功能完备的 SQL 数据库引擎。本文档将为您简要介绍其架构、关键组件及其协同运作模式。 SQLite 显著特点之一是无服务器架构。不同于常规数据库&#xff0c;它并非以单独进…

让 Deepseek GPS测速

下面是一个简单的微信小程序GPS测速功能的实现代码&#xff0c;包括前端页面和后端逻辑。 1. 页面结构 (index.wxml) <view class"container"><view class"speed-display"><text class"speed-value">{{speed}}</text>…

什么是软件的生命周期,以及常见的开发测试模型

目录 一、软件的生命周期 1、什么是生命周期&#xff1f; 2、每个阶段都要做些什么&#xff1f; 二、常见的开发模型 1、瀑布模型 2、螺旋模型 3、增量模型、迭代模型 4、敏捷模型 scrum模型 三个角色 五个会议 一、软件的生命周期 1、什么是生命周期&#xff…

JWT安全:弱签名测试.【实现越权绕过.】

JWT安全&#xff1a;假密钥【签名随便写实现越权绕过.】 JSON Web 令牌 (JWT)是一种在系统之间发送加密签名 JSON 数据的标准化格式。理论上&#xff0c;它们可以包含任何类型的数据&#xff0c;但最常用于在身份验证、会话处理和访问控制机制中发送有关用户的信息(“声明”)。…

数据分析与应用-----使用scikit-learn构建模型

目录 一、使用sklearn转换器处理数据 &#xff08;一&#xff09;、加载datasets模块中的数据集 &#xff08;二&#xff09;、将数据集划分为训练集和测试集 ​编辑 train_test_spli &#xff08;三&#xff09;、使用sklearn转换器进行数据预处理与降维 PCA 二、 构…

【Tomcat】Tomcat端口仅允许本地访问设置方法

要设置Tomcat端口仅允许本地访问&#xff0c;可以通过以下两种主要方式实现&#xff1a; 方法一&#xff1a;修改Tomcat配置文件&#xff08;推荐&#xff09; 修改 server.xml 文件 打开Tomcat的配置文件 conf/server.xml&#xff0c;找到 <Connector> 标签&#xff08;…

arcgis字段计算器中计算矢量面的每个点坐标

python脚本 函数 def ExportCoordinates(feat):coors = []partnum = 0partcount = feat.partCountwhile partnum < partcount:part = feat.getPart(partnum)pnt = part.next()while pnt:coors.append("({}, {})".format(pnt.X,pnt.Y))pnt = part.next()if not p…

企业级AI开启落地战,得场景者得天下

文&#xff5c;白 鸽 编&#xff5c;王一粟 这两周&#xff0c;企业级智能体开发平台颇有你方唱罢我方登台的架势。 微软、腾讯、网易等国内外巨头&#xff0c;近期都相继宣布推出了新一代智能体开发平台。相比于两年前&#xff0c;智能体开发的产品逻辑已经有了翻天覆地的变…

探索C++标准模板库(STL):String接口实践+底层的模拟实现(中篇)

前引&#xff1a;上一篇文章小编已经整理出了String的常用接口&#xff0c;梳理了各个接口的功能、参数&#xff0c;如何使用等各种实例。本篇文章将带大家看看String这些接口的实践使用&#xff0c;探索这些接口的实用性&#xff0c;是如何增加代码效率的。在本篇文章的末尾&a…

【模型显著性分析】配对样本 t 检验

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言 t t t 检验配对样本 t t t 检验&#xff08;适用于相关组&#xff09;代码论文描…