网易一面:Eureka怎么AP?Nacos既CP又AP,怎么实现的?

news2024/11/23 3:35:38

说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如网易、微博、阿里、汽车之家、极兔、有赞、希音、百度、滴滴的面试资格,遇到一几个很重要的面试题:

  • Eureka是AP还是CP? 说说其集群数据一致性流程?
  • Nacos是AP还是CP? 说说其集群数据一致性流程?

与之类似的、其他小伙伴遇到过的问题还有:

  • Eureka怎么AP?Nacos既CP又AP,怎么实现的?

所以,这里尼恩给大家做一下系统化、体系化的梳理,使得大家可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”

也一并把这个题目以及参考答案,收入咱们的 《尼恩Java面试宝典PDF》V112版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到公号【技术自由圈】获取

文章目录

    • 说在前面
    • 注册中心集群的数据一致性问题
      • CAP定理
      • 微服务注册中心是AP还是CP
    • Eureka 的数据同步方式
      • 多个副本之间的 复制方式
      • Eureka 的Peer to Peer 模式同步过程
      • 循环复制问题
      • 总结一下,Eureka 的数据同步方式
    • Nacos 满足AP,又满足CP
    • 快速了解Distro 协议
      • Distro 节点新加入集群场景
      • 心跳场景
      • 写操作场景
      • 读操作场景
      • 总结一下,Distro 的数据同步
    • 快速了解Raft协议
      • Raft算法选主流程
        • 1.Term
        • 2.RPC
        • 3.选举流程
        • 4.日志复制
      • 如何实现Raft算法
        • 启动选举
        • 选举流程
        • 心跳机制
    • 说在最后
    • 推荐阅读

注册中心集群的数据一致性问题

服务注册中心必然是高可用的,这意味着它不能是单点的,而必须是一个注册中心集群。

接下来的问题是:

在一个微服务注册中心集群中,如何确保微服务 Provider 提供者的注册信息或元数据信息保持一致性?

首先,回顾一下CAP定理。

CAP定理

分布式系统中有一个重要理论:CAP。

  1. C:一致性(Consistency)
    在分布式系统中,数据会在多个副本中存在,一些问题可能导致在写入数据时,部分副本成功,部分副本失败,从而导致数据不一致。一致性 C 的要求是,数据更新操作成功后,多个副本的数据必须保持一致。
  2. A:可用性(Availability)
    无论何时,客户端对集群进行读写操作,请求都应能得到正常的响应。
  3. P:分区容错性(Partition Tolerance)
    当发生通信故障,集群被分割成多个无法通信的分区时,集群仍应能正常运行。

微服务注册中心是AP还是CP

回到微服务注册中心的场景。

微服务注册中心的中间件非常多,比如传统的分布式协调组件 Zookeeper, 比如 传统的微服务注册中心 Eureka,比如 阿里的微服务注册中心Nacos,还有 google的 分布式协调组件 etcd,等等。

微服务注册中心是AP还是CP?

首先要明确的是 Eureka 是AP 高并发类型,不是CP强一致类型,而是弱数据一致性的。

ZooKeeper 是CP类型的注册中心,就是尽可能的保证强数据一致性,ZooKeeper首先牺牲A,另外,在某些情况下可以牺牲可用性P。

所以, Eureka 与ZooKeeper 完全是两个极端。

Eureka 则选择了 A,ZooKeeper 优先选择了 C。

Eureka 具有高可用性,在任何时候,服务消费者都能正常获取服务列表,但不保证数据的强一致性,消费者可能会拿到过期的服务列表

Nacos 则做了兼容,既能支持AP模式,也能支持CP模式。

Spring Cloud Alibaba Nacos 在 1.0.0 正式支持 AP 和 CP 两种一致性协议,其中,CP 一致性协议的实现是基于简化的 Raft 协议的强一致性实现。

Eureka 的数据同步方式

多个副本之间的 复制方式

首先看看 数据同步的方式,或者说多个副本的 复制方式。
通常,分布式系统中的数据在多个副本间的复制方式,大体上可以分为以下两种:

  • 主从复制

这种是 Master-Slave 模式,存在一个 master 主副本,其他则是 Slave 从副本,所有的写操作都会被提交到主副本,然后由主副本更新到其他从副本。

