经典组件知识(zookeeper,kafka,ngix)

news2024/11/24 9:02:53

关于zookeeper的具体介绍 优化的点可以在于zookeeper吗?
如何安装使用?
#include <zookeeper/zookeeper.h>
1、先配置java环境JDK,因为需要用java编译;
2、下载zk源码,解压;
3、重命名配置文件zoo_sample.cfg
4.启动zookeeper,检测是否成功启动,用zookeeper客户端连接下服务端

安装好之后如何用在C++客户端呢?zk是有C风格的API的,我们可以自定义类实现C++的。
首先要在定义类的时候包含zookeeper头文件,里面包含了zk常用的接口。然后链接时要指定链接zk_mt库(多客户端)
服务端调用代码:生成一个zk类,开启,发布节点(包括服务和方法,服务是永久节点,方法是临时节点,还会加ip+port)

  //把当前rpc节点上要发布的服务全部注册到zk上面,让rpc client可以从zk上发现服务
    ZookeeperClient zk_client;
    zk_client.start();

    //在配置中心中创建节点
    for (auto &sp : service_map_)
    {
        string service_path = "/" + sp.first;
        zk_client.create(service_path.c_str(), nullptr, 0);
        for (auto &mp : sp.second.method_map_)
        {
            string method_path = service_path + "/" + mp.first;
            char method_path_data[128] = {0};
            sprintf(method_path_data, "%s:%d", ip.c_str(), port);
            //ZOO_EPHEMERAL 表示znode时候临时性节点
            zk_client.create(method_path.c_str(), method_path_data, strlen(method_path_data), ZOO_EPHEMERAL);
        }
    }

客户端:只要使用get_data方法就可以实现找到服务器的ip+port

 //获取ip和port
    ZookeeperClient zk_client;
    zk_client.start();
    string method_path = "/" + service_name + "/" + method_name;
    string host_data = zk_client.get_data(method_path.c_str());

这里的zookeeper类如下:主要是定义了开始函数,创建节点函数和获取数据函数,当然还有一个zk句柄

#pragma once
#include <semaphore.h>
#include <zookeeper/zookeeper.h>
#include <string>
using namespace std;
class ZookeeperClient
{
public:
    ZookeeperClient();
    ~ZookeeperClient();

    //启动连接--》zkserver
    void start();
    //在zkserver 根据指定的path创建znode节点
    void create(const char *path, const char *data, int datalen, int state = 0);
    //根据参数指定的znode节点路径,获取znode节点的值
    string get_data(const char *path);
private:
    //zk的客户端句柄
    zhandle_t *zhandle_;
};

其中构造函数就是给句柄初始化NULL,析构函数就是释放句柄 zookeeper_close(zhandle_);
启动zk

void ZookeeperClient::start()
{
    string host = RpcApplication::get_instance().get_configure().find_load("zookeeper_ip");
    string port = RpcApplication::get_instance().get_configure().find_load("zookeeper_port");
    string con_str = host + ":" + port;
    cout << con_str << endl;
    zhandle_ = zookeeper_init(con_str.c_str(), global_watcher监视点函数,功能就是看看连接状态是不是成功,成功就获取句柄信号量,进行sem_post同步一下,信号量加1, 30000过期时间, nullptr, nullptr, 0);
    if (zhandle_ == nullptr)
    {
        RPC_LOG_FATAL("zookeeper init error");
    }
    sem_t sem;
    sem_init(&sem, 0, 0);
    zoo_set_context(zhandle_, &sem); //设置信号量s
    sem_wait(&sem);  //这个相当于要么得到资源信号量减1,要么阻塞等待
    RPC_LOG_INFO("zookeeper init success");
}

可以看到其实是调用了zk原有的接口zookeeper_init函数,生成句柄。然后有一些信号量同步操作,具体意义是什么还不清楚我。

