设计一套实时分布式日志流收集平台(tail Logs --->HDFS)

本文介绍了一种自研的日志收集平台,该平台能够实时收集应用客户端产生的大量日志并发送至HDFS,用于后续的数据挖掘和分析。平台通过日志扫描线程和tail线程确保数据的完整性和准确性,同时具备故障恢复能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目前业界大概这么几个开源的分布式日志系统,notify+rsync,Facebook 的Scribe,apache的chukwa,linkin的kafa和cloudera的flume。
之所以自己设计一台这么一个平台,而没有采用开源,主要是基于这么考虑
   1、以上这几种开源日志系统,虽然提供了日志tail实时输出的功能,但是在tail进程宕掉后,无法从收集的点开始收集,只能重新开始,这样有很多重复的日志
   2、这几种开源的日志系统功能比较全面,但是对我们平台来说,只用部分的功能,设计一个简单可用可控的平台是我们的一个目标
这篇文章讲述了笔者以前自己设计的一个日志收集平台的技术细节,在电商开放平台中有应用到。
应用场景是这样的,
平台中各个应用客户端会实时产生大量的日志,需要实时把各个应用客户端的日志收集起来,发送到分布式文件系统中,供后续的数据挖掘和分析。
数据会收集到HDFS中,每天定时生成一个文件(文件前缀为日期,后缀为序列号从0开始),并且当文件的大小超多一定大小时,自动生成一个新的文件,文件前缀为当前日期,后缀为当前序列号递增。
系统的运行架构图,以及相关说明

 

说明如下:
1、首先启动一个日志扫描线程(扫描日志目录),当有本地日志文件生成的时,会生成一个日志tail任务,放到日志tail队列中等待调度。
2、对任务队列中的tail任务从线程池获取一个tail线程,该线程的职责是tail日志文件,输出到MQ中。在输出到MQ的同时,把当前的行号LSN记录到LSN Store中, 这里有一个考虑是如果日志tail线程宕掉,可以从宕掉时的日志行开始tail(seek操作)。
3、Collector节点启动多个线程从MQ中获取日志数据,并梳理日志的类别(操作日志,访问日志,业务日志等),根据不同的类型写到HDFS中不同的文件。如果在写入过程中,出现错误(比如HDFS暂时不可访问,这里有告警机制),那么就暂存在本地,等待恢复正常后,批量导入到HDFS中。
4、Lsn记录器,记录日志当前tail到哪一行了,在tail时,先写入Lsn Buffer中,是append方式,当超过一定的100M大小或者一定时间间隔时,就写到LSN File,只写最后的行号,并清除buffer。
     这样做的好处是,append数据到buffer(而不是update操作)的内存操作非常快。宕机恢复,在查询时,先从buffer查找,如果buffer中不存在,再从File中查找。
5、对于HDFS文件名称的切换按照以下策略进行
   每天定时生成一个文件(文件前缀为日期,后缀为序列号从0开始),并且当文件的大小超多一定大小时,自动生成一个新的文件,文     件前缀为当前日期,后缀为当前序列号递增。
    实现了两个Trigger,分别为SizeTriger(在调用HDFS输出流写的同时,count该流已经写入的大小总和,若超过一定大小,则创建新的文件和输出流,写入操作指向新的输出流,同时close以前的输出流)和TimeTriger(开启定时器,当到达该点时,自动创建新的文件和输出流,新的写入重定向到该流中,同时close以前的输出流)。
 