因此,写压力都会聚集在主副本上,这成为了系统的瓶颈,而从副本则可以分担读请求。

  • 对等复制

这种是 Peer to Peer 模式,副本之间不存在主从之分,任何一个副本都可以接收写操作,然后各个副本之间会相互进行数据更新。

Peer to Peer 对等复制模式的优势:

任何一个副本都可以接收写请求,不存在写压力的瓶颈,但是在各个副本间进行数据同步时可能会出现数据冲突。

Eureka 就是采用了 Peer to Peer 模式。

Eureka 的Peer to Peer 模式同步过程

在 Eureka Server 启动之后,它会利用本地的 Eureka Client 向其他 Eureka Server 节点中的一个节点发起请求,以获取注册的服务信息,并将这些信息复制到其他 peer 节点。

每当 Eureka Server 的自身信息发生变化,例如微服务的客户端向它发起注册、续约或注销请求时,它会将最新的信息推送给其他 Eureka Server,以保持数据的同步性。

循环复制问题

当然,这里有一个问题: 循环复制问题。

具体来说,如果自身的信息变更是由另一个 Eureka Server 同步过来的,那么如果再将这些信息同步回去,就会出现数据同步的死循环。

在 Eureka Server 执行复制操作时,它会使用一个名为 HEADER_REPLICATION 的 http header 来区分复制操作。

如果一个请求携带了 HEADER_REPLICATION 这个 header,那么这个请求就不再是普通应用实例微服务的客户端的正常请求,而是来自其他 server 的复制请求。这样,当 Eureka Server 收到复制请求时,它就不会再执行复制操作,从而避免了死循环。

还有一个问题,就是数据冲突。

比如 server A 向 server B 发起同步请求,如果 A 的数据比 B 的还旧,那么 B 不可能接受 A 的数据。在这种情况下,B 如何知道 A 的数据是旧的呢?这时 A 又应该怎么办呢?

数据的新旧通常是通过版本号来定义的,Eureka 使用 lastDirtyTimestamp 这个类似版本号的属性来实现。

lastDirtyTimestamp 是注册中心中服务实例的一个属性,它表示此服务实例最近一次变更时间。

节点间的复制,可能会出错,如何进行错误的检测和弥补呢?

此外,Eureka 集群中,还有一个重要的机制:hearbeat 心跳,即续约操作,用于完成数据的最终修复。由于节点间复制可能出现错误,我们可以通过心 beat 机制来发现并修复这些错误。

总结一下,Eureka 的数据同步方式

  • Eureka 使用 Peer to Peer 模式进行数据复制。
  • Eureka 通过 http header就是 HEADER_REPLICATION 解决循环复制问题。
  • Eureka 通过 lastDirtyTimestamp 解决复制冲突。
  • Eureka 通过心跳机制实现数据修复。

Nacos 满足AP,又满足CP

与Eureka 、Zookeeper集群不同Nacos 既能支持AP,又能支持 CP。

Nacos 支持 CP+AP 模式,这意味着 Nacos 可以根据配置识别为 CP 模式或 AP 模式,默认情况下为 AP 模式。

  • 如果注册Nacos的client节点注册时ephemeral=true,那么Nacos集群对这个client节点的效果就是AP,采用distro协议实现;

  • 而注册Nacos的client节点注册时ephemeral=false,那么Nacos集群对这个节点的效果就是CP的,采用raft协议实现。

根据client注册时的属性,AP,CP同时混合存在,只是对不同的client节点效果不同。

因此,Nacos 能够很好地满足不同场景的业务需求。

快速了解Distro 协议

Distro 协议是 Nacos 自主研发的一种 AP 分布式协议,专为临时实例设计,确保在部分 Nacos 节点宕机时,整个临时实例仍可正常运行。

作为一款具有状态的中间件应用的内置协议,Distro 确保了各 Nacos 节点在处理大量注册请求时的统一协调和存储。

Distro 协议 与Eureka Peer to Peer 模式同步过程, 大致是类似的。