创建节点函数也是同步检查path是否存在flag = zoo_exists(zhandle_, path, 0, nullptr);不存在调用zoo_create函数。获取数据也是用了zoo_get函数。
谈一下你对zk的理解:
zk是一个开源的分布式协调服务,为分布式提供一致性的软件。实现诸如数据发布/订阅负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
我的项目没有涉及到zk集群的概念,只是数据的发布和订阅,利用create,getdata函数比较简单。
zk的好处是把一些复杂容易出错(尤其是强一致性的服务)的关键服务封装成简单的接口,使用简单。
zk主要组成成分是
文件系统:类似于普通文件系统,特别的是目录节点也可以存储数据,为了低延迟,一般数据长度有限1M左右,节点分为永久节点(除非手动删除,否则节点一直存在于 Zookeeper 上)和临时节点。临时节点是客户端建立的,一旦客户端断开连接,客户端就失效了。还有永久顺序和临时顺序,节点名后边会追加一个由父节点维护的自增整型数字。(四种节点类型)
通知机制;watcher机制。Zookeeper 允许客户端向服务端的某个 Znode 注册一个 Watcher 监听,当服务端的一些指定事件触发了这个 Watcher,服务端会向指定客户端发送一个事件通知来实现分布式的通知功能,然后客户端根据 Watcher 通知状态和事件类型做出业务上的改变。
(这里讲的是单个实例的,主要是文件系统和通知机制,下面会讲集群,也就是主节点和从节点以及观察者节点)

zk如何保证一致性的?
有序性是 zookeeper 中非常重要的一个特性,所有的更新都是全局有序的,每个更新都有一个唯一的时间戳,这个时间戳称为 zxid(Zookeeper Transaction Id)。而读请求只会相对于更新有序,也就是读请求的返回结果中会带有这个 zookeeper 最新的 zxid。

zk如何保证权限安全的
比如Linux,redis都是UGO模式,user/group/others。粗粒度
ACL访问控制列表权限机制,是一种细粒度的,更安全。具体表现在可以根据ip地址,或者账号密码,或者root等模式。每种模式的读写删除管理节点权限不一样。以及管理对象是一个实体。

zk实例有哪些角色?
leader 核心节点,处理请求,同步数据,调度(为什么要有主节点,可以避免重复计算)
follower 写请求转发给leader,参与投票
observer 不参与投票。为了增加提升集群的非事务处理能力
数据同步是用了ZAB协议

leader宕机会重新选leader。

ZAB 协议是为分布式协调服务 Zookeeper 专门设计的一种支持崩溃恢复的原子广播协议。ZAB 协议包括两种基本的模式:崩溃恢复(leader宕机,超过半数节点宕机,重启系统)和消息广播。当集群中超过半数机器与该 Leader 服务器完成数据同步之后,退出恢复模式进入消息广播模式,Leader 服务器开始接收客户端的事务请求生成事物提案来进行事务请求处理。
数据同步也分为全量同步,差异化同步,回滚再同步等方式,具体没研究过。
ZAB和raft区别联系
因为raft比zab出来晚点,可能raft 里面的有些东西会借鉴zab协议,本质上都是维护一个replicated log。核心都是日志复制,也就是数据同步。raft比zab实现要简单一些。
相同点:
1、采用quorum来确定整个系统的一致性(也就是对某一个值的认可),这个quorum一般实现是集群中半数以上的服务器,zookeeper里还提供了带权重的quorum实现.
2 写操作都是在leader上写
3、选哪个为Leader类似的,raft是term+log index,zab是quorum最新的作为leader。
4.都有心跳机制查看leader是否存活,以及超时时间。
不同点
zab用的是epoch和count的组合来唯一表示一个值, 而raft用的是term和index
raft协议数据只有单向地从leader到follower(成为leader的条件之一就是拥有最新的log), 而zab的zookeeper实现中 ,一个prospective leader需要将自己的log更新为quorum里面最新的log,然后才好在synchronization阶段将quorum里的其他机器的log都同步到一致.
总结一下:都是为了分布式系统中一致性的协议。核心都是日志复制和leader选举机制。
不同点在于选leader标准不同,以及leader强势程度不同,raft强leader导致实现更简单。
另外,raft可以实现强一致性(线性一致性读),ZAB不知道能不能。

