ZooKeeper 基础知识总结
先赞后看,Java进阶一大半
ZooKeeper 官网这样介绍道:ZooKeeper 是一种集中式服务,用于维护配置信息、命名、提供分布式同步和提供组服务。
各位hao,我是南哥,相信对你通关面试、拿下Offer有所帮助。
⭐⭐⭐一份南哥编写的《Java学习/进阶/面试指南》:https://github/JavaSouth
1. ZooKeeper的协议
1.1 ZAB协议
面试官:知道ZAB协议吗?
要深入学习ZooKeeper前,南哥认为我们要先学习ZooKeeper的核心理念,所有的ZooKeeper行为都是围绕这个核心来进行的。说了那么多,它就是——ZAB协议。
ZAB协议英文全称叫ZooKeeper Atomic Broadcast,我们透过中文含义可以大概了解他做了什么事情:ZooKeeper原子消息广播协议。
来看看原子广播在维基百科的解释。
在容错分布式计算中,原子广播或全序广播是指多进程系统中的所有正确进程都以相同顺序接收同一组消息(即相同的消息序列)的广播。
那ZooKeeper广播啥呢?我们知道ZooKeeper集群有Leader服务器、Follower服务器,这个Leader服务器接收了客户端所有的事务请求,事务请求可以是新增某一个ZNode节点,也可以是删除某一个ZNode节点。
这些事务请求的变更要不要提交、如何通知其他Follower服务器进行同步变更,这就是广播涉及的主要内容了。
ZAB协议主要包含了消息广播、崩溃模式,跟着南哥往下看看。
1.2 消息广播
面试官:消息广播你讲一讲?
ZAB协议的消息广播类似于二阶段提交过程。顾名思义事务最终的提交要分为两个阶段。
消息广播的流程如下:
(1)针对客户端的事务请求,Leader服务器会为其生成对应的事务Proposal,同时广播给集群中其余Followr机器。这个事务Proposal我们可以把他理解为事务提案。
(2)Follower服务器在接收到事务Proposal后会以事务日志形式写入到本地磁盘中,如果写入成功,则反馈一个Ack反馈给到Leader服务器。
(3)Leader服务器会收集其他Follower服务器的选票,只有半数的Follow服务器同意本次事务请求,那Leader服务器就会广播一个Commit消息,通知所有Follower服务器进行事务提交。
总结下来,也就是分为二个阶段,第一阶段是询问事务Proposal的写入尝试能否成功,第二阶段就是在Leader服务器、Follower服务器进行事务提交。
1.3 消息广播的缺点
面试官:那二阶段提交有什么缺点吗?
当然消息广播的二阶段提交有所缺点。
(1)在消息广播的第二阶段,如果有部分Follower服务器没有收到Leader服务器广播的事务提交消息,这就会出现数据不一致的情况了。
(2)单点问题。如果Leader服务器在第二阶段奔溃了,那其他Follower服务器仍然会处于锁定上一次事务资源的状态中。
(3)同步阻塞问题。参与一个客户端事务请求时,Leader、Follower服务器的其他逻辑都需要进行阻塞,直到等到上一个二阶段提交完成之后才会开始执行。
1.4. 崩溃模式
面试官:崩溃模式呢?
ZAB协议涉及Leader服务器、Follower服务器,Leader服务器充当了最重要的作用。如果Leader服务器崩溃了或者失去和Follwer服务器之间的联系,那上面南哥提到的二阶段提交各种问题很可能都会出现。
开头不是说ZAB协议包含了消息广播、崩溃模式?别慌,崩溃模式就是为此而生的。
崩溃模式总的来说就做了两个事情,我们记住这两点方便理解:一个是确保提交已经被Leader提交的事务Proposal,另一个是丢弃已经被跳过的事务Proposal。
(1)为了解决上文的第1点问题。Leader服务器会为每一个Follower服务器都准备一个Proposal消息队列,通过该队列发送那些没有被各Follower服务器同步的事务Proposal,同时在Proposal消息后面加上Commit消息让Follower服务器进行事务提交。这可以解决二阶段提交带来的数据不一致问题。
(2)为了解决上文的第2点问题。ZooKeeper设计了一个高32位的epoch,用来作为Leader服务器的标识;设计了一个低32位的事务偏移量ZXID,用来作为最新已提交事务的偏移量。
新的Leader服务器上线后,新的Leader服务器拥有集群里最大的事务偏移量,Leader服务器会和Follower服务器的ZXID进行比对,从而让Follower服务器回退被跳过的事务Proposal。
2. ZooKeeper数据模型
2.1 ZooKeeper数据节点
面试官:你说说ZooKeeper数据模型?
ZooKeeper的数据模型是一颗树结构,每一个树节点是一个数据节点,我们称它为ZNode。
而每一个ZNode的节点路径标识使用斜杠/
作为分隔符,我们可以在ZNode节点下写入数据、创建节点,这种斜杠/
作为路径分隔符的方式和Unix文件系统路径非常相似。
大家可以看下Unix文件系统路径,以斜杠/
作为路径分隔符。
# 根目录
/
# 可执行文件所在位置
/bin
# 设备驱动
/dev
这是ZooKeeper数据模型概念图,是不是非常类似呢?
另外ZooKepper这种斜杠/
作为路径分隔符正好和Windows相反,Windows使用的是反斜杠\
。
# Windows路径示例
C:\Java\jdk1.8.0_311
2.2 数据节点类型
面试官:那ZooKeeper数据节点有几种类型?
ZooKeeper一共有四种节点类型,但从整体来看主要是持久节点类型、临时节点类型这两种,另外两种类型只是在以上两种节点类型基础上增加了顺序的特性。大家这样理解会更方便记忆~
- 持久节点:这种数据节点一旦背创建后,就会一直存在于ZooKeeper服务器上,除非对该数据节点执行删除操作。
- 持久顺序节点:刚刚和大家说了,该节点类型就是在持久节点基础上增加了顺序的特性。如果在持久顺序节点类型的父节点创建子节点,ZooKeeper会为该子节点名加上一个数字后缀来维护子节点的顺序。
- 临时节点:临时节点比较特殊,它的生命周期是和客户端会话绑定在一起的。这个客户端可以是连接ZooKeeper的某一个终端命令窗口,也可以是连接ZooKeeper的某一个Spring服务线程。如果客户端会话失效了,那这个临时节点就会被自动清除。
- 临时顺序节点:在临时节点的基础上添加了顺序特性。
另外大家记住一点,临时节点只能作为叶子节点,是不能在临时节点下面创建任何子节点的。原因大概是临时节点子节点没有存在的意义,创建子节点的场景大多是基于持久节点的场景,这种设计也可以防止对临时节点的误用。
2.3 数据节点的版本
面试官:数据节点版本知道吧?
ZooKeeper数据节点的版本概念和CAS操作的版本概念是一样的,同样是在多线程环境下,通过乐观锁这种无锁操作来保证线程安全性。
当一个数据节点被创建后,该节点的version值为0,代表它被更新过0次,如果后续对该节点进行更新操作,那version便会递增。
对数据节点的每次更新,都会对比数据节点的version是否是预期值,只有符合预期值,才会将新值更新到该数据节点。
大家可以通过以下CAS例子代码来了解CAS操作的执行过程。
@Slf4j
public class CAS implements Runnable {private static AtomicInteger val = new AtomicInteger(0);private void compareSwap(int expectVal, int operateVal) {if (val.compareAndSet(expectVal, operateVal)) {log.info("the thread called {} operated", Thread.currentThread().getName());} else {this.run(); // 相当于获取不到锁则重新执行}}@Overridepublic void run() {int curVal = val.get();log.info("the thread called {} get val is {}", Thread.currentThread().getName(), curVal);compareSwap(curVal, curVal + 1);}public static void main(String[] args) throws InterruptedException {CAS cas0 = new CAS();CAS cas1 = new CAS();Thread thread0 = new Thread(cas0, "cas0");Thread thread1 = new Thread(cas1, "cas1");thread0.start();thread1.start();thread0.join();thread1.join();log.info("current thread name: {} , the value of val: {}", Thread.currentThread().getName(), val);}
}控制台打印:
[ INFO ]the thread called cas0 get val is 0
[ INFO ]the thread called cas1 get val is 0
[ INFO ]the thread called cas0 operated
[ INFO ]the thread called cas1 get val is 1
[ INFO ]the thread called cas1 operated
[ INFO ]current thread name: main , the value of val: 2
2.4 事务ID
面试官:ZooKeeper事务ID呢?
我们熟悉的数据库事务一般是包含对数据库状态的读写操作,数据库事务具有ACID特性:原子性、一致性、持久性、隔离性。数据库事务这块大家有不懂的可以看我往期文章《MySQL事务的性情很“原子“,要么执行要么不执行》。
但ZooKeeper的事务和数据库事务大相径庭。ZooKeeper事务一般是包括对数据节点的创建、删除、更新,也包括客户端会话创建、失效情况对临时节点的影响。
每一个事务请求,ZooKeeper都会为其分配一个全局唯一的事务ID,我们称它为ZXID。所以ZXID也可以间接反映出对数据节点操作的全局顺序,这个全局顺序在Follower服务器对Leader服务器的数据复制上相当重要,可以用来保证数据的一致性。
2.5 Watcher机制
面试官:ZooKeeper数据变更通知使用什么对象?
ZooKeeper拥有分布式通知的功能,这个功能是基于Watcher机制来实现的。一个Watcher对象就像一个订阅者,当订阅的主题状态发生变化,就会通知Watcher订阅者作出一定动作。
Watcher机制的工作流程,首先是客户端向ZooKeeper服务器注册Watcher通知,接着会将Watcher对象存储在客户端本身的WatchManager中。当ZooKeeper服务器触发Watcher事件后会向客户端发起通知,客户端就从本身的WatchManager取出对应的Watcher对象来执行回调操作。
Watcher机制的大致流程大家可以参考下图:
3. ZooKeeper分布式锁
3.1 排他锁实现分布式锁
面试官:知道Zookeeper有什么应用场景吗?
目前地球村里大型公司部署的分布式技术,绝大部分都是由Zookeeper提供底层的技术支持,所以Zookeeper多么重要就不用我多说了吧。
我们可以利用Zookeeper来完成分布式系统涉及的各种核心功能,例如以下4种:
-
数据发布/订阅。可以用来实现配置中心。
-
命名服务。类似于UUID,可以生成全局唯一的ID。
-
集群管理。每一个服务器是一个子节点,可以用来检测到集群中机器的上/下线情况。
-
分布式锁。
南哥先讲下我们可以怎么利用Zookeeper来实现分布式锁,要实现分布式锁,分为获取锁和释放锁两个步骤。
ZooKeepr获取锁时会在/exclusive_lock
节点下创建子节点,如果创建成功则获得锁。如果创建失败,则访问Zookeeper的客户端会在该节点注册一个Watcher监听
,用来实时监控子节点的变更从而重新获得锁,这有点类似于线程的循环等待。
当要释放锁时,Zookeeper会删除该子节点,此时/exclusive_lock
节点下就有空位了。Watcher监听则通知客户端可以重新创建子节点来获得锁资源。
3.2 共享锁实现分布式锁
面试官:你说的是排他锁,共享锁呢?
大家有没发现,上面分布式锁的实现方式是排他锁,我们也可以使用共享锁的实现方式,来看看两者的区别。
排他锁,又称为写锁或独占锁,是一种基本的锁类型。如果事务T1对数据对象O1加上了排他锁,那么在整个加锁期间,只允许事务T1对O1进行读取和更新操作,其他任何事务都不能再对这个数据对象进行任何类型的操作——直到T1释放了排他锁。
共享锁,又称为读锁,同样是一种基本的锁类型。如果事务T1对数据对象O1加上了共享锁,那么当前事务只能对O1进行读取操作,其他事务也只能对这个数据对象加共享锁——直到该数据对象上的所有共享锁都被释放。
Zookeeper以共享锁方式来实现分布式锁,每次读、写请求都会去创建子节点,这是一个类似于“/shared_lock/[Hostname]-请求类型-序号
”的临时顺序节点。
每一个要获得分布式锁的客户端都会去获取子节点列表,同时注册Watcher监听,读、写这两步有不同的步骤。
(1)获取读锁的话,如果前面比自己小的序号没有写请求,则表示可以读。
(2)获取写锁的话,只有在自己是序号最小的情况下,才可以读成功。
另外共享锁的释放锁和排他锁都是一样的,只需要删除所创建的子节点就可以。
3.3 共享锁羊群效应
面试官:有没听说过共享锁的羊群效应?
大家要注意下,共享锁来实现分布式锁,在集群规模比较大的场景下,可能会出现羊群效应。
什么是羊群效应?我们看看百度百科的解释。
羊群效应是个人的观念或行为由于真实的或想象的群体的影响或压力,而向与多数人相一致的方向变化的现象。
其实共享锁的特别之处,在于每次读、写请求都要注册Watcher监听来获取子节点列表,特别是数量更多的读请求,每1分钟可能是上百万次的请求。
以共享锁来实现,子节点列表只要每次一变动,就要通知所有的服务器客户端。这明显造成了短时间大量的事件通知,给Zookeeper带来的性能消耗是巨大的。
3.4 处理羊群效应
面试官:那怎么解决呢?
如何看待共享锁带来的羊群效应,我们从两个方面来看待。如果在集群不大的情况下羊群效应发生带来的影响不会太大,而且这种设计简单实用。
而如果在集群规模大的场景下,我们可以这样改进。客户端的读、写请求首先获取子节点列表,但都不注册Watcher监听。
(1)读请求:只向比自己序号小的最后一个写请求节点注册Watcher监听。
(2)写请求:只向比自己序号小的最后一个节点注册Watcher监听。
这样的设计就可以避免羊群效应,主要是从监听子节点列表,改进为只监听某个子节点。
3.5 Kafka应用场景
面试官:Kafka应用场景呢,知道Kafka是怎么利用Zookeeper吗?
南哥了解到的Kafka利用Zookeeper的主要有 4 点,我们来看看。
(1)使用Zookeeper来对所有Broker服务器、Topic进行管理。Broker启动后都会到Zookeeper上创建属于自己的临时节点,其节点路径为/broker/ids/[0…N]
,注册Topic节点也是一样。
(2)而在Kafka防止消费重复消费方面,消费者消费消息后,都会在消息分区写入临时节点,代表该消息已消费。
(3)另外在Kafka生产者负载均衡方面,Kafka消息生产者会通过监听Broker节点列表,负载均衡地分发到某一个Broker。
(4)在消费者负载均衡有两方面。一方面,每一个消费者服务器都会在Zookeeper创建消费者节点。当有新消息时,Kafka就可以通过Zookeeper的消费者节点列表负载均衡地通知某个消费者;另一方面,Kafka将一个Topic分成了多个分区,多个分区由不同的Broker处理,这是实现对Broker的负载均衡。
我是南哥,南就南在Get到你的点赞点赞点赞。
看了就赞,Java进阶一大半。点赞 | 收藏 | 关注,各位的支持就是我创作的最大动力❤️
相关文章:

ZooKeeper 基础知识总结
先赞后看,Java进阶一大半 ZooKeeper 官网这样介绍道:ZooKeeper 是一种集中式服务,用于维护配置信息、命名、提供分布式同步和提供组服务。 各位hao,我是南哥,相信对你通关面试、拿下Offer有所帮助。 ⭐⭐⭐一份南哥编写…...
npm库xss依赖的使用方法和vue3 中Web富文本编辑器 wangeditor 使用xss库解决 XSS 攻击的方法
npm库xss依赖的使用方法和vue3 中Web富文本编辑器 wangeditor 使用xss库解决 XSS 攻击的方法 1. npm库xss依赖的使用方法1.1 xss库定义1.2 xss库功能 2. vue3 中 wangeditor 使用xss库解决 XSS 攻击的方法和示例2.1 在终端执行如下命令安装 xss 依赖2.2 在使用 wangeditor 的地…...

微信小程序蓝牙writeBLECharacteristicValue写入数据返回成功后,实际硬件内信息查询未存储?
问题:连接蓝牙后,调用小程序writeBLECharacteristicValue,返回传输数据成功,查询硬件响应发现没有存储进去? 解决:一直以为是这个write方法的问题,找了很多相关贴,后续进行硬件日志…...

5G NR:带宽与采样率的计算
100M 带宽是122.88Mhz sampling rate这是我们都知道的,那它是怎么来的呢? 采样率 子载波间隔 * 采样长度 38.211中对于Tc的定义, 在LTE是定义了Ts,在NR也就是5G定义了Tc。 定义这个单位会对我们以后工作中的计算至关重要。 就是在…...
go 和java 编写方式的理解
1. go 推荐写流水账式的代码(非贬义),自己管自己。java喜欢封装各种接口供外部调用,让别人来管自己。 2. 因为协程的存在, go的变量作用域聚集在方法内部,即函数不可重入,而java线程的限制&…...
C# 7.1 .Net Framwork4.7 VS2017环境下,方法的引用与调用
方法的调用比较好理解,就是给方法传递实参,执行方法代码。 方法引用涉及委托,委托签名与其引用的方法必须一致。以下demo说明方法调用与引用在写程序时的区别: using System; using System.Collections.Generic; using System.L…...

etcd、kube-apiserver、kube-controller-manager和kube-scheduler有什么区别
在我们部署K8S集群的时候 初始化master节点之后(在master上面执行这条初始化命令) kubeadm init --apiserver-advertise-address10.0.1.176 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.16.0 --service…...
每日一题 LCR 057. 存在重复元素 III
LCR 057. 存在重复元素 III 滑动窗口二分查找 有序集合 有lower_bound(num) ,可以找到第一个大于其的数字 class Solution { public:bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {set<long> win;for(int i0;i<nums.size();i){a…...

使用IDEA编写测试用例,复杂度校验
最近我们公司要求开发人员必须写测试用例,组织了TDD培训,测试驱动开发,同时衡量代码的圈复杂度,我记录下初次使用的过程。 编写测试用例,查看用例覆盖度 1、要编写测试用例,并看下测试用例的覆盖度&#…...

搭建私有云存储
1、安装LNMP环境 yum install nginx -y yum install -y nginx mariadb-server php php-fpm php-mysqlnd systemctl restart nginx.service --- 启动Nginx systemctl start mariadb.service ---启动数据库 mysql -e create database lxdb character set utf8 ---创建数据库 my…...

【从零开始的LeetCode-算法】3304. 找出第 K 个字符 I
Alice 和 Bob 正在玩一个游戏。最初,Alice 有一个字符串 word "a"。 给定一个正整数 k。 现在 Bob 会要求 Alice 执行以下操作 无限次 : 将 word 中的每个字符 更改 为英文字母表中的 下一个 字符来生成一个新字符串,并将其 追加 到原始的…...
深入解析分布式遗传算法及其Python实现
目录 深入解析分布式遗传算法及其Python实现目录第一部分:分布式遗传算法的背景与原理1.1 遗传算法概述1.2 分布式遗传算法的引入1.3 分布式遗传算法的优点与挑战优点:挑战:第二部分:分布式遗传算法的通用Python实现2.1 基本组件的实现第三部分:案例1 - 基于多种交叉与变异…...

gitee:创建仓库,存入本地文件至仓库
一、git下载 git:下载与安装-CSDN博客https://blog.csdn.net/weixin_46001736/article/details/144107485?sharetypeblogdetail&sharerId144107485&sharereferPC&sharesourceweixin_46001736&spm1011.2480.3001.8118 二、创建仓库 1、主页面->右上角新增…...

计算分数的浮点数值
计算分数的浮点数值 C语言代码C 代码Java代码Python代码 💐The Begin💐点点关注,收藏不迷路💐 两个整数a和b分别作为分子和分母,既分数 a/b ,求它的浮点数值(双精度浮点数,保留小数点…...
在 C/C++ 中,volatile 关键字的作用是什么?.volatile 关键字与 const 关键字有什么区别?
volatile关键字用于告诉编译器,被修饰的变量可能会被程序以外的因素(如硬件、操作系统等)修改,因此每次访问该变量时都应该从内从中读取他的值,而不是使用可能存在的缓存之,这在多线程编程,与硬…...

golang debug调试
1. 本地调试 1:Add Configurations 添加配置文件(Run kind :Directory) 2:进入run运行窗口 3:debug断点调试模式 1. Resume Program (继续运行) 图标: ▶️ 或 ► 快捷键: F9(Windows/Linux&a…...

自动化运维(k8s)之微服务信息自动抓取:namespaceName、deploymentName等全解析
前言:公司云原生k8s二开工程师发了一串通用性命令用来查询以下数值,我想着能不能将这命令写成一个自动化脚本。 起初设计的 版本一:开头加一条环境变量,执行脚本后,提示输入:需要查询的命名空间,…...

07 初始 Oracle 优化器
查询优化器,简称优化器,是数据库最核心的组件之一。我们在这个系列的第一篇文章中已经给大家介绍了,优化器会参与到SQL语句的解析过程中,用来生成SQL语句的执行计划,直接决定SQL语句执行性能的优劣。 什么是执行计划 …...
Java对象与XML互相转换(xstream)
依赖 <dependency><groupId>com.thoughtworks.xstream</groupId><artifactId>xstream</artifactId><version>1.4.18</version></dependency> 实体类 package com.itheima.util;import lombok.AllArgsConstructor; import lom…...

一键生成唯美动漫图:ComfyUI-tPonynai详细搭建教程
tPonynai 是在 C 站上开源的动漫风格扩散模型,与其他基础大模型一样,只需要输入适当的正面和负面提示词就能够实现动漫图片的生成。截至目前已经有 12.9k 的下载量,生成效果也非常不错。本文将介绍ComfyUI-tPonynai在算家云搭建以及本地部署的…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...

Ubuntu系统多网卡多相机IP设置方法
目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机,交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息,系统版本:Ubuntu22.04.5 LTS;内核版本…...

【PX4飞控】mavros gps相关话题分析,经纬度海拔获取方法,卫星数锁定状态获取方法
使用 ROS1-Noetic 和 mavros v1.20.1, 携带经纬度海拔的话题主要有三个: /mavros/global_position/raw/fix/mavros/gpsstatus/gps1/raw/mavros/global_position/global 查看 mavros 源码,来分析他们的发布过程。发现前两个话题都对应了同一…...