Distro 协议的同步过程,大致如下:

  • 每个节点是平等的都可以处理写请求,同时将新数据同步至其他节点。
  • 每个节点只负责部分数据,定时发送自己负责数据的校验值,到其他节点来保持数据⼀致性。
  • 每个节点独立处理读请求,并及时从本地发出响应。

接下来的几节将通过不同的场景介绍 Distro 协议的工作原理。

Distro 节点新加入集群场景

新加入的 Distro 节点,会进行全量数据拉取。

具体操作是依次访问所有 Distro 节点,通过向其他机器发送请求,来拉取全量数据

在完成全量拉取操作后,Nacos 的每台机器都维护了当前所有注册的非持久化实例数据。

心跳场景

在 Distro 集群启动后,各台机器之间会定期发送心跳。

心跳信息主要包括各机器上的所有数据的元信息(使用元信息是为了确保网络中数据传输量维持在较低水平)。这种数据校验以心跳形式进行,即每台机器在固定时间间隔内向其他机器发起一次数据校验请求。

如果在数据校验过程中,某台机器发现其他机器上的数据与本地数据不一致,会发起一次全量拉取请求,将数据补全。

写操作场景

对于⼀个已经启动完成的 Distro 集群,在⼀次客户端发起写操作的流程中,当注册非持久化的实例的写请求打到某台 Nacos 服务器时,Distro 集群处理的流程图如下。

整个步骤包括几个部分(图中从上到下顺序):

  • 前置的 Filter 拦截请求,并根据请求中包含的 IP 和 port 信息计算其所属的 Distro 责任节点,并将该请求转发到所属的 Distro 责任节点上。
  • 责任节点上的 Controller 对写请求进行解析。
  • Distro 协议定期执行 Sync 任务,将本机所负责的所有实例信息同步到其他节点上。

读操作场景

由于每台机器上都存储了全量数据,因此在每次读操作中,Distro 机器会直接从本地获取数据,实现快速响应。

这种机制确保了 Distro 协议可以作为 AP 协议,对读操作进行及时响应。

  • 在网络分区状况下,所有读操作仍可正常返回结果;
  • 当网络恢复时,各 Distro 节点会将各数据片段进行合并恢复。

总结一下,Distro 的数据同步

Distro 协议是 Nacos 针对临时实例数据开发的⼀致性协议。

数据存储在缓存中,并在启动时进行全量数据同步,定期执行数据校验

遵循 Distro 协议的设计理念,每个 Distro 节点均能接收读写请求。Distro 协议的请求场景主要分为以下三种情况:

  1. 当该节点接收到属于该节点负责的实例的写请求时,直接写入。
  2. 当该节点接收到不属于该节点负责的实例的写请求时,将在集群内部路由,转发给对应的节点,从而完成读写。
  3. 当该节点接收到任何读请求时,都直接在本机查询并返回(因为所有实例都被同步到了每台机器上)。

作为 Nacos 的内置临时实例一致性协议,Distro 协议确保了在分布式环境中,每个节点上的服务信息状态能够及时通知其他节点,支持数十万量级服务实例的存储和一致性维护。

快速了解Raft协议

Spring Cloud Alibaba Nacos 在 1.0.0 正式支持 AP 和 CP 两种一致性协议,其中的CP一致性协议实现,是基于简化的 Raft 的 CP 一致性。

Raft 适用于一个管理日志一致性的协议,相比于 Paxos 协议, Raft 更易于理解和去实现它。

为了提高理解性,Raft 将一致性算法分为了几个部分,包括领导选取(leader selection)、日志复制(log replication)、安全(safety),并且使用了更强的一致性来减少了必须需要考虑的状态。

相比Paxos,Raft算法理解起来更加直观。

Raft算法将Server划分为3种状态,或者也可以称作角色:

  • Leader: 负责Client交互和log复制,同一时刻系统中最多存在1个。
  • Follower:被动响应请求RPC,从不主动发起请求RPC。
  • Candidate:一种临时的角色,只存在于leader的选举阶段,某个节点想要变成leader,那么就发起投票请求,同时自己变成candidate。如果选举成功,则变为candidate,否则退回为follower

状态或者说角色的流转如下:

在Raft中,问题被分解为:领导选取、日志复制、安全和成员变化。

通过复制日志来实现状态机的复制:

