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

Nacos源码—4.Nacos集群高可用分析四

大纲

6.CAP原则与Raft协议

7.Nacos实现的Raft协议是如何写入数据的

8.Nacos实现的Raft协议是如何选举Leader节点的

9.Nacos实现的Raft协议是如何同步数据的

10.Nacos如何实现Raft协议的简版总结

8.Nacos实现的Raft协议是如何选举Leader节点的

(1)初始化RaftCore实例时会开启两个异步任务

(2)选举Leader节点的MasterElection异步任务

(1)初始化RaftCore实例时会开启两个异步任务

在RaftCore的init()方法中,会开启两个异步任务。第一个异步任务的作用是选举Leader节点,第二个异步任务的作用是发送心跳同步数据。

@Deprecated
@DependsOn("ProtocolManager")
@Component
public class RaftCore implements Closeable {...//Init raft core.@PostConstructpublic void init() throws Exception {Loggers.RAFT.info("initializing Raft sub-system");final long start = System.currentTimeMillis();//从本地文件中加载数据raftStore.loadDatums(notifier, datums);setTerm(NumberUtils.toLong(raftStore.loadMeta().getProperty("term"), 0L));Loggers.RAFT.info("cache loaded, datum count: {}, current term: {}", datums.size(), peers.getTerm());initialized = true;Loggers.RAFT.info("finish to load data from disk, cost: {} ms.", (System.currentTimeMillis() - start));//开启一个异步任务选举Leader节点masterTask = GlobalExecutor.registerMasterElection(new MasterElection());//开启一个异步任务通过心跳同步数据heartbeatTask = GlobalExecutor.registerHeartbeat(new HeartBeat());versionJudgement.registerObserver(isAllNewVersion -> {stopWork = isAllNewVersion;if (stopWork) {try {shutdown();raftListener.removeOldRaftMetadata();} catch (NacosException e) {throw new NacosRuntimeException(NacosException.SERVER_ERROR, e);}}}, 100);//给NotifyCenter注册一个监听PersistentNotifierNotifyCenter.registerSubscriber(notifier);Loggers.RAFT.info("timer started: leader timeout ms: {}, heart-beat timeout ms: {}", GlobalExecutor.LEADER_TIMEOUT_MS, GlobalExecutor.HEARTBEAT_INTERVAL_MS);}...
}public class GlobalExecutor {//线程池的线程数是可用线程的一半private static final ScheduledExecutorService NAMING_TIMER_EXECUTOR =ExecutorFactory.Managed.newScheduledExecutorService(ClassUtils.getCanonicalName(NamingApp.class),Runtime.getRuntime().availableProcessors() * 2,new NameThreadFactory("com.alibaba.nacos.naming.timer"));...public static ScheduledFuture registerMasterElection(Runnable runnable) {//以固定的频率来执行某项任务,它不受任务执行时间的影响,到时间就会执行任务return NAMING_TIMER_EXECUTOR.scheduleAtFixedRate(runnable, 0, TICK_PERIOD_MS, TimeUnit.MILLISECONDS);}public static ScheduledFuture registerHeartbeat(Runnable runnable) {//以相对固定的频率来执行某项任务,即只有等这一次任务执行完了(不管执行了多长时间),才能执行下一次任务return NAMING_TIMER_EXECUTOR.scheduleWithFixedDelay(runnable, 0, TICK_PERIOD_MS, TimeUnit.MILLISECONDS);}...
}

(2)选举Leader节点的MasterElection异步任务

MasterElection的run()方法就体现了Raft协议进行Leader选举的第一步。即每个节点会进行休眠,如果时间没到则返回然后重新执行异步任务。等休眠时间到了才会调用MasterElection的sendVote()方法发起投票。

一旦执行MasterElection的sendVote()方法发起投票:会先把选举周期+1,然后投票给自己,接着修改节点状态为Candidate。做完这些准备工作后,才会以HTTP形式向其他节点发送投票请求。

其他节点返回投票信息时,会调用RaftPeerSet的decideLeader()方法处理。这个方法会处理其他节点返回的投票信息,具体逻辑如下:

首先用一个Map记录每个节点返回的投票信息,然后遍历这个Map去统计投票数量,最后比较当前节点的累计票数,是否已超过集群节点半数。如果超过,则把当前节点的状态修改为Leader。