两阶段提交和三阶段提交
见分布式事务那一篇文章

数据发布订阅系统/配置中心/本项目注册发现中心
特点:数据量较小,配置可能会更新。
基于 Zookeeper 的实现方式
· 数据存储:将数据(配置信息)存储到 Zookeeper 上的一个数据节点
· 数据获取:应用在启动初始化节点从 Zookeeper 数据节点读取数据,并在该节点上注册一个数据变更 Watcher
· 数据变更:当变更数据时,更新 Zookeeper 对应节点数据,Zookeeper会将数据变更通知发到各客户端,客户端接到通知后重新读取变更后的数据即可。

zk实现分布式锁

1、zookeeper中规定,在同一时刻**,不能有多个客户端创建同一个节点**,我们可以利用这个特性实现分布式锁。zookeeper临时节点只在session生命周期存在,session一结束会自动销毁。
2、watcher机制,在代表锁资源的节点被删除,即可以触发watcher解除阻塞重新去获取锁,这也是zookeeper分布式锁较其他分布式锁方案的一大优势。
第一种基于临时节点。只有获得锁的A线程可以创建节点。其他的阻塞并设置监听,A结束后自动删除节点,其他线程重新竞争。
这种方案会产生惊群现象,影响性能。
第二种基于顺序临时节点,每个节点只监听上一个节点的信息,最小序号的获得锁,结束后删除自己,那么第二小的监听到了就去获得锁。

消息队列的作用
解耦、削峰、 异步(非必要逻辑异步运行,加快响应速度)

kafka
首先有个topic的概念,类似于表。
Partition 分区:一个topic下面有多个分区,这些分区会存储到不同的服务器上面,或者说,其实就是在不同的主机上建了不同的目录。多个分区多个线程,多个线程并行处理肯定会比单线程好得多。Topic 也是逻辑概念,而 Partition 就是分布式存储单元。

在这里插入图片描述
Replica 副本机制:Partition 为了保证数据安全,所以每个 Partition 可以设置多个副本。
而且其实每个副本都是有角色之分的,它们会选取一个副本作为 Leader,而其余的作为 Follower。

我们的生产者在发送数据的时候,是直接发送到 Leader Partition 里面,然后 Follower Partition 会去 Leader 那里自行同步数据,消费者消费数据的时候,也是从 Leader 那去消费数据的。

Consumer Group 消费者组:
我们在消费数据时会在代码里面指定一个 group.id,这个 id 代表的是消费组的名字。不同组可有唯一的一个消费者去消费同一主题的数据。