日志:每台机器都保存一份日志,日志来源于客户端的请求,包含一系列的命令。

状态机:状态机会按顺序执行这些命令。

一致性模型:在分布式环境中,确保多台机器的日志保持一致,从而使状态机回放时的状态保持一致。

Raft算法选主流程

Raft中使用心跳机制来出发leader选举。当服务器启动的时候,服务器成为follower。只要follower从leader或者candidate收到有效的RPCs就会保持follower状态。如果follower在一段时间内(该段时间被称为election timeout)没有收到消息,则它会假设当前没有可用的leader,然后开启选举新leader的流程。

1.Term

Term的概念类比中国历史上的朝代更替,Raft 算法将时间划分成为任意不同长度的任期(term)。

任期用连续的数字进行表示。每一个任期的开始都是一次选举(election),一个或多个候选人尝试成为领导者。如果一个候选人赢得选举,它将在该任期的剩余时间内担任领导者。在某些情况下,选票可能会被平分,导致没有选出领导者,此时将开始新的任期并立即进行下一次选举。Raft 算法确保在给定的任期中只有一个领导者。

2.RPC

Raft 算法中服务器节点之间通信使用远程过程调用(RPCs),并且基本的一致性算法只需要两种类型的 RPCs,为了在服务器之间传输快照增加了第三种 RPC。

RPC有三种:

  • RequestVote RPC:候选人在选举期间发起
  • AppendEntries RPC:领导人发起的一种心跳机制,复制日志也在该命令中完成
  • InstallSnapshot RPC:领导者使用该RPC来发送快照给太落后的追随者
3.选举流程

(1)follower增加当前的term,转变为candidate。

(2)candidate投票给自己,并发送RequestVote RPC给集群中的其他服务器。

(3)收到RequestVote的服务器,在同一个term中,只会按照先到先得投票给至多一个candidate。且只会投票给log至少和自身一样新的candidate。

初始节点

Node1 转为 Candidate 发起选举

Node 确认选举

Node1 成为 leader,发送 Heartbeat

candidate节点保持(2)的状态,直到下面三种情况中的一种发生。

  • 该节点赢得选举,即收到大多数节点的投票,然后转变为 leader 状态。
  • 另一个服务器成为 leader,即收到合法心跳包(term 值大于或等于当前自身 term 值),然后转变为 follower 状态。
  • 一段时间后仍未确定胜者,此时会启动新一轮的选举。

为了解决当票数相同时无法确定 leader 的问题,Raft 使用随机选举超时时间。

4.日志复制

日志复制(Log Replication)的主要目的是确保节点的一致性,在此阶段执行的操作都是为了确保一致性和高可用性。

当 Leader 选举产生后,它开始负责处理客户端的请求。所有的事务(更新操作)请求都必须先由 Leader 处理。日志复制(Log Replication)就是为了确保执行相同的操作序列所做的工作。

在 Raft 中,当接收到客户端的日志(事务请求)后,先把该日志追加到本地的Log中,然后通过heartbeat把该Entry同步给其他Follower,Follower接收到日志后记录日志然后向Leader发送ACK,当Leader收到大多数(n/2+1)Follower的ACK信息后将该日志设置为已提交并追加到本地磁盘中,通知客户端并在下个heartbeat中Leader将通知所有的Follower将该日志存储在自己的本地磁盘中。

如何实现Raft算法

Nacos server在启动时,会通过RunningConfig.onApplicationEvent()方法调用RaftCore.init()方法。

