首页 文章 精选 留言 我的

精选列表

搜索[vnc客户端],共10000篇文章
优秀的个人博客,低调大师

Zookeeper之Zookeeper底层客户端架构实现原理(转载)

Zookeeper的Client直接与用户打交道,是我们使用Zookeeper的interface。了解ZK Client的结构和工作原理有利于我们合理的使用ZK,并能在使用中更早的发现问题。本文将在研究源码的技术上讲述ZK Client的工作原理及内部工作机制。 在看完ZK Client的大致架构以后我希望能有一种简单的方式描述ZK Client的基本结构,想来想去我觉得还是图片比较能反映情况,于是我画了这张大致的结构图: 我想既然我画了这张图,就让我们从这张图开始讲起吧。 模块: 我们可以认为ZK的Client由三个主要模块组成:Zookeeper, WatcherManager, ClientCnxn Zookeeper是ZK Client端的真正接口,用户可以操作的最主要的类,当用户创建一个Zookeeper实例以后,几乎所有的操作都被这个实例包办了,用户不用关心怎么连接到Server,Watcher什么时候被触发等等令人伤神的问题。 WatcherManager,顾名思义,它是用来管理Watcher的,Watcher是ZK的一大特色功能,允许多个Client对一个或多个 ZNode进行监控,当ZNode有变化时能够通知到监控这个ZNode的各个Client。我们把一个ZK Client简单看成一个Zookeeper实例,那么这个实例内部的WatcherManager就管理了ZK Client绑定的所有Watcher。 ClientCnxn是管理所有网络IO的模块,所有和ZK Server交互的信息和数据都经过这个模块,包括给ZK Server发送Request,从ZK Server接受Response,以及从ZK Server接受Watcher Event。ClientCnxn完全管理了网络,从外部看来网络操作是透明的。 线程: 每当我们创建一个Zookeeper实例的时候,会有两个线程被创建:SendThread和EventThread。所以当我们使用ZK Client端的时候应该尽量只创建一个Zookeeper实例并反复使用。大量的创建销毁Zookeeper实例不仅会反复的创建和销毁线程,而且会在 Server端创建大量的Session。 SendThread是真正处理网络IO的线程,所有通过网络发送和接受的数据包都在这个线程中处理。这个线程的主体是一个while循环: while (zooKeeper.state.isAlive()) { try { if (sockKey == null) { // don’t re-establish connection if we are closing if (closing) { break; } startConnect(); lastSend = now; lastHeard = now; } … …. selector.select(to); Set<SelectionKey> selected; synchronized (this) { selected = selector.selectedKeys(); } // Everything below and until we get back to the select is // non blocking, so time is effectively a constant. That is // Why we just have to do this once, here now = System.currentTimeMillis(); for (SelectionKey k : selected) { … … if (doIO()) { lastHeard = now; } … … } } catch() { … … } } 复制代码 这里用了java的nio功能,当selector侦测到事件发生的时候就会触发一次循环,主要的操作会在doIO()里面完成: boolean doIO() throws InterruptedException, IOException { boolean packetReceived = false; SocketChannel sock = (SocketChannel) sockKey.channel(); if (sock == null) { throw new IOException(“Socket is null!”); } if (sockKey.isReadable()) { … … } if (sockKey.isWritable()) { … … } if (outgoingQueue.isEmpty()) { disableWrite(); } else { enableWrite(); } return packetReceived; } 这个过程大概是这样的: 1. 如果有数据可读,则读取数据包,如果数据包是先前发出去的Request的Response,那么这个数据包一定在Pending Queue里面。将它从Pending Queue里面移走,并将此信息添加到Waiting Event Queue 里面,如果数据包是一个Watcher Event,将此信息添加到Waiting Event Queue里面。 2. 如果OutgoingQueue里面有数据需要发送,则发送数据包并把数据包从Outgoing Queue移至Pending Queue,意思是数据我已经发出去了,但还要等待Server端的回复,所以这个请求现在是Pending 的状态。 另外一个线程EventThread是用来处理Event的。前面提到SendThread从Server收到数据的时候会把一些信息添加到 Event Thread里面,比如Finish Event和Watcher Event。EventThread就是专门用来处理这些Event的,收到Finish Event的时候会把相对应的Package置成Finish状态,这样等待结果的Client函数就能得以返回。收到Watcher Event的时候会联系WatcherManager找到相对应的Watcher,从WatcherManager里面移除这个Watcher(因为每个 Watcher只会被通知一次) 并回调Watcher的process函数。所以所有Watcher的process函数是运行在EventThread里面的。 保持连接: 到目前为止应该已经大概介绍了ZK Client端的大致结构和处理流程。还剩下一个问题就是当网络出问题时ZK Client是如何处理的。其实这个过程并不复杂,大概是执行以下步骤: 1. 网络发生故障,网络操作抛出的异常被捕获。 2. 确认网络操作失败,清除当前与Server相关的网络资源,包括Socket等等。 3. 在Server列表中逐个尝试链接Server。 这个过程从外界看来是透明的,外界并不会觉察到ZK Client已经悄悄地更换了一个连接的Server。 好了,对于ZK Client的介绍大概就这么多了,希望这样的介绍对于大家学习和使用Zookeeper有一些帮助。对于文章中没有介绍或者没有说清楚的地方需要进一步查看源码来解决。

优秀的个人博客,低调大师

[Hive]Hive使用指南四 客户端导入数据

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/52935649 根据导入的地方不一样,主要介绍下面几种方式: 从本地文件系统中导入数据到Hive表 从HDFS上导入数据到Hive表 从别的表中查询出相应的数据并导入到Hive表中 1. 本地文件系统导入Hive表中 1.1 导入普通Hive表 1.1.1 创建Hive普通表 CREATE TABLE IF NOT EXISTS order_uid_total( uid string, bucket_type string, file_name string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE; 1.1.2 导入数据 load data local inpath '/home/xiaosi/adv/order_uid_total.txt' into table order_uid_total; 1.1.3 查看数据 hive (test)> select * from order_uid_total where bucket_type = 'put' limit 10; OK 868 put uids.3_1 865 put uids.3_1 DC8 put uids.3_1 861 put uids.3_1 867 put uids.3_1 861 put uids.3_1 868 put uids.3_1 867 put uids.3_1 867 put uids.3_1 A00 put uids.3_1 1.2 导入Hive分区表 1.2.1 创建分区表 CREATE TABLE IF NOT EXISTS order_uid_total_partition( uid string ) PARTITIONED BY(bucket_type string, file_name string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE; 1.2.2 静态导入数据 load data local inpath '/home/xiaosi/adv/order_uid_total_partition.txt' into table order_uid_total_partition partition(bucket_type='put',file_name='uids_3_1'); 1.2.3 动态导入数据 如果表中有多个分区,按上面插入语句会要写很多的SQL,而且查询语句要对应上不同的分区,这样就插入语句用起来就会很繁琐。为了解决这个问题,Hive中提供了动态分区插入的功能,它能跟分区字段的内容自动创建分区,并在每个分区插入相应的内容: insert overwrite table order_uid_total_partition partition (bucket_type, file_name) select uid, bucket_type, file_name from order_uid_total; 如果直接运行上面代码,会报如下错误: FAILED: SemanticException [Error 10096]: Dynamic partition strict mode requires at least one static partition column. To turn this off set hive.exec.dynamic.partition.mode=nonstrict 从上面错误提示中,我们知道我们需要设置分区动态导入模式: set hive.exec.dynamic.partition.mode=nonstrict; 默认值为strict,设置完毕之后,再次导入数据即可。 备注 SELECT语句中要包含分区字段 2. HDFS上导入数据到Hive表 从本地文件系统中将数据导入到Hive表的过程中,其实是先将数据临时复制到HDFS的一个目录下,然后再将数据从那个临时目录下移动到对应的Hive表的数据目录里面。因此,我们可以直接从HDFS上的一个目录移动到相应Hive表的数据目录下,假设HDFS上有下面这个文件data/order_uid_total.txt,具体的操作如下: load data inpath 'data/order_uid_total.txt' overwrite into table order_uid_total; 相对比于从本地文件导入Hive表中,唯一的区别就是少了一个local关键词。local表示文件位于本地文件系统上,如果没有local关键词,表示文件位于HDFS上。 3. 从别的表中查询出相应的数据导入到Hive表中 3.1 普通Hive表 创建普通Hive表 CREATE TABLE IF NOT EXISTS order_uid_total( uid string, bucket_type string, file_name string ) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE; 查询数据导入Hive表中 insert overwrite table order_uid_total select uid, bucket_type, file_name from order_uid_total_partition; 3.2 分区Hive表 创建分区Hive表 CREATE TABLE IF NOT EXISTS order_uid_total_partition( uid string ) PARTITIONED BY(bucket_type string, file_name string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE; 查询数据导入Hive表中 insert overwrite table order_uid_total_partition partition (bucket_type, file_name) select uid, bucket_type, file_name from order_uid_total;

优秀的个人博客,低调大师

[Hive]Hive使用指南五 客户端导出数据

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/52924452 根据导出的地方不一样,将这些方式分为三种: 导出到本地文件系统中 导出到HDFS中 导出到Hive的另一个表中 1. 导出到本地文件系统中 INSERT OVERWRITE LOCAL DIRECTORY '/home/q/jifeng.si/data/client_behavior' SELECT * FROM client_behavior WHERE dt = '2017-08-16' LIMIT 2000; 这条HQL的执行需要启用Mapreduce作业,运行完这条语句之后,将会在本地文件系统/home/q/jifeng.si/data/client_behavior目录下生成文件名称为000000_2的文件,这是由Reduce产生的结果,我们可以看看这个文件的内容: ll /home/q/jifeng.si/data/client_behavior total 536 -rw-r--r-- 1 wirelessdev wirelessdev 546233 Aug 17 19:46 000000_2 在Hive0.11.0版本之前,当用户将Hive查询结果输出到文件中时,用户不能指定列的分割符,默认为\x01: cat /home/q/jifeng.si/data/client_behavior/000000_2 |awk -F"\x01" '{print $1}' | less 2017-08-16 2017-08-16 2017-08-16 2017-08-16 2017-08-16 2017-08-16 2017-08-16 ... 在Hive0.11.0版本之后,引入了新特性,用户可以指定列和行的分隔符: INSERT OVERWRITE LOCAL DIRECTORY '/home/q/jifeng.si/data/client_behavior' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' SELECT * FROM client_behavior WHERE dt = '2017-08-16' LIMIT 2000; 查看数据: cat /home/q/jifeng.si/data/client_behavior/000000_2 | awk -F"\t" '{print $1}' | less 2017-08-16 2017-08-16 2017-08-16 2017-08-16 2017-08-16 ... 2. 导出到HDFS中 导出到HDFS中,与导出到本地文件系统中思路一致,只是少了一个LOCAL关键字: INSERT OVERWRITE DIRECTORY 'tmp/data_group/test/client_behavior' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' SELECT * FROM client_behavior WHERE dt = '2017-08-16' LIMIT 2000; 上面代码将会导出查询数据到HDFS的tmp/data_group/test/client_behavior目录下。 3. 导出到Hive的另一个表中 导出到Hive中的另一个表中,也是Hive的数据导入方式: INSERT INTO client_behavior_copy SELECT * FROM client_behavior WHERE dt = '2017-08-16' LIMIT 2000; 备注 如果想要导入数据到另一个表中,则这个表必须已经创建成功

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

用户登录
用户注册