Nacos简介—4.Nacos架构和原理一
大纲
1.Nacos的定位和优势
2.Nacos的整体架构
3.Nacos的配置模型
4.Nacos内核设计之一致性协议
5.Nacos内核设计之自研Distro协议
6.Nacos内核设计之通信通道
7.Nacos内核设计之寻址机制
8.服务注册发现模块的注册中心的设计原理
9.服务注册发现模块的注册中心的服务数据模型
10.服务注册发现模块的健康检查机制
11.配置管理模块的配置一致性模型
12.Zookeeper、Eureka和Nacos的对比总结
整理于官方文档
1.Nacos的定位和优势
(1)Nacos的定位
(2)Nacos的优势
(3)Nacos生态
(1)Nacos的定位
Nacos是Dynamic Naming and Configuration Service的首字母简称,⼀个更易于构建云原生应用的服务发现和管理和动态配置管理的平台。
(2)Nacos的优势
一.易⽤
简单的数据模型,标准的restfulAPI,易用的控制台,丰富的使用文档。
二.稳定
99.9%高可用,支持具有数百万服务的大规模场景。
三.实时
数据变更毫秒级推送生效。1w级,SLA承诺1w实例上下线1s,99.9%推送完成。10w级,SLA承诺1w实例上下线3s,99.9%推送完成。100w级别,SLA承诺1w实例上下线9s,99.9%推送完成。
四.规模
十万级服务/配置,百万级连接,具备强大扩展性。
(3)Nacos生态
Nacos几乎支持所有主流语言,比如Java/Python/Golang。这三种语言已经支持Nacos 2.0长链接协议,能最大限度发挥Nacos性能。DNS(Dubbo + Nacos + Spring-Cloud-Alibaba/Seata/Sentinel)最佳实践,是Java微服务生态最佳解决方案。
2.Nacos的整体架构
(1)架构图
(2)用户层
(3)业务层
(4)内核层
(5)插件
(1)架构图
整体架构分为用户层、业务层、内核层和插件。用户层主要解决用户使用的易用性问题,业务层主要解决服务发现和配置管理的功能问题,内核层用来解决分布式系统⼀致性、存储、高可用等核心问题,插件用来解决扩展性问题。
(2)用户层
一.OpenAPI
暴露Rest风格的HTTP接口,简单易用和方便集成。
二.Console
易用控制台,用于服务管理、配置管理等操作。
三.SDK
多语言SDK,目前几乎支持所有主流编程语言。
四.Agent
Sidecar模式运行,通过标准DNS协议与业务解耦。
五.CLI
命令行对产品进行轻量化管理,像git⼀样好用。
(3)业务层
一.服务管理
实现服务CRUD、域名CRUD、服务健康状态检查、服务权重管理等功能。
二.配置管理
实现配置CRUD、版本管理、灰度管理、监听管理、推送轨迹等功能。
三.元数据管理
提供元数据CURD和打标能力,为实现上层流量和服务灰度非常关键。
(4)内核层
一.插件机制
实现三个模块可分可合,实现扩展点SPI机制,用于扩展自己公司定制。
二.事件机制
实现异步化事件通知、SDK数据变化异步通知等逻辑,这是Nacos高性能的关键部分。
三.日志模块
管理日志分类、日志级别、日志移植、日志格式、异常码 + 帮助文档。
四.回调机制
SDK通知数据,通过统⼀的模式回调用户处理,接口和数据结构需要具备可扩展性。
五.寻址机制
解决Server IP直连、域名访问、NameServer寻址、广播等多种寻址模式。
六.传输通道
解决Server与存储、Server间、Server与SDK间高效通信问题。
七.容量管理
管理每个租户、分组下的容量,防止存储被写爆,影响服务可用性。
八.流量管控
按照租户、分组等维度管控请求频率、长链接个数、报文大小等。
九.缓存机制
容灾目录、本地缓存、Server缓存机制,是Nacos高可用的关键。
十.启动模式
按照单机模式、配置模式、服务模式、DNS模式,启动不同的模块。
十一.⼀致性协议
解决对于不同数据的不同⼀致性要求的问题。
十二.存储模块
解决数据持久化、非持久化存储,数据分片问题。
(5)插件
一.NameServer
解决Namespace到ClusterID的路由问题。
解决用户环境与Nacos物理环境映射问题。
二.CMDB
解决元数据存储,与三方CMDB系统对接问题。
解决应用、人、资源关系。
三.Metrics
暴露标准Metrics数据,方便与三方监控系统打通。
四.Trace
暴露标准Trace,方便与SLA系统打通。日志白平化 + 推送轨迹能力,方便和计量计费系统打通。
五.接入管理
相当于阿里云开通服务,分配身份、容量、权限。
六.用户管理
解决用户管理、登录、SSO等问题。
七.权限管理
解决身份识别,访问控制,角色管理等问题。
八.审计系统
扩展接口方便与不同公司审计系统打通。
九.通知系统
核心数据变更、操作,方便打通SMS系统,通知对应人数据发生变更。
3.Nacos的配置模型
(1)修改服务配置的背景
(2)Nacos配置管理中的概念
(3)Nacos的配置模型之基础模型
(4)Nacos的配置模型之配置资源模型
(5)Nacos的配置模型之配置存储模型(ER图)
(1)修改服务配置的背景
在单体架构时,我们可以将配置写在配置文件中,但缺点就是每次修改配置都需要重启服务才能生效。
当应用程序实例比较少的时候还可以维护。如果转向微服务架构成百上千实例,每修改⼀次配置要将全部实例重启,这样不仅增加了系统的不稳定性,也提高了维护的成本。
那么如何能够做到服务不重启就可以修改配置?所以就产生了四个基础诉求:
一.需要支持动态修改配置
二.需要实时的动态变更
三.变更太快如何管控变更风险,如灰度、回滚等
四.敏感配置如何做安全配置
(2)Nacos配置管理中的概念
一.配置(Configuration)
开发中通常会将⼀些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在,让系统更好地适配实际的物理运行环境。
配置管理⼀般在系统部署时进行,由系统管理员或运维人员完成该步骤。配置变更是调整系统运行时的行为的有效手段之⼀。
二.配置管理(Configuration Management)
在Nacos中,系统中所有配置的存储、编辑、删除、灰度管理、历史版本管理、变更审计等所有与配置相关的活动统称为配置管理。
三.配置服务(Configuration Service)
在服务或应用运行中,提供动态配置或元数据以及配置管理的服务提供者。
四.配置项(Configuration Item)
⼀个具体的可配置的参数与其值,通常以"key = value"的形式存在。例如我们常配置系统的日志输出级别"logLevel = INFO"就是⼀个配置项。
五.配置集(Configuration Set)
⼀组相关或者不相关的配置项的集合称为配置集。在系统中,⼀个配置文件通常就是⼀个配置集,包含了系统各方面的配置。例如,⼀个配置集可能包含了数据源、线程池、日志级别等配置项。
六.命名空间(Namespace)
用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的Group或Data ID的配置。Namespace的常用场景之⼀是不同环境的配置的区分隔离。例如开发环境和生产环境的资源(如数据库配置、限流阈值)隔离等。如果在没有指定Namespace的情况下,默认使用public命名空间。
七.配置组(Group)
Nacos中的⼀组配置集,是配置的维度之⼀。通过⼀个有意义的字符串(如ABTest中的实验组、对照组)对配置集分组,从而区分Data ID相同的配置集。
当在Nacos上创建⼀个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用DEFAULT_GROUP。
配置分组的常见场景:不同的应用或组件使用了相同的配置项。如database_url配置和MQ_Topic配置。
八.配置ID(Data ID)
Nacos中的某个配置集的ID,配置集ID是划分配置的维度之⼀。Data ID通常用于划分系统的配置集,⼀个系统或应用可包含多个配置集。每个配置集都可被⼀个有意义的名称标识。Data ID尽量保障全局唯⼀,可以参考Nacos Spring Cloud中的命名规则。
九.配置快照(Configuration Snapshot)
Nacos的客户端SDK会在本地生成配置的快照。当客户端无法连接Nacos时,可使用配置快照显示系统的整体容灾能力。配置快照类似于Git中的本地commit,也类似于缓存。配置快照会在适当的时机更新,但是并没有缓存过期(expiration)的概念。
(3)Nacos的配置模型之基础模型
下图是Nacos配置管理的基础模型:
说明一:Nacos提供了可视化的控制台,通过控制台可以发布配置、更新配置、删除配置、灰度发布、版本管理等。
说明二:Client端也可以发布配置、更新配置、监听配置等。
说明三:Client端会通过gRPC长连接监听配置。
说明四:Server端会对比Client端配置的MD5和本地配置的MD5是否相等,如果不相等,那么Server端就会推送配置变更到Client端。
说明五:Client端会保存配置的快照,当服务端出现问题时则从本地获取。
(4)Nacos的配置模型之配置资源模型
Namespace的设计就是用来进行资源隔离的,我们在进行配置资源时可以从以下两个角度来看。
角度一:从单个租户的角度来看
我们要配置多套环境的配置,可以根据不同的环境来创建Namespace。比如有开发环境、测试环境、线上环境,那么就创建对应的dev、test、prod。Nacos会自动生成对应的Namespace Id。如果同⼀个环境内想配置不相同的配置,可以通过Group来区分。
角度二:从多个租户的角度来看
每个租户都可以有自己的命名空间。我们可以为每个用户创建⼀个命名空间,并给用户分配对应的权限。
比如多个租户:zhangsan、lisi、wangwu。每个租户都想有⼀套自己的多环境配置,即每个租户都想配置多套环境。那么可以给每个租户创建⼀个Namespace:zhangsan、lisi、wangwu。同样会生成对应的Namespace Id,然后使用Group区分不同环境的配置。如下图所示:
(5)Nacos的配置模型之配置存储模型(ER图)
Nacos存储配置有几个比较重要的表:
一.config_info表存储配置信息
里面有dataId、groupId、content、tenantId、encryptedDataKey等数据。
二.config_info_beta表存储灰度测试的配置信息
存储的字段内容和config_info基本相似,但有⼀个beta_ips字段是用于客户端请求配置时,判断是否是灰度的IP的。
三.config_tags_relation表存储配置的标签
在发布配置时如果指定了标签,则会把标签和配置的关联信息存储在该表。
四.his_config_info表存储配置的历史信息
对配置进行的发布、更新、删除等操作都会记录⼀条数据,可以根据这个标实现多版本管理和快速回滚。
4.Nacos内核设计之一致性协议
(1)为什么Nacos需要⼀致性协议
(2)为什么Nacos会同时运行CP协议以及AP协议
(3)为什么Nacos选择Raft以及Distro协议
(4)Nacos早期的⼀致性协议
(5)Nacos当前的⼀致性协议
(6)Nacos如何做到⼀致性协议下沉的
(1)为什么Nacos需要⼀致性协议
首先Nacos需要实现在其内部存储数据,从而可以尽可能减少用户部署以及运维成本,只需⼀个程序包就可以快速以单机模式或集群模式启动Nacos。
单机模式下的内部存储很容易实现,使用简单的内嵌关系型数据库即可。集群模式下的内部存储就要考虑各节点间的数据⼀致性以及数据同步。而要解决这个问题,就不得不引入共识算法,通过共识算法来保障各个节点间的数据⼀致性。
(2)为什么Nacos会同时运行CP协议以及AP协议
这要从Nacos的应用场景出发:由于Nacos是⼀个集服务注册发现以及配置管理于⼀体的组件,因此要将集群模式下各节点间的数据⼀致性保障问题拆分成两方面来看。
一.从服务注册发现来看
服务注册发现中心,在当前微服务体系下,是十分重要的组件。服务间为了感知对方服务当前可正常提供服务的实例信息,需要从服务注册发现中心进行获取。
因此对于服务注册发现中心组件的可用性,提出了很高的要求,需要在任何场景下,尽最大可能保证服务注册发现能力可以对外提供服务。
同时Nacos服务注册发现,实现了基于心跳自动完成服务数据补偿的机制。如果节点出现了数据丢失,节点可以通过该机制快速补偿丢失的数据。
因此为了满足服务注册发现中心的可用性,强⼀致性的共识算法就不合适。因为强⼀致性共识算法能否对外提供服务是有要求的。如果当前集群可用的节点数没有过半的话,整个算法直接"罢工"。
而最终⼀致共识算法会更多保障服务的可用性,并且能保证在⼀定的时间内各节点间的数据能达成⼀致。
上述都是针对Nacos服务注册发现中的非持久化服务实例而言,即需要客户端上报心跳进行服务实例续约。即针对此类型的服务数据,选择最终一致共识算法来保障数据的一致性。
而对于Nacos服务发现注册中的持久化服务实例,因为所有数据都是直接调用Nacos服务端时进行创建的,因此需要由Nacos保障数据在各节点间的强⼀致性。故而针对此类型的服务数据,选择强⼀致性共识算法来保障数据的⼀致性。
二.从配置管理来看
由于配置数据是直接在Nacos服务端进行创建并进行管理的,因此必须保证大部分节点都保存了此配置数据才能认为配置被成功保存了。
否则就会丢失配置的变更,如果出现这种情况,问题是很严重的。如果发布重要配置变更时,出现丢失变更的情况,则可能会引起严重故障。
因此对于配置数据的管理,必须要求集群中大部分的节点是强⼀致的,这里只能使用强⼀致性共识算法。
(3)为什么Nacos选择Raft以及Distro协议
对于强⼀致性共识算法,当前工业生产中,最多使用的就是Raft协议。Raft协议更容易让人理解,并且有很多成熟的工业算法实现。比如JRaft、BRaft、Zookeeper的ZAB、Consul的Raft、Apache的Ratis。
因为Nacos是Java技术栈,所以只能在JRaft、ZAB、Apache Ratis中选择。首先,ZAB和Zookeeper强绑定。然后,JRaft支持多RaftGroup,而且可以让Nacos支持多数据分片。所以Nacos最终选择了JRaft这种强一致性协议。
Distro协议是阿里自研的⼀个最终⼀致性协议。最终⼀致性的协议有很多,比如Gossip、Eureka内的数据同步算法。而Distro协议是集Gossip以及Eureka协议的优点并加以优化出来的。
原生的Gossip协议:由于随机选取节点发送消息,所以存在重复发送消息给同⼀节点的问题。从而增加网络传输压力,也给消息节点带来额外处理负载。
Distro协议引入了权威Server的概念:也就是每个节点负责⼀部分数据以及将自己的数据同步给其他节点,从而有效地避免了消息冗余的问题。
(4)Nacos早期的⼀致性协议
先来看早期的Naocs版本的架构:
在Nacos早期的架构中,服务注册发现和配置管理的⼀致性协议是分开的,并没有下沉到Nacos的内核模块作为通用的能力来进行演进。
服务注册发现的⼀致性协议和服务注册发现的业务逻辑强耦合在⼀起,且充斥着服务注册发现的⼀些概念,使服务注册发现的整体逻辑难以维护。
由于服务注册发现的业务逻辑耦合了⼀致性协议层的数据状态,所以难以做到计算存储彻底分离,以及影响了计算层的无限水平扩容能力。
因此为了解决这个问题,必然要对Nacos的⼀致性协议进行抽象以及下沉,使一致性协议成为内核模块的功能,让服务注册发现模块只充当计算角色,同时为配置模块去外部数据库存储打下架构基础。
(5)Nacos当前的⼀致性协议
接着看当前的Nacos版本的架构:
在新的Nacos架构中,已完成了将⼀致性协议从原先的服务注册发现模块下沉到了内核模块中,并且提供了统⼀的抽象接口。使上层的服务注册发现模块和配置管理模块,不再需要耦合任何⼀致性语义。当解耦抽象分层后,每个模块都能快速演进,并且性能和可用性都实现大幅提升。
(6)Nacos如何做到⼀致性协议下沉的
Nacos如何做到将AP、CP协议下沉到内核模块中?
一.对⼀致性协议进行抽象
所谓⼀致性协议,就是用来保证数据的读写是⼀致的。⼀致性协议最基础的两个方法,就是写入数据的方法和读取数据的方法。
public interface ConsistencyProtocol<T extends Config, P extends RequestProcessor> extends CommandOperations {...//Obtain data according to the request.//@param request request//@return data {@link Response}//@throws Exception {@link Exception}Response getData(ReadRequest request) throws Exception;//Data operation, returning submission results synchronously.//@param request {@link com.alibaba.nacos.consistency.entity.WriteRequest}//@return submit operation result {@link Response}//@throws Exception {@link Exception}Response write(WriteRequest request) throws Exception;...
}
任何使用⼀致性协议的组件,都只需要使用getData()方法和write()方法即可。同时,⼀致性协议已经被抽象在了consistency的包中。Nacos对于AP、CP的⼀致性协议接口使用抽象都在里面。并且在实现具体的⼀致性协议时,采用了插件可插拔的形式,进⼀步将⼀致性协议的逻辑,从服务注册发现、配置管理模块中解耦。
public class ProtocolManager extends MemberChangeListener implements DisposableBean {...private void initAPProtocol() {ApplicationUtils.getBeanIfExist(APProtocol.class, protocol -> {Class configType = ClassUtils.resolveGenericType(protocol.getClass());Config config = (Config) ApplicationUtils.getBean(configType);injectMembers4AP(config);protocol.init((config));ProtocolManager.this.apProtocol = protocol;});}private void initCPProtocol() {ApplicationUtils.getBeanIfExist(CPProtocol.class, protocol -> {Class configType = ClassUtils.resolveGenericType(protocol.getClass());Config config = (Config) ApplicationUtils.getBean(configType);injectMembers4CP(config);protocol.init((config));ProtocolManager.this.cpProtocol = protocol;});}...
}
其实,仅对⼀致性协议进行抽象是不够的。因为此时服务注册发现、配置管理模块,还要依赖⼀致性协议的接口。服务注册发现、配置管理模块依然要在显式处理⼀致性协议的读写逻辑,以及要自己实现⼀个对接⼀致性协议的存储,这并不优雅。
服务发现以及配置模块,应该专注于数据的使用以及计算,而不是专注于数据如何存储、如何保障数据⼀致性。数据存储以及多节点⼀致的问题则应该交由存储层来保证。
为了降低⼀致性协议出现在服务注册发现、配置管理这两个模块中的频次,以及尽可能让⼀致性协议只在内核模块中感知,Nacos做了另⼀个处理——对数据存储进行抽象。
二.对数据存储进行抽象
⼀致性协议,就是用来保证数据⼀致的。
如果利用⼀致性协议实现存储接口,那么服务注册发现模块和配置管理模块,就由原来的依赖⼀致性协议接口转变为依赖存储接口。
而存储接口的具体实现,就比⼀致性协议要丰富得多了。并且这两个模块也无需为直接依赖⼀致性协议而承担多余的编码工作,比如快照处理、状态机实现、数据同步等编码工作,从而使得这两个模块可以更加专注自己的核心逻辑。
对于数据存储的抽象,以服务注册发现模块为例:
public interface KvStorage {enum KvType {//Local file storage.File,//Local memory storage.Memory,//LSMTree storage.LSMTree,AP,CP,}//获取⼀个数据byte[] get(byte[] key) throws KvStorageException;//存入⼀个数据void put(byte[] key, byte[] value) throws KvStorageException;//删除⼀个数据void delete(byte[] key) throws KvStorageException;...
}
由于服务注册发现模块的存储,更多是根据key去执行点查的操作,因此Key-Value类型的存储接口最适合不过。而Key-Value的存储接口定义好后,其实就是这个KVStore的具体实现了。
可以直接将KVStore的实现对接Redis,也可以直接对接DB。或者直接根据Nacos内核模块的⼀致性协议,在此基础上实现⼀个内存或者持久化的分布式强(弱)⼀致性KV。
通过功能边界将Nacos进程进⼀步分离为计算逻辑层和存储逻辑层,计算层和存储层之间的交互仅通过⼀层薄薄的数据操作胶水代码来处理。这样就在单个Nacos进程里实现了计算和存储逻辑的彻底分离。
同时,基于存储层的插件化设计:如果中小公司有运维成本要求,可以直接使用Nacos自带的内嵌分布式存储组件来部署⼀套Nacos集群。
如果中大型公司的服务实例数据、配置数据的量级很大,并且本身有⼀套比较好的Paas层服务,则完全可以重写已有的存储组件,从而实现Nacos计算层与存储层的彻底分离。
相关文章:
Nacos简介—4.Nacos架构和原理一
大纲 1.Nacos的定位和优势 2.Nacos的整体架构 3.Nacos的配置模型 4.Nacos内核设计之一致性协议 5.Nacos内核设计之自研Distro协议 6.Nacos内核设计之通信通道 7.Nacos内核设计之寻址机制 8.服务注册发现模块的注册中心的设计原理 9.服务注册发现模块的注册中心的服务数…...
splitchunk(如何将指定文件从主包拆分为单独的js文件)
1. 说明 webpack打包会默认将入口文件引入依赖js打包为一个入口文件,导致这个文件会比较大,页面首次加载时造成加载时间较长 可通过splitchunk配置相应的规则,对匹配的规则打包为单独的js,减小入口js的体积 2. 示例 通过正则匹配ÿ…...
MCP+A2A协议终极指南:AI系统构建技术全解析(医疗/金融实战+Streamable HTTP代码详解)
简介 2025年,MCP协议与A2A协议成为AI系统互联的核心技术。本文从通信机制到企业级应用,结合Streamable HTTP、零信任安全、多模态处理等最新技术,提供Go/Python/Java多语言实战代码,覆盖医疗诊断、金融风控等场景。含15+完整案例、性能优化方案及安全架构设计,助你掌握下…...
关于定时任务原理
关于定时任务原理 计算机是怎么计时的关于本地定时任务实现小根堆实现时间轮实现 关于分布式任务的实现管理未来的执行时间点 今天来聊一下工作中经常使用的定时任务的底层实现原理 计算机是怎么计时的 计算机内部使用多种方式来计时,主要依赖于硬件时钟࿰…...
【vue3】购物车实战:从状态管理到用户体验的全流程实现
在电商项目中,购物车是核心功能之一,需要兼顾数据一致性、用户体验和逻辑复杂度。 本文结合 Vue3 Pinia 技术栈,详细讲解如何实现一个高效且易用的购物车系统,重点剖析 添加购物车 和 头部购物车预览 的核心逻辑与实现细节。 一…...
日本IT|UIUX主要的工作都是哪些?及职业前景
在日本IT行业中,UI/UX(用户界面/用户体验)设计的工作涵盖从用户研究到界面实现的全流程,尤其在数字化服务、电商、金融科技等领域需求旺盛。 本篇是UI/UX在日本的主要工作内容、行业特点及职业前景分析: 一、UI/UX的主…...
Tailwind CSS 实战:基于 Kooboo 构建企业官网页面(二)
基于上篇内容,继续完善企业官网页面: Tailwind CSS 实战:基于 Kooboo 构建企业官网页面(一) 3.3 服务亮点:用于展示企业主要的服务项 1. 整体结构: <section class"py-16">&…...
第7章 内部类与异常类
7.1 内部类 在一个类中定义另一个类,这样的类称为内部类,包含内部类的类称为内部类的外部类。 关系: 内部类的外嵌类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外嵌类中的方法。 内部类的类体中不可以声明类变量和…...
优先队列、堆笔记(算法第四版)
方法签名描述构造函数MaxPQ()创建一个优先队列MaxPQ(int max)创建一个初始容量为 max 的优先队列MaxPQ(Key[] a)用 a[] 中的元素创建一个优先队列普通方法void insert(Key v)向优先队列中插入一个元素Key max()返回最大元素Key delMax()删除并返回最大元素boolean isEmpty()返回…...
7.14 GitHub命令行工具测试实战:从参数解析到异常处理的全链路测试方案
GitHub命令行工具测试实战:从参数解析到异常处理的全链路测试方案 GitHub Sentinel Agent 用户界面设计与实现:测试命令行工具 关键词:命令行工具测试, 接口集成测试, 参数化测试, 异常处理测试, 测试覆盖率分析 1. 命令行工具测试架构设计 通过三层测试体系保障 CLI 工具…...
使用CubeMX新建USART1不定长接收工程
目录 1、新建板级支持包 2、修改中断服务函数 3、修改main.c文件 4、程序流程 新建工程的基本操作步骤参考这里:STM32CubeMX学习笔记(6)——USART串口使用_unused(huart)-CSDN博客 1、新建板级支持包 在本地保存新建工程的文件夹中新建Us…...
【C++QT】Layout 布局管理控件详解
文章目录 一、QVBoxLayout 垂直布局1.1 特点1.2 常用方法1.3 应用场景1.4 示例代码 二、QHBoxLayout 水平布局2.1 特点2.2 常用方法2.3 应用场景2.4 示例代码 三、QGridLayout 网格布局3.1 特点3.2 常用方法3.3 应用场景3.4 示例代码 四、QFormLayout 表单布局4.1 特点4.2 常用…...
w~嵌入式C语言~合集6
我自己的原文哦~ https://blog.51cto.com/whaosoft/13870384 一、开源MCU简易数字示波器项目 这是一款采用STC8A8K MCU制造的简单示波器,只有零星组件,易于成型。这些功能可以涵盖简单的测量: 该作品主要的规格如下: 单片机…...
坐标转换:从WGS-84到国内坐标系(GCJ-02BD-09)
目录 🍅点击这里查看所有博文 随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记…...
快速上手 MetaGPT
1. MetaGPT 简介 在当下的大模型应用开发领域,Agent 无疑是最炙手可热的方向,这也直接催生出了众多的 Agent 开发框架。在这之中, MetaGPT 是成熟度最高、使用最广泛的开发框架之一。 MetaGPT 是一款备受瞩目的多智能体开发框架,…...
「Docker已死?」:基于Wasm容器的新型交付体系如何颠覆十二因素应用宣言
一、容器技术的量子跃迁 1. 传统容器体系的测不准原理 某金融平台容器集群真实数据: 指标Docker容器Wasm容器差异度冷启动时间1200ms8ms150倍内存占用256MB6MB42倍镜像体积780MB12MB65倍内核调用次数2100次/s23次/s91倍 二、Wasm容器的超流体特性 1. 字节码的量子…...
有源晶振输出匹配电阻选择与作用详解
一、输出匹配电阻的核心作用 阻抗匹配 减少信号反射:当信号传输线阻抗(Z0)与负载阻抗不匹配时,会发生反射,导致波形畸变(如振铃、过冲)。 公式:反射系数Γ (Z_L - Z0) / (Z_L Z0)…...
Shell脚本-while循环应用案例
在Shell脚本编程中,while循环是一种非常有用的控制结构,适用于需要基于条件进行重复操作的场景。与for循环不同,while循环通常用于处理不确定次数的迭代或持续监控某些状态直到满足特定条件为止的任务。本文将通过几个实际的应用案例来展示如…...
【JavaScript】二十七、用户注册、登陆、登出
文章目录 1、案例:用户注册页面1.1 发送验证码1.2 验证用户名密码合法性1.3 已阅读并同意用户协议1.4 表单提交 2、案例:用户登陆页面2.1 tab切换2.2 登陆跳转2.3 登陆成功与登出 1、案例:用户注册页面 1.1 发送验证码 需求:用户…...
Vue中Axios实战指南:高效网络请求的艺术
Axios作为Vue生态中最流行的HTTP客户端,以其简洁的API和强大的功能成为前后端交互的首选方案。本文将带你深入掌握Axios在Vue项目中的核心用法和高级技巧。 一、基础配置 1. 安装与引入 npm install axios 2. 全局挂载(main.js) import …...
SAP-pp 怎么通过底表的手段查找BOM的全部ECN变更历史
表:ABOMITEMS,查询条件是MAST的STLNR (BOM清单) 如果要得到一个物料的详细ECN历史,怎么办? 先在MAST表查找BOM清单,然后根据BOM清单在ABOMITEMS表里面查询组件,根据查询组件的结果…...
数据需求管理办法有哪些?具体应如何应用?
目录 一、数据需求管理的定义 二、数据需求管理面临的问题 1.需求理解偏差 2.需求变更频繁 3.需求优先级难以确定 4.数据质量与需求不匹配 三、数据需求管理办法的具体流程 1.建立有效的沟通机制 2.规范需求变更管理流程 3.制定需求优先级评估标准 4.加强数据质量管…...
单片机 + 图像处理芯片 + TFT彩屏 复选框控件
复选框控件使用说明 一、控件概述 本复选框控件是一个适用于单片机图形界面的UI组件,基于单片机 RA8889/RA6809 TFT显示屏 GT911触摸屏开发。控件提供了丰富的功能和自定义选项,使用简单方便,易于移植。 主要特点: 支持可…...
塔能合作模式:解锁工厂能耗精准节能新路径
在工厂寻求能耗精准节能的道路上,除了先进的技术,合适的合作模式同样至关重要。塔能科技提供的能源合同管理(EMC)和交钥匙方式(EPC),为工厂节能项目的落地实施提供了有力支持,有效解…...
使用PHP对接印度股票市场数据
在本篇文章中,我们将介绍如何通过StockTV提供的API接口使用PHP语言来获取并处理印度股票市场的数据。我们将以查询公司信息、查看涨跌排行榜和实时接收数据为例,展示具体的操作流程。 准备工作 首先,请确保您已经从StockTV获得了API密钥&am…...
make学习三:书写规则
系列文章目录 Make学习一:make初探 Make学习二:makefile组成要素 文章目录 系列文章目录前言默认目标规则语法order-only prerequisites文件名中的通配符伪目标 Phony Targets没有 Prerequisites 和 recipe内建特殊目标名一个目标多条规则或多个目标共…...
Arduino 入门学习笔记(五):KEY实验
Arduino 入门学习笔记(五):KEY实验 开发板:正点原子ESP32S3 例程源码在文章顶部可免费下载(审核中…) 1. GPIO 输入功能使用 1.1 GPIO 输入模式介绍 在上一文章中提及到 pinMode 函数, 要对…...
Grok发布了Grok Studio 和 Workspaces两个强大的功能。该如何使用?如何使用Grok3 API?
最近Grok又更新了几个功能:Grok Studio 和 Workspaces。 其中 Grok Studio 主要功能包括: 代码执行:在预览标签中运行 HTML 片段、Python、JavaScript 等。 Google Drive 集成:附加并处理 Docs、Sheets、Slides等文件。 协作工…...
学习spark总结
一、Spark Core • 核心功能:基于内存计算的分布式计算框架,提供RDD弹性分布式数据集,支持转换(如map、filter)和动作(如collect、save)操作。 • 关键特性:高容错性(L…...
LeetCode 24 两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。 示例 1: 输入:head [1,2,3,4] 输出:[2,1…...
Qt中的全局函数讲解集合(全)
目录 1.qAbs 2.qAsConst 3.qBound 4.qConstOverload 5.qEnvironmentVariable 6.qExchange 7.qFloatDistance 8.qInstallMessageHandler 在头文件<QtGlobal>中包含了Qt的全局函数,现在就这些全局函数一一详解。 1.qAbs 原型: template &…...
《明解C语言入门篇》读书笔记四
目录 第四章:程序的循环控制 第一节:do语句 do语句 复合语句(程序块)中的声明 读取一定范围内的值 逻辑非运算符 德摩根定律 德摩根定律 求多个整数的和及平均值 复合赋值运算符 后置递增运算符和后置递减运算符 练习…...
【每日随笔】文化属性 ② ( 高维度信息处理 | 强者思维形成 | 认知重构 | 资源捕获 | 进化路径 )
文章目录 一、高维度信息处理1、" 道 " - 高维度信息2、上士对待 " 道 " 的态度3、中士对待 " 道 " 的态度4、下士对待 " 道 " 的态度 二、形成强者思维1、认知重构 : 质疑本能 -> 信任惯性2、资源捕获 : 远神崇拜 -> 近身模仿3…...
terraform查看资源建的关联关系
一、使用 terraform graph 命令生成依赖关系图 该命令会生成资源间的依赖关系图(DOT 格式),需配合 Graphviz 工具可视化。 1. 安装 Graphviz # Ubuntu/Debian sudo apt-get install graphviz# MacOS brew install graphviz 2. 生成并查看…...
win11报错 ‘wmic‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件 的解决方案
方法一:检查环境变量 右键点击“此电脑”或“计算机”: 选择“属性”,然后点击“高级系统设置”。 进入环境变量设置: 在“系统属性”窗口中,点击“环境变量”。 检查Path变量: 在“系统变量”部分,找到并…...
监控易一体化运维:巡检管理,守护企业系统稳定的坚固防线
在数字化浪潮奔涌的当下,企业业务高度依赖信息技术系统,数据流量呈爆发式增长。从日常办公到核心业务运作,每一个环节都离不开稳定可靠的系统支持。在这种背景下,确保系统时刻处于最佳状态的重要性。而监控易的巡检管理功能&#…...
技能点总结
技能点总结 1、多线程导致事物失效的原因1.1 线程间竞争条件1.2 可见性问题1.3 原子性破坏1.4 死锁与活锁1.5 事务隔离级别问题1.5.1 脏读、不可重复读、幻读 1、多线程导致事物失效的原因 多线程环境下事物失效是一个常见问题,主要原因包括以下几个方面࿱…...
23种设计模式-行为型模式之命令模式(Java版本)
Java 命令模式(Command Pattern)详解 🧠 什么是命令模式? 命令模式是一种行为型设计模式,它将请求封装成一个对象,从而使你可以使用不同的请求、队列、日志请求以及支持可撤销的操作。 命令模式将请求的…...
聊一聊接口测试的核心优势及价值
目录 一、核心优势 提前发现问题,降低修复成本 高稳定性与维护效率 全面覆盖复杂场景 性能与安全测试的基石 高度自动化与高效执行 支持微服务与分布式架构 二、核心价值 加速交付周期及降低维护成本 提升质量与用户体验 增强安全性及促进团队间的协作 …...
大学之大:索邦大学2025.4.27
索邦大学:千年学术传承与现代创新的交响 一、前身历史:从巴黎大学到现代索邦的千年脉络 1. 中世纪起源:欧洲学术之母的诞生 索邦大学的历史可追溯至9世纪,其前身巴黎大学被誉为“欧洲大学之母”。1257年,神学家罗伯特…...
python文本合并脚本
做数据集本地化时,用到了文本txt合并问题,用了trae -cn ai辅助测试一下效果,还可以吧,但还是不如人灵光,反复的小错,如果与对成手,应该很简单,这里只做了测试吧,南无阿弥…...
Coding Practice,48天强训(25)
Topic 1:笨小猴(质数判断的几种优化方式,容器使用的取舍) 笨小猴__牛客网 #include <bits/stdc.h> using namespace std;bool isPrime(int n) {if(n < 1) return false;if(n < 3) return true; // 2和3是质数if(n % 2 0 …...
pytorch学习使用
1. 基础使用 1.1 基础信息 # 输出 torch 版本 print(torch.__version__)# 判断 cuda 是否可用 print(torch.cuda.is_available()) """ 2.7.0 False """1.2 创建tensor # 创建一个5*3的矩阵,初始值为0. print("-------- empty…...
《AI大模型应知应会100篇》第38篇:大模型与知识图谱结合的应用模式
第38篇:大模型与知识图谱结合的应用模式 摘要 随着大模型(如GPT、BERT等)和知识图谱技术的快速发展,两者的融合为构建更精准、可解释的智能系统提供了新的可能性。本文将深入探讨大模型与知识图谱的能力互补性、融合架构设计以及…...
TypeScript中的type
在 TypeScript 中,type 是一个非常重要的关键字,用于定义类型别名(Type Alias)。它允许你为一个类型创建一个新的名字,从而使代码更加简洁和可读。type 可以用来定义基本类型、联合类型、元组类型、对象类型等。以下是…...
数据库3,
describe dt drop table 删表 df delete from删行 usw update set where更新元素 iiv insert into values()插入行 sf select from选行 select *选出所有行 (ob order by 排序 由低到高 DESC由高到低 order by score&#…...
I-CON: A Unifying Framework for Representation Learning
1,本文关键词 I-Con框架、表征学习、KL散度、无监督分类、对比学习、聚类、降维、信息几何、监督学习、自监督学习、统一框架 2,术语表 术语解释I-Con本文提出的统一表征学习方法,全称Information Contrastive Learning,通过最…...
mybatis首个创建相关步骤
1。先关联数据库,用户,密码,数据库保持一致 2.添加包和类 1.User放和数据库属性一样的 package com.it.springbootmybatis01.pojo;lombok.Data lombok.AllArgsConstructor lombok.NoArgsConstructor public class User {private Integer i…...
vue3子传父——v-model辅助值传递
title: 子组件向父组件传值 date: 2025-04-27 19:11:09 tags: vue3 vue3子传父——v-model辅助值传递 一、子组件发出 1.步骤一创建emit对象 这个对象使用的是defineEmits进行的创建,emit的中文意思又叫发出,你就把他当成一个发出数据的函数方法来用…...
Golang | 向倒排索引上添加删除文档
syntax "proto3";package types;message Keyword {string Field 1; // 属性/类型/名称string Word 2; // 关键词 }message Document {string Id 1; //业务使用的唯一Id,索引上此Id不会重复uint64 IntId 2; //倒排索引上使用的文档id(业务侧不用管这…...