启动选举
public static void init() throws Exception {
 
    Loggers.RAFT.info("initializing Raft sub-system");
 
    // 启动Notifier,轮询Datums,通知RaftListener
    executor.submit(notifier);
     
    // 获取Raft集群节点,更新到PeerSet中
    peers.add(NamingProxy.getServers());
 
    long start = System.currentTimeMillis();
 
    // 从磁盘加载Datum和term数据进行数据恢复
    RaftStore.load();
 
    Loggers.RAFT.info("cache loaded, peer count: {}, datum count: {}, current term: {}",
        peers.size(), datums.size(), peers.getTerm());
 
    while (true) {
        if (notifier.tasks.size() <= 0) {
            break;
        }
        Thread.sleep(1000L);
        System.out.println(notifier.tasks.size());
    }
 
    Loggers.RAFT.info("finish to load data from disk, cost: {} ms.", (System.currentTimeMillis() - start));
 
    GlobalExecutor.register(new MasterElection()); // Leader选举
    GlobalExecutor.register1(new HeartBeat()); // Raft心跳
    GlobalExecutor.register(new AddressServerUpdater(), GlobalExecutor.ADDRESS_SERVER_UPDATE_INTERVAL_MS);
 
    if (peers.size() > 0) {
        if (lock.tryLock(INIT_LOCK_TIME_SECONDS, TimeUnit.SECONDS)) {
            initialized = true;
            lock.unlock();
        }
    } else {
        throw new Exception("peers is empty.");
    }
 
    Loggers.RAFT.info("timer started: leader timeout ms: {}, heart-beat timeout ms: {}",
        GlobalExecutor.LEADER_TIMEOUT_MS, GlobalExecutor.HEARTBEAT_INTERVAL_MS);
}

在init方法主要做了如下几件事:

  1. 获取Raft集群节点 peers.add(NamingProxy.getServers());
  2. Raft集群数据恢复 RaftStore.load();
  3. Raft选举 GlobalExecutor.register(new MasterElection());
  4. Raft心跳 GlobalExecutor.register(new HeartBeat());
  5. Raft发布内容
  6. Raft保证内容一致性
选举流程

其中,raft集群内部节点间是通过暴露的Restful接口,代码在 RaftController 中。RaftController控制器是raft集群内部节点间通信使用的,具体的信息如下:

POST HTTP://{ip:port}/v1/ns/raft/vote : 进行投票请求

POST HTTP://{ip:port}/v1/ns/raft/beat : LeaderFollower发送心跳信息

GET HTTP://{ip:port}/v1/ns/raft/peer : 获取该节点的RaftPeer信息

PUT HTTP://{ip:port}/v1/ns/raft/datum/reload : 重新加载某日志信息

POST HTTP://{ip:port}/v1/ns/raft/datum : Leader接收传来的数据并存入

DELETE HTTP://{ip:port}/v1/ns/raft/datum : Leader接收传来的数据删除操作

GET HTTP://{ip:port}/v1/ns/raft/datum : 获取该节点存储的数据信息

GET HTTP://{ip:port}/v1/ns/raft/state : 获取该节点的状态信息{UP or DOWN}

POST HTTP://{ip:port}/v1/ns/raft/datum/commit : Follower节点接收Leader传来得到数据存入操作

DELETE HTTP://{ip:port}/v1/ns/raft/datum : Follower节点接收Leader传来的数据删除操作

GET HTTP://{ip:port}/v1/ns/raft/leader : 获取当前集群的Leader节点信息

GET HTTP://{ip:port}/v1/ns/raft/listeners : 获取当前Raft集群的所有事件监听者
RaftPeerSet
心跳机制

Raft中使用心跳机制来触发leader选举。

心跳定时任务是在GlobalExecutor 中,通过 GlobalExecutor.register(new HeartBeat())注册心跳定时任务,具体操作包括:

  • 重置Leader节点的heart timeout、election timeout;
  • sendBeat()发送心跳包
public class HeartBeat implements Runnable {
    @Override
    public void run() {
        try {

            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);
        }
    }
}

简单说明了下Nacos中的Raft一致性实现,更详细的流程,可以下载源码,查看 RaftCore 进行了解。

源码可以通过以下地址检出:

git clone https://github.com/alibaba/nacos.git

说在最后

注册中心的 数据一致性 相关面试题,是非常常见的面试题。

以上的内容,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。

在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,并且在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。

推荐阅读

《百亿级访问量,如何做缓存架构设计》

《多级缓存 架构设计》

《消息推送 架构设计》

《阿里2面:你们部署多少节点?1000W并发,当如何部署?》

《美团2面:5个9高可用99.999%,如何实现?》

《网易一面:单节点2000Wtps,Kafka怎么做的?》

《字节一面:事务补偿和事务重试,关系是什么?》

《网易一面:25Wqps高吞吐写Mysql,100W数据4秒写完,如何实现?》

《亿级短视频,如何架构?》