附带HDFS flush写数据说明:
HDFS操作过程中,只有在流flush(当数据包满的时,会自动flush;或者手动flush)和关闭的时候,才真正的写数据到datenode的硬盘上,那么对于HDFS来讲,默认的packet是64K,当超过数据超过64K时,会自动进行输出到dataNode的输出流中。
调用close时候,会自动把未构成一个packet的数据,也输出到dataNode输出流中写到datanode硬盘,完成后汇报给NameNode(当然datanode中的数据大小超过一个块如64M的时候,也会向NameNode汇报)
<configuration> <!-- 把多个NameNode的地址组装成一个集群mycluster --> <property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property> <!-- 指定hadoop运行时产生文件的存储目录 --> <property> <name>hadoop.tmp.dir</name> <value>/usr/ha/hadoop-3.1.3/data</value> </property> </configuration> <configuration> <!-- NameNode数据存储目录 --> <property> <name>dfs.namenode.name.dir</name> <value>file://${hadoop.tmp.dir}/name</value> </property> <!-- DataNode数据存储目录 --> <property> <name>dfs.datanode.data.dir</name> <value>file://${hadoop.tmp.dir}/data</value> </property> <!-- JournalNode数据存储目录 --> <property> <name>dfs.journalnode.edits.dir</name> <value>${hadoop.tmp.dir}/jn</value> </property> <!-- 完全分布式集群名称 --> <property> <name>dfs.nameservices</name> <value>mycluster</value> </property> <!-- 集群中NameNode节点都有哪些 --> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2,nn3</value> </property> <!-- NameNode的RPC通信地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>hadoop101:8020</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>hadoop102:8020</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn3</name> <value>hadoop103:8020</value> </property> <!-- NameNode的http通信地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>hadoop101:9870</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>hadoop102:9870</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn3</name> <value>hadoop103:9870</value> </property> <!-- 指定NameNode元数据在JournalNode上的存放位置 --> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://hadoop101:8485;hadoop102:8485;hadoop103:8485/myclus ter</value> </property> <!-- 访问代理类:client用于确定哪个NameNode为Active --> <property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyP rovider</value> </property> <!-- 配置隔离机制,即同一时刻只能有一台服务器对外响应 --> <value>shell(true)</value> <property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> <value>shell(true)</value> </property> <!-- 使用隔离机制时需要ssh秘钥登录--> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/root/.ssh/id_rsa</value> </property> </configuration> 这是我的两个配置文件的内容,有没有问题
最新发布
06-18
<think>我们正在检查Hadoop高可用集群的配置文件是否正确,特别是关于NameNode、DataNode、JournalNode以及fencing方法的设置。以下将分步骤进行验证。###1.验证NameNode配置在Hadoop高可用集群中,NameNode的配置主要集中在`hdfs-site.xml`文件中。需要检查以下关键参数:-**`dfs.nameservices`**:定义命名服务的名称,例如`mycluster`。-**`dfs.ha.namenodes.[nameservice]`**:指定该命名服务下的NameNode逻辑ID,例如`nn1,nn2`。-**`dfs.namenode.rpc-address.[nameservice].[namenode_id]`**:指定每个NameNode的RPC地址和端口。-**`dfs.namenode.http-address.[nameservice].[namenode_id]`**:指定每个NameNode的HTTP地址和端口。-**`dfs.namenode.shared.edits.dir`**:指定JournalNode集群的地址,用于共享编辑日志。格式如:`qjournal://node1:8485;node2:8485;node3:8485/mycluster`。**示例配置片段**:```xml<property><name>dfs.nameservices</name><value>mycluster</value></property><property><name>dfs.ha.namenodes.mycluster</name><value>nn1,nn2</value></property><property><name>dfs.namenode.rpc-address.mycluster.nn1</name><value>hadoop1:8020</value></property><property><name>dfs.namenode.rpc-address.mycluster.nn2</name><value>hadoop2:8020</value></property><property><name>dfs.namenode.http-address.mycluster.nn1</name><value>hadoop1:9870</value></property><property><name>dfs.namenode.http-address.mycluster.nn2</name><value>hadoop2:9870</value></property><property><name>dfs.namenode.shared.edits.dir</name><value>qjournal://hadoop1:8485;hadoop2:8485;hadoop3:8485/mycluster</value></property>```###2.验证DataNode配置DataNode的配置相对简单,主要确保它们能够连接到正确的NameNode服务。在`hdfs-site.xml`中,需要设置:-**`dfs.datanode.address`**:DataNode的数据传输地址(可选,通常默认即可)。-**`dfs.datanode.http.address`**:DataNode的HTTP地址(可选)。但最重要的是,DataNode会自动向所有活跃的NameNode和备用NameNode发送块报告和心跳。因此,只要NameNode的配置正确,DataNode通常不需要额外配置。###3.验证JournalNode配置JournalNode用于共享NameNode的编辑日志。在`hdfs-site.xml`中,需要设置:-**`dfs.journalnode.edits.dir`**:指定JournalNode存储编辑日志的本地目录。**示例配置**:```xml<property><name>dfs.journalnode.edits.dir</name><value>/path/to/journal/node/edits</value></property>```此外,确保在`core-site.xml`中配置了ZooKeeper地址(如果使用基于ZKFC的自动故障转移):```xml<property><name>ha.zookeeper.quorum</name><value>zk1:2181,zk2:2181,zk3:2181</value></property>```###4.验证Fencing方法在HadoopHA中,fencing(隔离)机制用于防止脑裂问题。常见的fencing方法包括SSH和Shell脚本。在`hdfs-site.xml`中,需要配置:-**`dfs.ha.fencing.methods`**:定义隔离方法,例如`sshfence`或`shell(/path/to/script)`。-**`dfs.ha.fencing.ssh.private-key-files`**:如果使用SSH隔离,指定私钥文件路径。-**`dfs.ha.fencing.ssh.connect-timeout`**:SSH连接超时时间(毫秒)。**示例配置**:```xml<property><name>dfs.ha.fencing.methods</name><value>sshfence</value></property><property><name>dfs.ha.fencing.ssh.private-key-files</name><value>/home/hadoop/.ssh/id_rsa</value></property><property><name>dfs.ha.fencing.ssh.connect-timeout</name><value>30000</value></property>```###5.验证ZKFC配置ZooKeeperFailoverController(ZKFC)负责监控NameNode状态并执行故障转移。在`hdfs-site.xml`中,需要配置:-**`dfs.ha.automatic-failover.enabled`**:设置为`true`以启用自动故障转移。###验证配置的方法1.**使用`hdfsgetconf`命令**:```bashhdfsgetconf-confKeydfs.nameserviceshdfsgetconf-confKeydfs.ha.namenodes.myclusterhdfsgetconf-confKeydfs.namenode.rpc-address.mycluster.nn1```这些命令可以输出配置的值,用于验证配置是否正确加载。2.**启动服务并检查日志**:-启动JournalNode:`hdfs--daemonstartjournalnode`-格式化JournalNode(仅在首次设置时):`hdfsnamenode-initializeSharedEdits`-启动NameNode:`hdfs--daemonstartnamenode`-启动ZKFC:`hdfs--daemonstartzkfc`检查各节点的日志文件(位于`$HADOOP_HOME/logs/`)是否有错误。3.**检查进程状态**:-使用`jps`命令查看Java进程,确保有`NameNode`、`JournalNode`、`DFSZKFailoverController`等进程运行。###常见问题-**版本不一致**:如引用[1]所述,如果NameNode被重新格式化,会导致DataNode的`VERSION`文件与NameNode不一致,从而DataNode无法启动。解决方法是删除DataNode的数据目录(`dfs.datanode.data.dir`)并重新同步,或者确保在重新格式化NameNode后,所有DataNode的数据目录都被清除[^1]。-**配置文件未同步**:如引用[4]所述,必须确保所有节点上的配置文件一致。使用`scp`命令将配置文件分发到所有节点[^4]。###总结通过以上步骤,可以系统地验证Hadoop高可用集群的配置文件。特别注意NameNode、JournalNode和fencing方法的配置,以及配置文件的同步问题。如果遇到启动失败,务必检查日志文件以获取具体错误信息。---###§§相关问题§§1.Hadoop高可用集群中,如何解决DataNode无法启动的问题?2.如何配置Hadoop高可用集群的自动故障转移?3.在Hadoop高可用集群中,JournalNode的作用是什么?4.如何手动切换Hadoop高可用集群中的NameNode角色?</think>### 验证Hadoop高可用集群配置文件的正确性指南 以下是验证Hadoop HA配置文件中关键组件设置是否正确的步骤和方法: #### 1. **NameNode配置验证** 在`hdfs-site.xml`中检查: ```xml <!-- 命名服务标识 --> <property> <name>dfs.nameservices</name> <value>mycluster</value> <!-- 集群唯一标识符 --> </property> <!-- NameNode逻辑ID --> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> <!-- 至少两个NN标识 --> </property> <!-- RPC地址配置 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>node1:8020</value> <!-- 主NN地址 --> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>node2:8020</value> <!-- 备NN地址 --> </property> <!-- HTTP地址配置 --> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>node1:9870</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>node2:9870</value> </property> ``` **验证方法**: ```bash hdfs getconf -confKey dfs.nameservices hdfs getconf -confKey dfs.ha.namenodes.mycluster ``` #### 2. **JournalNode配置验证** 在`hdfs-site.xml`中检查: ```xml <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://node1:8485;node2:8485;node3:8485/mycluster</value> </property> <property> <name>dfs.journalnode.edits.dir</name> <value>/path/to/journal/data</value> <!-- JN数据目录 --> </property> ``` **验证方法**: 1. 检查JournalNode进程状态: ```bash jps | grep JournalNode ``` 2. 测试端口连通性: ```bash telnet node1 8485 ``` #### 3. **DataNode配置验证** 在`hdfs-site.xml`中检查: ```xml <property> <name>dfs.datanode.address</name> <value>0.0.0.0:1004</value> <!-- 数据传输端口 --> </property> <property> <name>dfs.datanode.http.address</name> <value>0.0.0.0:1006</value> <!-- HTTP端口 --> </property> ``` **验证方法**: 1. 检查块报告是否正常: ```bash hdfs dfsadmin -report ``` 2. 查看DataNode日志: ```bash tail -f $HADOOP_HOME/logs/hadoop-*-datanode-*.log ``` #### 4. **Fencing方法验证** 在`hdfs-site.xml`中检查隔离机制: ```xml <!-- SSH隔离 --> <property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/hadoop/.ssh/id_rsa</value> </property> <!-- Shell脚本隔离(备选) --> <property> <name>dfs.ha.fencing.methods</name> <value>shell(/path/to/fence_script.sh)</value> </property> ``` **验证方法**: 1. 测试SSH无密码登录: ```bash ssh node2 "hostname" # 应无需密码返回主机名 ``` 2. 手动触发隔离测试: ```bash hdfs haadmin -ns mycluster -failover nn1 nn2 --forcefence ``` #### 5. **ZKFC配置验证** 在`hdfs-site.xml`中检查: ```xml <property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property> <property> <name>dfs.ha.zookeeper.quorum</name> <value>zk1:2181,zk2:2181,zk3:2181</value> </property> ``` **验证方法**: ```bash # 检查ZKFC进程 jps | grep DFSZKFailoverController # 检查ZooKeeper状态 echo stat | nc zk1 2181 ``` ### 配置文件一致性检查 使用以下命令验证所有节点配置一致性: ```bash # 主节点生成配置摘要 md5sum $HADOOP_HOME/etc/hadoop/*.xml > /tmp/hadoop-md5 # 其他节点验证 scp user@master:/tmp/hadoop-md5 . md5sum -c hadoop-md5 ``` ### 关键注意事项 1. **版本一致性**:如引用[1]所述,确保所有节点的`VERSION`文件中`clusterID`一致(位于`dfs.namenode.name.dir/current`和`dfs.datanode.data.dir/current`)[^1] 2. **端口冲突**:使用`netstat -tuln | grep <端口号>`检查端口占用 3. **日志分析**:所有组件的日志路径: - NameNode: `$HADOOP_HOME/logs/hadoop-*-namenode-*.log` - DataNode: `$HADOOP_HOME/logs/hadoop-*-datanode-*.log` - JournalNode: `$HADOOP_HOME/logs/hadoop-*-journalnode-*.log` > 通过以上系统检查,可确保HA配置正确性。若仍有问题,建议检查防火墙设置和SELinux状态。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值