Kafka 也是主从式的架构,主节点就叫 Controller,其余的为从节点,Controller 是需要和 Zookeeper 进行配合管理整个 Kafka 集群。
broker分布式部署,就需要一个注册中心来进行统一管理。Zookeeper用一个专门节点保存Broker服务列表,也就是 /brokers/ids。broker在启动时,向Zookeeper发送注册请求,Zookeeper会在/brokers/ids下创建这个broker节点,如/brokers/ids/[0…N],并保存broker的IP地址和端口。
这个节点临时节点,一旦broker宕机,这个临时节点会被自动删除。
Zookeeper也会为topic分配一个单独节点,每个topic都会以/**brokers/topics/[topic_name]**的形式记录在Zookeeper。一个topic的消息会被保存到多个partition,这些partition跟broker的对应关系也需要保存Zookeeper。当分区的leader故障转移也需要zookeeper参与。
消费者组也会向Zookeeper进行注册,Zookeeper会为其分配节点来保存相关数据,节点路径为/consumers/{group_id}
Controller的选举工作依赖于Zookeeper,选举成功后,Zookeeper会创建一个/controller临时节点。

控制器用来监听分区变化(元数据变化,Leader故障,增减分区)、topic变化、broker变化。

kafka缺点就是:需要同时部署两个系统。而且分区增加时,Zookeeper集群压力变大,达到一定级别后,监听延迟增加,给Kafaka的工作带来了影响。并且单个控制节点如果节点故障,新的Controller选举成功后,会重新从Zookeeper拉取元数据进行初始化,并且需要通知其他所有的broker更新ActiveControllerId。老的Controller需要关闭监听、事件处理线程和定时任务。分区数非常多时,这个过程非常耗时,而且这个过程中Kafka集群是不能工作的。
(有新的采用多个控制节点,用raft协议保证他们的一致性)

Kafka 性能好在什么地方?

1、磁盘顺序写。随机写的话是在文件的某个位置修改数据,性能会较低。

2、零拷贝技术。下面是非零拷贝,数据要从内核状态拷贝到kafka进程空间,再拷贝到socket的缓存。耗时比较高。
Kafka 利用了 Linux 的 sendFile 技术(NIO),省去了进程切换和一次数据拷贝,让性能变得更好。内核的数据直接发送到网卡了。

零拷贝技术要多说一点。C++的vector也涉及到零拷贝,比如emplace_back是零拷贝,因为不用拷贝一个临时对象,采用的是右值引用?尤其是当涉及到很大的数据拷贝非常消耗时空资源

而这里网络中的零拷贝:
传统的:read首先DMA从磁盘拷贝到内核页缓存,再拷贝到用户空间。write先从用户拷贝到socket内核缓存,再拷贝到网卡;
mmap:零拷贝的一种。主要思想是把内核空间和用户态共享,就不用拷贝到用户态,上下文切换。
sendfile:Linux2.1内核开始引入了sendfile函数,用于将文件通过socket传送。主要优化是在内核socket缓冲区中记录当前要发生的数据在page buffer中的位置和偏移量。这样直接从page buf就可以发到网卡,没有拷贝的过程。
在这里插入图片描述

3、日志分段存储 Kafka 规定了一个分区内的 .log 文件最大为 1G,做这个限制目的是为了方便把 .log 加载到内存去操作。 其实redis对于主从复制时RDB文件的大小也会有限制,不然加载到内存很慢。

4、Kafka 的网络设计
在这里插入图片描述

加强版的 Reactor 网络线程模型。是一个三层的设计 prosessors-qequest-线程池。
acceptor不进行处理而是封装成channel给processors。然后消费者线程去消费这些 socketChannel 时,会获取一个个 Request 请求,里面包含了数据,然后线程池来读取。
所以如果我们需要对 Kafka 进行增强调优,增加 Processor 并增加线程池里面的处理线程,就可以达到效果。

ngix

是一个http代理和反向代理的web服务器,内存少15MB启动快高并发。还可以实现负载均衡和动静分离
应用场景:
1、做http服务器,静态的网站,例如说:我们使用的OpenVPN。
2、反向代理实现负载均衡。当网站的访问量达到一定程度后,单台服务器不能满足用户的请求时,需要用多台服务器集群可以使用nginx做反向代理,并且多台服务器可以平均分担负载。它会让客户端感觉不到,依然输入原来的网址。
3、安全配置防火墙功能

处理请求的流程
启动时读取配置文件得到需要监听的ip,port。然后主进程会创建好套接字(socket,bind,listen)
然后fork出很多子进程,竞争accept新的连接,这个时候客户端就可以和ngix建立三次握手了。某一个子进程会 accept 成功,得到这个建立好的连接的 Socket ,然后创建 nginx 对连接的封装
接着,设置读写事件处理函数,并添加读写事件来与客户端进行数据的交换。最后,Nginx 或客户端来主动关掉连接,到此,一个连接就寿终正寝了

高并发的原因:因为webserver是IO密集型的,主要是网络IO。所以也是用到了IO复用+异步非阻塞IO

也是用到了单线程+epoll和redis一样。

动静分离根据静态资源的特点将其做缓存操作,这就是网站静态化处理的核心思路
严格意义上,可以理解成使用nginx处理静态页面,tomcat或PHP处理动态页面。静态资源就是多次访问,源代码不变的(CSS,jpg、js)动态资源:当用户多次访问这个资源,资源的源代码可能会发送改变。

当然,因为现在七牛、阿里云等 CDN 服务已经很成熟,主流的做法,是把静态资源缓存到 CDN 服务中,从而提升访问速度。
相比本地的 Nginx 来说,CDN 服务器由于在国内有更多的节点,可以实现用户的就近访问。并且,CDN 服务可以提供更大的带宽,不像我们自己的应用服务,提供的带宽是有限的。

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

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

相关文章

5000 字手把手实战|Kubernetes+极狐GitLab CI,获得极致 CI/CD 体验

目录 极狐GitLab CI K8s 架构解析 极狐GitLab CI 流程图 流程详解 极狐GitLab CI K8s 架构优点 开启极狐GitLab CI K8s 实战 环境准备 记录注册信息 获取极狐GitLab Runner 绑定 docker.sock 配置缓存 安装极狐GitLab Runner 集成 CI 定义文件 注意事项 配置…

Python实战基础11-函数

1 函数的创建于调用 1.1 创建一个函数 创建函数也称为定义函数&#xff0c;定义函数的格式如下&#xff1a; def functionname([parameterlist]): [comments] [functionbody] 参数说明&#xff1a; functionname&#xff1a;函数名称&#xff0c;在调用函数时使用。 paramete…

用echarts绘制的柱状图、折柱结合图,源码文末免费拿!

文章目录 Apache EchartsNPM 安装 ECharts在线定制 ECharts使用 Echarts 绘制基础柱状图绘制带背景的柱状图绘制带背景的柱状图绘制多条柱状图绘制条形柱状图绘制带标记的柱状图绘制折线图和柱状图绘制多轴折线图和柱状图源码地址 Apache Echarts 本文中的所有代码&#xff0c…

剑指offer(C++)-JZ46:把数字翻译成字符串(算法-动态规划)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 有一种将字母编码成数字的方式&#xff1a;a->1, b->2, ... , z->26。 现在给一串数字&#xf…

如何在Angular应用程序中插入自定义 CSS?这里有答案!

Kendo UI for Angular是专用于Angular开发的专业级Angular组件&#xff0c;telerik致力于提供纯粹的高性能Angular UI组件&#xff0c;无需任何jQuery依赖关系。 Kendo UI R1 2023正式版下载(Q技术交流&#xff1a;726377843&#xff09; 为什么需要在 Angular 应用程序中插入…

兼容性测试点和注意项,建议收藏

一&#xff1a;兼容性测试的概念&#xff1a;就是验证开发出来的程序在特定的运行环境中与特定的软件、硬件或数据相组合是否能正常运行、有无异常的测试过程。 二&#xff1a;兼容性测试的分类&#xff1a; &#xff08;1&#xff09;浏览器兼容性测试 指的是在浏览器上检查…

航空公司预订票数学建模论文

航空公司预订票数学建模论文篇1 试谈机票订票模型与求解 一、概述 1. 问题背景描述 在激烈的市场竞争中&#xff0c;航空公司为争取更多的客源而开展的一个优质服务项目是预订票业务,本模型针对预订票业务&#xff0c;建立二元规划订票方案&#xff0c;既考虑航空公司的利润最大…

form-create和form-create-designer创建自定义组件

在项目中&#xff0c;我需要使用表单设计器form-create-designer设计带有选择用户的弹窗组件&#xff0c;而设计器内置的组件不能满足需求&#xff0c;因此要创建自定义组件。form-create 支持在表单内部生成任何 vue 组件。 1.开发选择用户的组件 SelectUser.vue <!--用户…

论文《Diagnostic accuracy of CT imaging parameters in pelvic lipomatosis》案例分析

一、引言 在该篇文章的引言部分&#xff0c;作者明确阐述了本篇论文的研究目的、问题和方法&#xff0c;并指出了研究的贡献和创新点。以下是具体内容&#xff1a; 研究目的&#xff1a;本研究的目的是评估盆腔脂肪肥大的CT成像特征&#xff0c;并探讨其在诊断和管理中的应用…

Java程序设计入门教程--包

情形 在Java中&#xff0c;包(package)是一种松散的类的集合&#xff0c;它可以将各种类文件组织在一起&#xff0c;就像磁盘的目录&#xff08;文件夹&#xff09;一样。包的管理机制提供了类的多层次命名空间避免了命名冲突问题&#xff0c;解决了类文件的组织问题&#xff0…

Midjourney AI绘画中文教程(完整版)

我有一种预感&#xff0c;这篇内容一定会破万~~~ Midjourney AI绘画中文教程&#xff0c;Midjourney是一款2022年3月面世的AI绘画工具&#xff0c;创始人是David Holz。 只要输入想到的文字&#xff0c;就能通过人工智能产出相对应的图片&#xff0c;耗时只有大约一分钟&…

Linux Shell 实现部署单机Oracle 21C

oracle前言 Oracle开发的关系数据库产品因性能卓越而闻名&#xff0c;Oracle数据库产品为财富排行榜上的前1000家公司所采用&#xff0c;许多大型网站也选用了Oracle系统&#xff0c;是世界最好的数据库产品。此外&#xff0c;Oracle公司还开发其他应用程序和软件。同时&#…

《Spring Guides系列学习》guide1 - guide5

要想全面快速学习Spring的内容&#xff0c;最好的方法肯定是先去Spring官网去查阅文档&#xff0c;在Spring官网中找到了适合新手了解的官网Guides&#xff0c;一共68篇&#xff0c;打算全部过一遍&#xff0c;能尽量全面的了解Spring框架的每个特性和功能。 开始吧&#xff0…

UDP就一定比TCP快吗?

前言 话说&#xff0c;UDP比TCP快吗&#xff1f; 相信就算不是八股文老手&#xff0c;也会下意识的脱口而出&#xff1a;”是“。 但这也让人好奇&#xff0c;用UDP就一定比用TCP快吗&#xff1f;什么情况下用UDP会比用TCP慢&#xff1f; 我们今天就来聊下这个话题。 使用…

关于使用--- pyinstaller---无法打包py文件为exe的问题集合

目录 安装 pyinstaller 问题1&#xff1a; 解决办法&#xff1a; CMD中输入 问题2&#xff1a; 解决办法&#xff1a; CMD中输入 问题3&#xff1a; 将py文件打包成exe中&#xff0c;需要按照如下在CMD中输入 PyInstaller介绍 PyInstaller是一个Python库&#xff0c;可以…

智慧档案馆八防是怎么建设的?都需要注意哪些内容

智慧档案馆八防环境监控系统一体化解决系统方案 智慧档案库房一体化平台通过智慧档案管理&#xff0c;实现智慧档案感知协同处置功能&#xff1b;实现对档案实体的智能化识别、定位、跟踪监控&#xff1b;实现对档案至智能密集架、空气恒湿净化一体设备、安防设备&#xff0c…

基于java用队列实现栈

基于java用队列实现栈 问题描述 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压入栈顶。 int …

C++第六章:函数

函数 一、函数基础1.0 简介形参和实参形参列表函数的返回类型 1.1 局部对象自动对象局部静态对象 1.2 函数声明在头文件中进行函数声明 1.3 分离式编译编译和链接多个源文件 二、参数传递2.1 传值参数指针形参 2.2 传引用参数使用形参返回额外信息 2.3 const形参和实参指针或引…

「实在RPA·人社数字员工」促进人力社保数字办公战略转型

一、人力社保部门数字化转型的重要性 伴随着国家放宽人力资源市场准入条例&#xff0c;多次出台相关扶持政策&#xff0c;市场竞争加剧&#xff0c;后疫情时代格局的大变局&#xff0c;如何提高服务质量和效率&#xff0c;如何降本增效&#xff0c;成为人力资源和社会保障行业…

【算法】不使用LinkedHashMap实现一个LRU缓存

文章目录 什么是LRU&#xff1f;设计思路代码实现 LRU是我在面试过程中遇到的比较多的算法题了&#xff0c;并且我自己的项目中也手写了LRU算法&#xff0c;所以觉得还是有必要掌握一下这个重要的算法的。 什么是LRU&#xff1f; LRU是一种缓存淘汰策略。 我们知道&#xff0…