《炸裂,靠“吹牛”过京东一面,月薪40K》

《太猛了,靠“吹牛”过顺丰一面,月薪30K》

《炸裂了…京东一面索命40问,过了就50W+》

《问麻了…阿里一面索命27问,过了就60W+》

《百度狂问3小时,大厂offer到手,小伙真狠!》

《饿了么太狠:面个高级Java,抖这多硬活、狠活》

《字节狂问一小时,小伙offer到手,太狠了!》

《收个滴滴Offer:从小伙三面经历,看看需要学点啥?》

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓

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

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

相关文章

有哪些ai智能写作是永久免费的

无论你是一个自媒体作者&#xff0c;企业家&#xff0c;还是一个博客写手&#xff0c;你都了解创作的挑战。创意和时间常常成为限制因素&#xff0c;而AI智能写作工具则旨在解决这些问题。 这些工具利用先进的自然语言处理技术&#xff0c;可以生成各种类型的文本&#xff0c;包…

Appium+python+unittest搭建UI自动化框架

阅读本小节&#xff0c;需要读者具备如下前提条件&#xff1a; 掌握一种编程语言基础&#xff0c;如java、python等。 掌握一种单元测试框架&#xff0c;如java语言的testng框架、python的unittest框架。 掌握目前主流的UI测试框架&#xff0c;移动端APP测试框架Appium&…

Java中的IO流的缓冲流

不爱生姜不吃醋⭐️ 如果本文有什么错误的话欢迎在评论区中指正 与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 &#x1f334;IO流体系结构&#x1f334;缓冲流1.提高效率的原理2.缓冲流的类型3.字符缓冲流两个特有方法 &#x1f334;总结 &#x1f334;IO流体系…

如何查阅下载美国物理学会(APS)文献

APS美国物理学会数据库简介&#xff1a; The American Physical Society (APS)成立于1899年&#xff0c;是世界上最具声望的物理学专业学会之一。APS不仅为用户带来今日尖端研究&#xff0c;同时为全球各研究单位提供自1893年以来&#xff0c;在“PHYSICAL REVIEW”上刊载的所…