@Deprecated
@DependsOn("ProtocolManager")
@Component
public class RaftCore implements Closeable {private RaftPeerSet peers;...public class MasterElection implements Runnable {@Overridepublic void run() {try {if (stopWork) {return;}if (!peers.isReady()) {return;}//随机休眠RaftPeer local = peers.local();local.leaderDueMs -= GlobalExecutor.TICK_PERIOD_MS;//休眠时间没到就直接返回if (local.leaderDueMs > 0) {return;}//reset timeoutlocal.resetLeaderDue();local.resetHeartbeatDue();//发起投票sendVote();} catch (Exception e) {Loggers.RAFT.warn("[RAFT] error while master election {}", e);}}private void sendVote() {RaftPeer local = peers.get(NetUtils.localServer());Loggers.RAFT.info("leader timeout, start voting,leader: {}, term: {}", JacksonUtils.toJson(getLeader()), local.term);peers.reset();//选举周期+1local.term.incrementAndGet();//投票给自己local.voteFor = local.ip;//自己成为候选者,设置当前节点状态为Candidate状态local.state = RaftPeer.State.CANDIDATE;Map<String, String> params = new HashMap<>(1);params.put("vote", JacksonUtils.toJson(local));//遍历其他集群节点for (final String server : peers.allServersWithoutMySelf()) {final String url = buildUrl(server, API_VOTE);try {//发送HTTP的投票请求HttpClient.asyncHttpPost(url, null, params, new Callback<String>() {@Overridepublic void onReceive(RestResult<String> result) {if (!result.ok()) {Loggers.RAFT.error("NACOS-RAFT vote failed: {}, url: {}", result.getCode(), url);return;}RaftPeer peer = JacksonUtils.toObj(result.getData(), RaftPeer.class);Loggers.RAFT.info("received approve from peer: {}", JacksonUtils.toJson(peer));//处理返回的投票结果peers.decideLeader(peer);}@Overridepublic void onError(Throwable throwable) {Loggers.RAFT.error("error while sending vote to server: {}", server, throwable);}@Overridepublic void onCancel() {}});} catch (Exception e) {Loggers.RAFT.warn("error while sending vote to server: {}", server);}}}}...
}@Deprecated
@Component
@DependsOn("ProtocolManager")
public class RaftPeerSet extends MemberChangeListener implements Closeable {private volatile Map<String, RaftPeer> peers = new HashMap<>(8);...//Calculate and decide which peer is leader. If has new peer has more than half vote, change leader to new peer.public RaftPeer decideLeader(RaftPeer candidate) {//记录本次投票结果peers.put(candidate.ip, candidate);SortedBag ips = new TreeBag();int maxApproveCount = 0;String maxApprovePeer = null;//统计累计票数for (RaftPeer peer : peers.values()) {if (StringUtils.isEmpty(peer.voteFor)) {continue;}ips.add(peer.voteFor);if (ips.getCount(peer.voteFor) > maxApproveCount) {maxApproveCount = ips.getCount(peer.voteFor);maxApprovePeer = peer.voteFor;}}//判断投票数量是否超过半数,如果已超半数则把自己节点的状态改为Leaderif (maxApproveCount >= majorityCount()) {RaftPeer peer = peers.get(maxApprovePeer);//设置当前节点的状态为Leader状态peer.state = RaftPeer.State.LEADER;if (!Objects.equals(leader, peer)) {leader = peer;ApplicationUtils.publishEvent(new LeaderElectFinishedEvent(this, leader, local()));Loggers.RAFT.info("{} has become the LEADER", leader.ip);}}return leader;}...
}

9.Nacos实现的Raft协议是如何同步数据的

(1)Leader节点如何发送心跳来同步数据

(2)Follower节点如何处理心跳来同步数据

(1)Leader节点如何发送心跳来同步数据

RaftCore的init()方法会开启另外一个异步任务HeartBeat。HeartBeat的run()方法会调用HeartBeat的sendBeat()方法来发送心跳请求。

其中只有Leader节点才会发送心跳请求。Leader在调用HeartBeat的sendBeat()方法发送心跳同步数据请求时,会将Instance的key作为心跳的参数发送给其他Follower节点。Follower节点接收到Leader的心跳请求后,会比较请求中的数据与自身数据的差异,如果存在差异则向Leader同步。

HeartBeat的sendBeat()方法主要包括三部分:

第一部分:判断当前节点是不是Leader,如果不是Leader则不能发送心跳。

第二部分:组装发送心跳包的参数。只会把datum.key放入进去,并不会把整个Instance信息传输过去。Follower节点拿到心跳包中的key之后,发现部分key在自身节点是不存在的,那么这时Follower节点就会根据这些key向Leader节点获取Instance的详细信息进行同步。

第三部分:向其他Follower节点发送心跳数据,是通过HTTP的方式来发起心跳请求的,请求地址为:/v1/ns/raft/beat。

@Deprecated
@DependsOn("ProtocolManager")
@Component
public class RaftCore implements Closeable {...public class HeartBeat implements Runnable {@Overridepublic void run() {try {if (stopWork) {return;}if (!peers.isReady()) {return;}RaftPeer local = peers.local();local.heartbeatDueMs -= GlobalExecutor.TICK_PERIOD_MS;if (local.heartbeatDueMs > 0) {return;}local.resetHeartbeatDue();//发送心跳同步数据sendBeat();} catch (Exception e) {Loggers.RAFT.warn("[RAFT] error while sending beat {}", e);}}private void sendBeat() throws IOException, InterruptedException {RaftPeer local = peers.local();//第一部分:判断当前节点是不是Leader,如果不是Leader则不能发送心跳if (EnvUtil.getStandaloneMode() || local.state != RaftPeer.State.LEADER) {return;}if (Loggers.RAFT.isDebugEnabled()) {Loggers.RAFT.debug("[RAFT] send beat with {} keys.", datums.size());}local.resetLeaderDue();//build dataObjectNode packet = JacksonUtils.createEmptyJsonNode();packet.replace("peer", JacksonUtils.transferToJsonNode(local));ArrayNode array = JacksonUtils.createEmptyArrayNode();if (switchDomain.isSendBeatOnly()) {Loggers.RAFT.info("[SEND-BEAT-ONLY] {}", switchDomain.isSendBeatOnly());}if (!switchDomain.isSendBeatOnly()) {//第二部分:组装发送心跳包的参数//组装数据,只会把datum.key放入进去,并不会把整个Instance信息传输过去for (Datum datum : datums.values()) {ObjectNode element = JacksonUtils.createEmptyJsonNode();if (KeyBuilder.matchServiceMetaKey(datum.key)) {//只放入key的信息element.put("key", KeyBuilder.briefServiceMetaKey(datum.key));} else if (KeyBuilder.matchInstanceListKey(datum.key)) {element.put("key", KeyBuilder.briefInstanceListkey(datum.key));}element.put("timestamp", datum.timestamp.get());array.add(element);}}packet.replace("datums", array);//broadcastMap<String, String> params = new HashMap<String, String>(1);params.put("beat", JacksonUtils.toJson(packet));String content = JacksonUtils.toJson(params);        ByteArrayOutputStream out = new ByteArrayOutputStream();GZIPOutputStream gzip = new GZIPOutputStream(out);gzip.write(content.getBytes(StandardCharsets.UTF_8));gzip.close();byte[] compressedBytes = out.toByteArray();String compressedContent = new String(compressedBytes, StandardCharsets.UTF_8);if (Loggers.RAFT.isDebugEnabled()) {Loggers.RAFT.debug("raw beat data size: {}, size of compressed data: {}", content.length(), compressedContent.length());}//第三部分:向其他Follower节点发送心跳数据,通过HTTP的方式来发起心跳,请求地址为:/v1/ns/raft/beat//发送心跳 + 同步数据for (final String server : peers.allServersWithoutMySelf()) {try {final String url = buildUrl(server, API_BEAT);if (Loggers.RAFT.isDebugEnabled()) {Loggers.RAFT.debug("send beat to server " + server);}//通过HTTP发送心跳HttpClient.asyncHttpPostLarge(url, null, compressedBytes, new Callback<String>() {@Overridepublic void onReceive(RestResult<String> result) {if (!result.ok()) {Loggers.RAFT.error("NACOS-RAFT beat failed: {}, peer: {}", result.getCode(), server);MetricsMonitor.getLeaderSendBeatFailedException().increment();return;}peers.update(JacksonUtils.toObj(result.getData(), RaftPeer.class));if (Loggers.RAFT.isDebugEnabled()) {Loggers.RAFT.debug("receive beat response from: {}", url);}}@Overridepublic void onError(Throwable throwable) {Loggers.RAFT.error("NACOS-RAFT error while sending heart-beat to peer: {} {}", server, throwable);MetricsMonitor.getLeaderSendBeatFailedException().increment();}@Overridepublic void onCancel() {}});} catch (Exception e) {Loggers.RAFT.error("error while sending heart-beat to peer: {} {}", server, e);MetricsMonitor.getLeaderSendBeatFailedException().increment();}}}}...
}

(2)Follower节点如何处理心跳来同步数据

Follower节点收到Leader节点发送过来的HTTP请求"/v1/ns/raft/beat"时,会执行RaftController类中的beat()方法,接着会执行RaftCore的receivedBeat()方法来进行具体的心跳处理。

RaftCore.receivedBeat()方法的具体逻辑如下:

一.首先会进行一些判断

第一个判断:Follower节点接收到的心跳请求如果不是Leader节点发出的会直接抛出异常。

第二个判断:Follower节点的term只会小于等于Leader节点的term,如果大于,则直接抛出异常。

第三个判断:如果自身节点的状态不是Follower,需要把状态改为Follower。因为有可能自身节点之前是Leader,但因为网络原因出现了脑裂问题。等网络恢复后,自身节点收到新Leader发来的心跳,新Leader的term比自身节点要大,那么它就需要切换成Follower节点。

二.然后对自身节点的datums中的key和心跳请求中的key进行比对

如果发现自身节点数据缺少了,那么就会记录到batch中,然后把batch中的key进行拆分包装成请求参数,最后通过HTTP方式向Leader节点查询这些key对应的Instance详细信息。

Follower节点拿到Leader节点返回的Instance服务实例信息后,会继续调用RaftStore.write()、PersistentNotifier.notify()这两个方法,一个将数据持久化到本地文件、一个将数据同步到内存注册表,从而最终完成以Leader节点为准的心跳请求同步数据的流程。

@Deprecated
@RestController
@RequestMapping({UtilsAndCommons.NACOS_NAMING_CONTEXT + "/raft", UtilsAndCommons.NACOS_SERVER_CONTEXT + UtilsAndCommons.NACOS_NAMING_CONTEXT + "/raft"})
public class RaftController {private final RaftCore raftCore;...@PostMapping("/beat")public JsonNode beat(HttpServletRequest request, HttpServletResponse response) throws Exception {if (versionJudgement.allMemberIsNewVersion()) {throw new IllegalStateException("old raft protocol already stop");}String entity = new String(IoUtils.tryDecompress(request.getInputStream()), StandardCharsets.UTF_8);String value = URLDecoder.decode(entity, "UTF-8");value = URLDecoder.decode(value, "UTF-8");JsonNode json = JacksonUtils.toObj(value);//处理心跳RaftPeer peer = raftCore.receivedBeat(JacksonUtils.toObj(json.get("beat").asText()));return JacksonUtils.transferToJsonNode(peer);}...
}@Deprecated
@DependsOn("ProtocolManager")
@Component
public class RaftCore implements Closeable {public final PersistentNotifier notifier;...//Received beat from leader. // TODO split method to multiple smaller method.public RaftPeer receivedBeat(JsonNode beat) throws Exception {...//第一个判断:如果发送心跳不是Leader,则直接抛出异常if (remote.state != RaftPeer.State.LEADER) {Loggers.RAFT.info("[RAFT] invalid state from master, state: {}, remote peer: {}", remote.state, JacksonUtils.toJson(remote));throw new IllegalArgumentException("invalid state from master, state: " + remote.state);}//第二个判断:如果本身节点的term还大于Leader的term,也直接抛出异常if (local.term.get() > remote.term.get()) {Loggers.RAFT.info("[RAFT] out of date beat, beat-from-term: {}, beat-to-term: {}, remote peer: {}, and leaderDueMs: {}", remote.term.get(), local.term.get(), JacksonUtils.toJson(remote), local.leaderDueMs);throw new IllegalArgumentException("out of date beat, beat-from-term: " + remote.term.get() + ", beat-to-term: " + local.term.get());}//第三个判断:自己的节点状态是不是FOLLOWER,如果不是则需要更改为FOLLOWERif (local.state != RaftPeer.State.FOLLOWER) {Loggers.RAFT.info("[RAFT] make remote as leader, remote peer: {}", JacksonUtils.toJson(remote));//mk followerlocal.state = RaftPeer.State.FOLLOWER;local.voteFor = remote.ip;}...//遍历Leader传输过来的Instance key,和本地的Instance进行对比for (Object object : beatDatums) {...try {if (datums.containsKey(datumKey) && datums.get(datumKey).timestamp.get() >= timestamp && processedCount < beatDatums.size()) {continue;}if (!(datums.containsKey(datumKey) && datums.get(datumKey).timestamp.get() >= timestamp)) {//记录需要同步的datumKeybatch.add(datumKey);}//到达一定数量才进行批量数据同步if (batch.size() < 50 && processedCount < beatDatums.size()) {continue;}...//使用batch组装参数String url = buildUrl(remote.ip, API_GET);Map<String, String> queryParam = new HashMap<>(1);queryParam.put("keys", URLEncoder.encode(keys, "UTF-8"));//发送HTTP请求给Leader,根据keys参数获取Instance详细信息HttpClient.asyncHttpGet(url, null, queryParam, new Callback<String>() {@Overridepublic void onReceive(RestResult<String> result) {if (!result.ok()) {return;}//序列化result结果List<JsonNode> datumList = JacksonUtils.toObj(result.getData(), new TypeReference<List<JsonNode>>() { });//遍历Leader返回的Instance详细信息for (JsonNode datumJson : datumList) {Datum newDatum = null;OPERATE_LOCK.lock();try {...//Raft写本地数据raftStore.write(newDatum);//同步内存数据datums.put(newDatum.key, newDatum);//和服务实例注册时的逻辑一样,最终会调用listener.onChange()方法notifier.notify(newDatum.key, DataOperation.CHANGE, newDatum.value);} catch (Throwable e) {Loggers.RAFT.error("[RAFT-BEAT] failed to sync datum from leader, datum: {}", newDatum, e);} finally {OPERATE_LOCK.unlock();}}...return;}...});batch.clear();} catch (Exception e) {Loggers.RAFT.error("[NACOS-RAFT] failed to handle beat entry, key: {}", datumKey);}}...}    ...
}

10.Nacos如何实现Raft协议的简版总结

Nacos实现的Raft协议主要包括三部分内容:

一.Nacos集群如何使用Raft协议写入数据

二.Nacos集群如何选举Leader节点

三.Nacos集群如何让Leader实现心跳请求同步数据

Nacos早期版本实现的只是Raft协议的简化版本,并没有两阶段提交的处理。而是Leader节点处理数据完成后,直接就去同步给其他集群节点。哪怕集群节点同步失败或没有过半节点成功,Leader的数据也不会回滚而只抛出异常。所以,Nacos早期版本的Raft实现,后期也会废弃使用。

如下是Nacos实现的Raft协议在注册服务实例时集群处理数据的流程:

如下是Nacos实现的Raft协议处理Leader选举和通过心跳同步数据的流程:

相关文章:

Nacos源码—4.Nacos集群高可用分析四

大纲 6.CAP原则与Raft协议 7.Nacos实现的Raft协议是如何写入数据的 8.Nacos实现的Raft协议是如何选举Leader节点的 9.Nacos实现的Raft协议是如何同步数据的 10.Nacos如何实现Raft协议的简版总结 8.Nacos实现的Raft协议是如何选举Leader节点的 (1)初始化RaftCore实例时会开…...

互联网大厂Java求职面试:AI与云原生下的系统设计挑战-3

互联网大厂Java求职面试&#xff1a;AI与云原生下的系统设计挑战-3 第一轮提问&#xff1a;从电商场景切入&#xff0c;聚焦分布式事务与库存一致性 面试官&#xff08;严肃&#xff09;&#xff1a;郑薪苦&#xff0c;你最近在做电商系统的促销活动&#xff0c;如何处理分布…...

【KWDB创作者计划】_通过一篇文章了解什么是 KWDB(KaiwuDB)

文章目录 &#x1f4cb; 前言&#x1f3af; 关于 KaiwuDB 组成&#x1f3af; KaiwuDB 核心架构和功能图&#x1f9e9; KaiwuDB 2.0 版本核心特性&#x1f9e9; KaiwuDB Lite 版本介绍 &#x1f3af; KaiwuDB 产品优势&#x1f3af; KaiwuDB 应用场景&#x1f9e9; 典型应用场景…...

双系统电脑中如何把ubuntu装进外接移动固态硬盘

电脑&#xff1a;win11 ubuntu22.04 实体机 虚拟机&#xff1a;VMware17 镜像文件&#xff1a;ubuntu-22.04.4-desktop-amd64.iso 或者 ubuntu20.4的镜像 外接固态硬盘1个 一、首先win11中安装vmware17 具体安装方法&#xff0c;网上很多教程 二、磁盘分区 1.在笔…...

Flink + Kafka 构建实时指标体系的实战方法论

本文聚焦于如何利用 Flink 与 Kafka 构建一套灵活、可扩展的实时指标体系,特别适用于用户行为分析、营销漏斗转化、业务实时看板等场景。 一、为什么要构建实时指标体系? 在数字化运营趋势下,分钟级指标反馈能力变得尤为重要: ✅ 营销投放实时监控 CTR / CVR ✅ 业务增长实…...

RLOO:将多次其他回答的平均reward作为baseline

RLOO&#xff1a;将多次其他回答的平均reward作为baseline TL; DR&#xff1a;基于 REINFROCE 算法&#xff0c;对于同一 prompt 在线采样 k k k 次&#xff0c;取除自己外的其他 k − 1 k-1 k−1 条回答的平均 reward 作为 baseline。 从 PPO 到 REINFORCE 众所周知&…...

在 Laravel 12 中实现 WebSocket 通信时进行身份验证

在 Laravel 12 中实现 WebSocket 通信时&#xff0c;若需在身份验证失败后主动断开客户端连接&#xff0c;需结合 频道认证机制 和 服务端主动断连操作。以下是具体实现步骤&#xff1a; 一、身份验证流程设计 WebSocket 连接的身份验证通常通过 私有频道&#xff08;Private …...

Transformer 与 LSTM 在时序回归中的实践与优化

&#x1f9e0; 深度学习混合模型&#xff1a;Transformer 与 LSTM 在时序回归中的实践与优化 在处理多特征输入、多目标输出的时序回归任务时&#xff0c;结合 Transformer 和 LSTM 的混合模型已成为一种有效的解决方案。Transformer 擅长捕捉长距离依赖关系&#xff0c;而 LS…...

Java注解

注解的底层原理&#xff1a; 注解的本质是一种继承自Annotation类的特殊接口&#xff0c;也被称为声明式接口&#xff0c;编译后会转换为一个继承自Anotation的接口&#xff0c;并生成相应的字节码文件。 注解的具体实现类是Java运行时生成的动态代理对象&#xff08;接口本身…...

Linux USB Gadget | 框架 / 复合设备实践 / Configfs 配置

注&#xff1a;本文为“Linux USB Gadget ”相关文章合辑。 图片清晰度受引文原图所限。 略作重排&#xff0c;未整理去重。 如有内容异常&#xff0c;请看原文 Linux USB Gadget 框架概述 2018-04-11 haoxing990 本文记录我在公司 Gadget 相关的驱动开发开发过程中的感悟。…...

Spring Boot之MCP Client开发全介绍

Spring AI MCP(模型上下文协议,Model Context Protocol)客户端启动器为 Spring Boot 应用程序中的 MCP 客户端功能提供了自动配置支持。它支持同步和异步两种客户端实现方式,并提供了多种传输选项。 MCP 客户端启动器提供以下功能: 多客户端实例管理 支持管理多个客户端实…...

nnUNet V2修改网络——暴力替换网络为Swin-Unet

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 Swin-Unet是一种基于纯Transformer的U型编码器-解码器架构,专为医学图像分割任务设计。传统方法主…...

【计网】ICMP、IP、Ethernet PDU之间的封装关系

TCP/IP体系结构 应用层RIP、OSPF、FTP运输层TCP、UDP网际层IP、ARP、ICMP网络接口层底层协议&#xff08;Ethernet&#xff09; 数据链路层 Ethernet报文格式 6Byte6Byte2Byte46~1500Byte4Byte目的MAC地址源MAC地址类型/长度数据FCS 其中&#xff0c;类型 / 长度值小于 1536…...

JSON 转换为 Word 文档

以下是一个在 Spring Boot 中实现 JSON 转 Word 的示例&#xff1a; 首先&#xff0c;需要在项目中引入相关的依赖&#xff0c;如 json 和 Apache POI 等。在 pom.xml 文件中添加以下内容&#xff1a; <!-- JSON 相关依赖 --> <dependency><groupId>com.fast…...

Kotlin Lambda优化Android事件处理

在 Kotlin 中&#xff0c;Lambda 表达式为 Android 事件处理提供了更加简洁优雅的解决方案。通过合理使用 Lambda&#xff0c;可以显著减少模板代码&#xff0c;提升代码可读性。以下是具体实现方式和应用场景&#xff1a; 一、传统方式 vs Lambda 方式对比 1. 按钮点击事件处…...

Springboot接入Deepseek模型

#实现功能&#xff1a;上下文对话、对话历史、清除会话 #本次提供项目源码压缩包&#xff0c;直接下载解压后导入idea即可正常使用 下载好源码后请在DeepSeek 开放平台中注册账号并充值1块余额,注意充值和API keys&#xff0c;API keys包含了秘钥&#xff0c;获取后复制到项目…...

量子跃迁:破解未来计算的“时空密码”​

引言&#xff1a;当量子比特撕裂“摩尔定律”的枷锁 根据德勤《Tech Trends 2025》报告&#xff0c;量子计算机可能在5-20年内成熟&#xff0c;其算力将直接威胁现有加密体系。这不仅是技术的跃迁&#xff0c;更是一场重构数字世界规则的“密码战争”。从谷歌的53量子比特悬铃…...

Spring MVC入门

本内容采用最新SpringBoot3框架版本,视频观看地址:B站视频播放 1. MVC概念 MVC是一种编程思想,它将应用分为模型(Model)、视图(View)、控制器(Controller)三个层次,这三部分以最低的耦合进行协同工作,从而提高应用的可扩展性及可维护性。 模型(Model) 模型层主要…...

【25软考网工】第五章(6)TCP和UDP协议、流量控制和拥塞控制、重点协议与端口

目录 一、TCP和UDP协议 1. TCP和UDP报文格式 1&#xff09;TCP传输控制协议 2&#xff09;UDP用户数据报协议 3&#xff09;TCP与UDP对比 4&#xff09;TCP和UDP类比 5&#xff09;应用案例 例题1#可靠传输服务层 例题2#提供可靠传输功能层 6&#xff09;TCP报文格式…...

如何修改 JAR 包中的源码

如何修改 JAR 包中的源码 前言一、准备工作二、将 JAR 当作 ZIP 打开并提取三、重写 Java 类方法 A&#xff1a;直接替换已编译的 .class方法 B&#xff1a;运行时类路径优先加载 四、修改 MyBatis&#xff08;或其他&#xff09;XML 资源五、重新打包 JAR&#xff08;命令行&a…...

【Linux网络】应用层协议HTTP

&#x1f308;个人主页&#xff1a;秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/qinjh_/category_12891150.html 目录 HTTP 协议 认识 URL urlencode 和 urldecode HTTP 协议请求与响应格式 H…...

高并发架构及场景解决方案

高并发 一、什么是高并发&#xff1f; 高并发是指系统在短时间内能够同时处理大量用户请求或任务的能力&#xff0c;是衡量分布式系统、互联网应用性能的重要指标之一。它的核心目标是确保系统在高负载下仍能稳定、高效运行&#xff0c;同时提供良好的用户体验。 1、高并发系…...

[ linux-系统 ] 常见指令2

1. man 指令 语法&#xff1a;man [选项] 命令 功能&#xff1a;查看联机手册获取帮助。 选项说明-k根据关键字搜索联机帮助。num只在第num章节找。-a显示所有章节的内容。 man是 Unix 和类 Unix 系统中的一个命令&#xff0c;用于查看操作系统和软件的手册页面&#xff08;ma…...

Spring AI快速入门

一、引入依赖 <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-model-openai</artifactId> </dependency> <dependencyManagement><dependencies><dependency><groupId>o…...

TCP数据报

三次握手&#xff08;Three-Way Handshake&#xff09; 是 TCP 协议中用于建立可靠连接的过程。通过三次握手&#xff0c;客户端和服务器能够确认彼此的存在&#xff0c;并且同步各自的初始序列号&#xff0c;为后续的数据传输做好准备。三次握手确保了双方在正式传输数据前能…...

JS循环-for循环嵌套

打印5行5列星星 效果图 代码&#xff1a; // 打印出5行5列的星星for(i 1 ; i < 5 ; i ) {// 外层控制打印行for(j 1 ; j < 5 ; j ) {// 内层控制每行打印几个document.write(⭐)}document.write(<br>)} 打印侧三角 效果图 代码&#xff1a; for(i 1 ; i &l…...

【技术追踪】通过潜在扩散和先验知识增强时空疾病进展模型(MICCAI-2024)

向扩散模型中引入先验知识&#xff0c;实现疾病进展预测&#xff0c;扩散模型开始细节作业了~ 论文&#xff1a;Enhancing Spatiotemporal Disease Progression Models via Latent Diffusion and Prior Knowledge 代码&#xff1a;https://github.com/LemuelPuglisi/BrLP 0、摘…...

Linux/AndroidOS中进程间的通信线程间的同步 - 内存映射

前言 如何使用 mmap()系统调用来创建内存映射。内存映射可用于 IPC 以及其他很多方面。 1 概述 mmap()系统调用在调用进程的虚拟地址空间中创建一个新内存映射。映射分为两种。 文件映射&#xff1a;文件映射将一个文件的一部分直接映射到调用进程的虚拟内存中。一旦一个文…...

单例模式的实现方法

单例模式&#xff08;Singleton Pattern&#xff09;是一种常用的软件设计模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供一个全局访问点。这种模式在需要控制对资源&#xff08;如配置对象、线程池、缓存等&#xff09;的访问时特别有用。 一、单例模…...

laravel 12 监听syslog消息,并将消息格式化后存入mongodb

在Laravel 12中实现监听Syslog消息并格式化存储到MongoDB&#xff0c;需结合日志通道配置、Syslog解析和MongoDB存储操作。以下是具体实现方案&#xff1a; 一、环境配置 安装MongoDB扩展包 执行以下命令安装必要的依赖&#xff1a; composer require jenssegers/mongodb ^4.0确…...

如何在使用 docker-compose 命令时指定 COMPOSE_PROJECT_NAME ?

1.默认值 COMPOSE_PROJECT_NAME 环境变量的默认值并非 docker。在没有显式设置 COMPOSE_PROJECT_NAME 时&#xff0c;其默认值是运行 docker-compose 命令所在目录的基础名称&#xff08;也就是当前工作目录去掉路径后的文件夹名称&#xff09;。 以下为你详细说明&#xff1…...

在命令行终端中快速打开npm包官网

命令 npm home 命令用于快速打开指定 npm 包的官网。例如&#xff0c;npm home react 会尝试打开 React 库的官方网站。 npm home PACKAGE_NAME 该命令会首先查找指定包的 package.json 文件中的 homepage 字段&#xff0c;如果存在&#xff0c;则打开该字段指定的网址。 {&…...

鸿蒙NEXT开发动画(风格的弹性缩放加载动画组件)

1.创建空白项目 2.Page文件夹下面新建Spin.ets文件&#xff0c;代码如下&#xff1a; // 接口定义&#xff08;必须放在使用前&#xff09; /*** 关键帧动画整体配置参数*/ interface KeyframeAnimationConfig {iterations: number;delay: number; }/*** 单个关键帧动画项*/…...

【MongoDB篇】MongoDB的事务操作!

目录 引言第一节&#xff1a;什么是事务&#xff1f; (ACID 原则)第二节&#xff1a;MongoDB 的演进&#xff1a;多文档 ACID 事务的到来&#xff01;&#x1f389;第三节&#xff1a;事务的“玩法”——如何执行一个事务&#xff1f;&#x1f4bb;&#x1f91d;第四节&#xf…...

Android第六次面试总结之Java设计模式篇(一)

一、单例模式在 Android 面试中的核心考点 1. Android 中如何安全实现单例&#xff1f;需注意哪些坑&#xff1f;&#xff08;字节跳动、美团面试真题&#xff09; 解答&#xff1a; Android 中实现单例需重点关注 Context 泄漏、线程安全 和 反射 / 序列化攻击。 推荐实现&…...

关于论文中插入公式但是公式相对于段落的位置偏上应该如何调整备份

因为mythtype之前插入到word里面出现了一些问题就给删掉了&#xff0c;本来要是word里面内联mythtype的话直接&#xff0c;点击mythtype的格式化就可以了&#xff0c; 也就是这个佬的视频介绍链接 然后现在试了试普通word里面的方法&#xff0c;这个是比较有用的 然后看这个例…...

[java八股文][Java并发编程面试篇]并发安全

juc包下你常用的类&#xff1f; 线程池相关&#xff1a; ThreadPoolExecutor&#xff1a;最核心的线程池类&#xff0c;用于创建和管理线程池。通过它可以灵活地配置线程池的参数&#xff0c;如核心线程数、最大线程数、任务队列等&#xff0c;以满足不同的并发处理需求。Exe…...

【东枫科技】代理英伟达产品:智能网卡

文章目录 对比详细&#xff1a;NVIDIA ConnectX-7 适配器详细&#xff1a;NVIDIA ConnectX-6 Lx 以太网智能网卡详细&#xff1a;NVIDIA ConnectX-6 Dx 以太网智能网卡详细&#xff1a;NVIDIA ConnectX-6 InfiniBand 适配器 对比 详细&#xff1a;NVIDIA ConnectX-7 适配器 为最…...

eNSP中路由器OSPF协议配置完整实验和命令解释

本实验使用三台华为路由器&#xff08;R1、R2和R3&#xff09;相连&#xff0c;配置OSPF协议实现网络互通。拓扑结构如下&#xff1a; 实验IP规划 R1: GE0/0/0: 192.168.12.1/24 (Area 0)Loopback0: 1.1.1.1/32 (Area 0) R2: GE0/0/0: 192.168.12.2/24 (Area 0)GE0/0/1: 192.…...

解锁健康生活:全新养身指南

健康养身不是遥不可及的目标&#xff0c;而是由一个个小习惯编织成的生活方式。当我们将这些健康理念融入日常&#xff0c;就能为身体注入源源不断的活力。​ 从 “吃” 开始守护健康。尝试制作 “营养碗”&#xff0c;底层铺满羽衣甘蓝、生菜等绿叶蔬菜&#xff0c;中间搭配水…...

win11 怎样把D盘空间分给C盘一点

如下所示&#xff0c;我的C盘甚至已经爆红了&#xff0c;打算D盘清理一些空间给C盘。 首先附上链接&#xff0c;这是我在b站看的教程&#xff0c;虽然跟着视频没成功&#xff0c;但是结合评论区大神们的建议&#xff0c;尝试了好几种方法&#xff0c;最终自己摸索成功了。 【怎…...

Apache Doris与StarRocks对比

## 历史背景 Apache Doris源自百度的Palo项目,于2017年开源,2018年贡献给Apache基金会,并于2022年从Apache孵化器毕业成为顶级项目。StarRocks则是由原Apache Doris团队的一部分成员在2020年分支出来成立的独立项目,最初称为DorisDB,后更名为StarRocks。这两个项目虽然有…...

OSCP - Proving Grounds - NoName

主要知识点 linux命令注入SUID find提权 具体步骤 从nmap开始搜集信息&#xff0c;只开放了一个80端口 Nmap scan report for 192.168.171.15 Host is up (0.40s latency). Not shown: 65534 closed tcp ports (reset) PORT STATE SERVICE VERSION 80/tcp open http …...

2025年OpenAI重大架构调整:资本与使命的再平衡

目录 前言 一、调整核心&#xff1a;三重架构的重构 1.1 控制权的重新锚定 1.2 营利部门的角色转型 1.3 资金池的重新配置 二、调整动因&#xff1a;三重矛盾的破解 2.1 资金需求与融资限制的冲突 2.2 商业竞争与使命纯度的博弈 2.3 内部治理与外部监管的张力 三、产…...

【quantity】0 README.md文件

PhysUnits 物理单位库 Type-safe physical quantities with dimensional analysis 带量纲分析的类型安全物理量库 A Rust library for safe unit operations / Rust实现的类型安全单位计算库 Core Design / 核心设计 1. Dimension / 量纲 /// Base SI dimensions / 国际单…...

[python] str

一、移除字符串中所有非字母数字字符 使用正则表达式 import re string_value "alphanumeric123__" cleaned_string re.sub(r[\W_], , string_value) # 或 r[^a-zA-Z0-9] print(cleaned_string) # 输出: alphanumeric123使用**str.isalnum()**方法 string_v…...

iOS与HTTPS抓包调试小结

最近在做一个多端 SDK 网络请求兼容性的测试&#xff0c;期间遇到一些 HTTPS 请求抓不到、iOS 抓包失效等问题&#xff0c;趁机整理一下我平时抓包时用到的几个工具和技巧&#xff0c;也顺便记录一下对比体验。 一、传统工具的局限 最早用的是 Charles 和 Fiddler&#xff0c…...

AI基础知识(02):机器学习的任务类型、学习方式、工作流程

03 机器学习(Machine Learning)的任务类型与学习方式 广义的机器学习主要是一个研究如何让计算机通过数据学习规律,并利用这些规律进行预测和决策的过程。这里的Machine并非物理意义上的机器,可以理解为计算机软硬件组织;Learning可以理解为一个系统或平台经历了某些过程…...

2025年大风灾害预警升级!疾风气象大模型如何筑起安全防线?

近年来,全球极端天气事件频发,大风灾害正成为威胁城市安全、交通运输和公共设施的重要隐患。据气象部门预测,2025年我国大风天气将更加频繁,局部地区可能出现超强阵风,对高空作业、电力设施、交通运输等领域构成严峻挑战。面对这一趋势,传统的气象预警方式已难以满足精准…...

Docker手动重构Nginx镜像,融入Lua、Redis功能

核心内容&#xff1a;Docker重构Nginx镜像&#xff0c;融入Lua、Redis功能 文章目录 前言一、准备工作1、说明2、下载模块3、Nginx配置文件3、Dockerfile配置文件3、准备工作全部结束 二、构建镜像三、基于镜像创建容器三、lua脚本的redis功能使用总结 前言 ⁣⁣⁣⁣ ⁣⁣⁣⁣…...