2020年12月 Python(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python编程&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 执行以下代码中&#xff0c;输出的结果是&#xff1f;&#xff08; &#xff09; sum0 for i in range(1,10,3):sumsumi p…

88、Redis 的 value 所支持的数据类型(String、List、Set、Zset、Hash)---->Set相关命令

本次讲解要点&#xff1a; ** Set相关命令&#xff1a;是指value中的数据类型** 启动redis服务器&#xff1a; 打开小黑窗&#xff1a; C:\Users\JH>e: E:>cd E:\install\Redis6.0\Redis-x64-6.0.14\bin E:\install\Redis6.0\Redis-x64-6.0.14\bin>redis-server.exe …

智慧能源:引领未来的能源革命

在当今世界&#xff0c;能源问题是一个备受关注的焦点话题。随着全球人口的不断增长和工业化进程的加速&#xff0c;对能源的需求也日益增加&#xff0c;同时&#xff0c;传统的能源资源面临着日益严重的枯竭和环境污染问题。在这一背景下&#xff0c;智慧能源应运而生&#xf…

vite跨域proxy设置与开发、生产环境的接口配置,接口在生产环境下,还能使用proxy代理地址吗

文章目录 vite的proxy开发环境设置如果后端没有提供可以替换的/mis等可替换的后缀的处理办法接口如何区分.env.development开发和.env.production生产环境接口在生产环境下&#xff0c;还能使用proxy代理地址吗&#xff1f; vite的proxy开发环境设置 环境&#xff1a; vite 4…

服务断路器_服务雪崩解决方案之服务隔离

那显而易见&#xff0c;做服务隔离的目的就是避免服务之间相互影响。毕竟谁也不能说自己的微服务百分百可用&#xff0c;如果不做隔离&#xff0c;一旦一个服务出现了问题&#xff0c;整个系统的稳定性都会受到影响&#xff01; 因此&#xff0c;做服务隔离是很有必要的。 什么…

消费者偏移量_consumer_offsets相关解析

1.概述 __consumer_offsets 是 kafka 自行创建的&#xff0c;和普通的 topic 相同。它存在的目的之一就是保存 consumer 提交的位移。 __consumer_offsets 的每条消息格式大致如图所示: 可以想象成一个 KV 格式的消息&#xff0c;key 就是一个三元组&#xff1a;group.idtopi…

成都睿趣科技:抖音开通橱窗带货需要钱吗

随着社交媒体和电子商务的蓬勃发展&#xff0c;抖音作为一种流行的短视频平台&#xff0c;也推出了自己的“抖音橱窗”功能&#xff0c;让内容创作者能够通过视频展示和销售产品&#xff0c;从而实现商业化。那么&#xff0c;抖音橱窗带货是否需要费用呢? 首先&#xff0c;要开…

现代数据架构-湖仓一体

当前的数据架构已经从数据库、数据仓库&#xff0c;发展到了数据湖、湖仓一体架构&#xff0c;本篇文章从头梳理了一下数据行业发展的脉络。 上世纪&#xff0c;最早出现了关系型数据库&#xff0c;也就是DBMS&#xff0c;有商业的Oracle、 IBM的DB2、Sybase、Informix、 微软…

关于坐标的旋转变换和坐标系的旋转变换

不管是坐标的旋转变换还是坐标系下的旋转变换&#xff0c;只和旋转的顺时针和逆时针有关。然坐标系间的顺时针和逆时针是根据当前坐标系在目标坐标系下的相对位置确定。 一。逆时针旋转belta角度的公式 二。顺时针旋转belta角度的公式 三。坐标的旋转变换 1.坐标的旋转变换相…

一文了解企业如何实现文件自动化实时同步

在当今的数字化时代&#xff0c;数据是企业的核心资产&#xff0c;也是企业竞争力的重要体现。数据的传输、共享、协作、备份等都需要依赖文件同步技术&#xff0c;实现数据在不同平台和设备之间的一致性和可用性。文件同步是指将一个或多个文件夹中的内容复制或更新到另一个或…

网络安全攻防:软件逆向之反汇编

网络安全是当今社会中一个非常重要的问题&#xff0c;而软件逆向工程是网络安全攻防中常用的一种技术手段。在软件逆向工程中&#xff0c;反汇编是一种基础而重要的技术。通过反汇编&#xff0c;我们可以将二进制程序转换为汇编语言&#xff0c;从而更好地理解程序的执行流程和…

在伦敦银投资中,技术是万能的?

一般进行伦敦银投资的投资者都会学习很多技术分析的方法&#xff0c;技术分析是一种还很适合普通投资者使用的市场分析工具&#xff0c;但是在伦敦银投资中&#xff0c;技术分析的作用不是万能的&#xff0c;其实技术分析还是有很多各种各样的缺点&#xff0c;如果投资者迷信技…

前缀和实例5(连续数组)

题目&#xff1a; 给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组&#xff0c;并返回该子数组的长度。 示例 1: 输入: nums [0,1] 输出: 2 说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。 示例 2: 输入: nums [0,1,0] 输出: 2 说明: [0…

Exception in thread “main“ java.sql.SQLException: No suitable driver

详细报错信息如下&#xff1a; Exception in thread "main" java.sql.SQLException: No suitable driver at java.sql.DriverManager.getDriver(DriverManager.java:315) at org.apache.spark.sql.execution.datasources.jdbc.JDBCOptions.$anonfun$driverC…

js遍历对象属性的方法

在 JavaScript 中&#xff0c;有许多方法可以遍历对象的属性&#xff0c;但在性能上并没有显著的差异。对于大多数用例&#xff0c;使用 for-in 循环或 Object.keys() 方法是最常见的。 然而&#xff0c;如果你正在寻找微优化&#xff0c;并希望遍历大量对象&#xff0c;可以考…

数字孪生需要自建3D模型?搞懂Blender建模要点,看这篇文章就够了!

1. Blender的基础介绍 关于城市大师的建模软件&#xff0c;一般推荐使用Blender。一是因为Blender是开源免费的&#xff0c;不会有经济负担&#xff0c;二是因为我们软件有针对Blender的插件&#xff0c;对其进行了一定程度上的补充。 【温馨提示】如果使用的是3Dmax或者maya…