Apache Flume - File通道

原文链接:https://blogs.apache.org/flume/entry/apache_flume_filechannel

说明:翻译在尽量符合原文表达的基础上,尽量保证行文流畅。水平有限,请多指正!

这篇文章是关于Flume FileChannel的。Flume是为高效收集聚合大量日志数据设计的可靠的、可用的分布式系统。它有一个基于流式数据流的简单灵活的体系。它提供了可控的可靠机制和许多故障转移与恢复机制。它使用了一个用于在线分析应用的简单可扩展的数据模型。

FileChannel是一个持久化的Flume channel,支持并行的写到多个磁盘并且支持加密。

概念
        当使用Flume时,每个流程都有一个Source、Channel、Sink。一个典型的例子是一个webserver通过RPC(比如:AvroSource)将events写到一个Source、然后Source将events写到MemoryChannel,最后HDFSSink消费event,将它写到HDFS。
                    
       MemoryChannel能提供很高的吞吐量,但是当系统断电或程序崩溃时会丢失数据。因此人们急需一个能持久化的Channel。FileChannel在FLUME-1085被实现。它的目标是提供一个可靠的高吞吐量的Channel。FileChannel保证当断电或崩溃发生时,事务被提交,没有数据丢失。
       重要的一点是FileChannel不做任何数据的复制,仅依赖于底层磁盘的可靠性,因此,由于持久性需要使用FileChannel的用户在购买和配置硬件时注意这一点。底层的磁盘将要做RAID、SAN或类似的东西。
       许多系统为了高的吞吐率需要拿允许小量数据丢失做交换。Flume组决定FileChannel采用不同的方式。Flume是一个支持事务的系统,多个event可以在单个事务中被put或take。batch size用来控制吞吐率。使用大的batch size,flume可以以高吞吐率移动数据,并且不丢失数据。batch size完全可以通过client控制。这个方法与DBMS
相似。
       一个flume事务包含put或take,一个事务中不能同时有put和take操作。每个事务都要实现put和take方法。source通过put将event放入channel,sink通过take将event从channel拿走。

设计
       FileChannel是基于内存队列和WAL设计的。每次事务都是根据事物类型(Take和Put)写到WAL,队列也做相应的修改。每次事务被commited,都会调用fsync确保events被存储在磁盘文件,同时指向该event的指针被放到队列中。这里的队列服务就像其他队列一样:它管理着什么被sink消费。在Take期间,该event的指针从队列被删除。直接从WAL读这个event。由于今天我们有大量可用的RAM,从操作系统的文件缓存中读取也是经常发生的。
       崩溃后,通过重放WALs,队列位置能恢复到崩溃前同样的状态,而那些没有commited的事务被丢弃。重放WALs相当耗时,因此队列本身会周期性的写到磁盘。将队列写到磁盘称为checkpoint。这样,崩溃后,队列首先从磁盘checkpoint文件加载,然后仅仅重放那些队列被最后一次checkpoint到磁盘后commited的事务,这样明显的减少了读取WAL的数量。
       例如,一个channel有2个event,如下所示:
      
       
       WALs包含3个重要的属性:事务ID、序列号、event数据。每个事务都有唯一的事务Id,并且每个event都有唯一的序列号。事务Id被用来简单的将event分组到同一事务,而序列号在重放log时使用。上图中,事务ID为1,序列号为1,2,3.
       当队列被checkpoint到磁盘,增加序列号,同时序列号也被保存到磁盘。重启时,队列首先从磁盘加载,然后比队列序列号大的任何WAL实体被重放。checkpoin操作期间,队列是locked,以至于没有Put或Take操作可以更改它的状态。如果checkpoint期间允许队列的修改,将导致磁盘存储的队列快照与实际队列不一致。
       在上面例子中,事务1commited后,checkpoint发生,在队列中的结果带着events被保存到磁盘还有序列号4也被保存。
       之后,在事务2中,从队列take一个event:
        
        
        如果这个时候崩溃了,重启时队列从checkpoint加载,注意,checkpoint发生在事务2前,2个event“a”和“b”都会被加载到队列,之后任何比4大的已经确认的事务被重放,重放后,“a”event从队列被删除。
       上面的设计2点没有考虑到,Take或Put进行中,同时发生checkpoint,会导致数据丢失。假定checkpoint发生在take“a”之后:
        
        如果此时崩溃,在以上描述的设计下,event“b”被加载进入队列,之后重放比5大的任何WAL实体,事务2被rollback,但是这里的take “a”不会被重放。event “a”被丢失,Put也存在相似的情况。由于这个原因,当队列的checkpoint发生时,仍然在处理中的事务也被写出,以至于可以适当的处理这个问题。
       

实现
       FileChannel在Flume项目的flume-file-channel模块,对应包名为org.apache.flume.channel.file。上面描述的队列对应 FlumeEventQueue类,WAL对应 Log类。队列本身是一个环形数组,通过内存映射文件支撑;而WAL对应一组文件,可以使用 LogFile类和它的子类读写这些文件。
结论
       FileChannel在遇到硬件、软件、环境失败时,给Flume用户提供了持久化的保证,而且具有高的吞吐量。这两个方面对于大多数情况都是比较重要的,因此FileChannel是推荐使用的Channel。
<think>我们正在解决的是:运行`flume-ngversion`时出现`CommandNotFoundException`错误,原因是未找到`flume-env.ps1`。根据引用[1]和引用[3]中的错误信息,以及用户之前的问题,我们可以推断:1.用户可能在Windows环境下运行Flume。2.错误信息中提到了`flume-ng.ps1`脚本,这是Flume在Windows上的启动脚本。3.错误可能是由于`flume-env.ps1`配置文件未正确设置或未被找到。回顾之前的解决方案,我们配置了`flume-env.ps1`并设置了`JAVA_HOME`等环境变量。但是,当运行`version`命令时,脚本可能因为某些原因(比如配置文件路径问题)而无法正确加载。在`flume-ng.ps1`脚本中,有一段代码用于加载`flume-env.ps1`:```powershellif("$conf"-ne""){Write-Host"Sourcingenvironmentconfigurationscript$conf\flume-env.ps1"if(Test-path"$conf\flume-env.ps1"){."$conf\flume-env.ps1"}else{Write-Host"WARN:Didnotfind$conf\flume-env.ps1"}}else{Write-Host"WARN:Noconfigurationdirectoryfound!Use--conf<dir>toset."}```注意:在运行`version`命令时,用户可能没有指定`-conf`参数,因此`$conf`变量为空,导致没有加载任何`flume-env.ps1`文件。而脚本中设置`$conf`默认值为`$FLUME_HOME\conf`是在用户没有指定且环境变量`FLUME_HOME`存在的情况下。但是,如果用户没有设置`FLUME_HOME`环境变量,那么`$conf`就会为空。因此,我们需要确保:1.用户运行命令时指定了`-conf`参数,指向`conf`目录(该目录下应有`flume-env.ps1`文件)。2.或者,设置`FLUME_HOME`环境变量,这样脚本会自动将`$conf`设置为`$env:FLUME_HOME\conf`。然而,在运行`version`命令时,用户可能不会指定`-conf`。因此,我们可以修改脚本,使其在没有指定`-conf`且`$env:FLUME_HOME`存在时,自动使用`$env:FLUME_HOME\conf`作为配置目录。但是,用户报告的错误是`CommandNotFoundException`,这通常表示PowerShell无法识别某个命令(可能是由于Java路径问题)。因此,即使没有加载`flume-env.ps1`,只要Java在系统PATH中,`version`命令应该也能运行。所以,更可能的原因是:-在没有`flume-env.ps1`的情况下,脚本依赖的Java环境变量(如`JAVA_HOME`)没有设置,而系统PATH中也没有Java。因此,解决方案有两个方向:方向一:确保`flume-env.ps1`被加载-在运行命令时指定`-conf`参数,例如:```powershell.\flume-ng.ps1version-conf../conf```-或者,设置`FLUME_HOME`环境变量,指向Flume的安装目录。方向二:确保系统环境变量中已经正确设置了Java的路径(即无需依赖`flume-env.ps1`)-将Java的`bin`目录添加到系统PATH中。但是,根据用户之前的问题,我们已经在`flume-env.ps1`中设置了`JAVA_HOME`和`PATH`。所以,如果这个配置文件没有被加载,那么Java环境可能就不存在。因此,我们重点确保`flume-env.ps1`被加载。修改脚本逻辑:即使没有指定`-conf`,我们也尝试使用默认位置(即`$PSScriptRoot\..\conf`)来加载`flume-env.ps1`。然而,我们注意到在脚本中已经有这样的逻辑:```powershell$FlumeHome=$nullif($env:FLUME_HOME){$FlumeHome=$env:FLUME_HOME}else{$ScriptPath=Split-Path-Parent$MyInvocation.MyCommand.Path$FlumeHome=Split-Path-Parent$ScriptPath}if("$conf"-eq""){if(Test-path("$FlumeHome\conf")){$conf="$FlumeHome\conf"Write-Host"WARN:Configdirectorynotset.Defaultingto$conf"}}```所以,如果用户没有设置`FLUME_HOME`,脚本会通过当前脚本路径计算出`FlumeHome`(即`bin`目录的父目录),然后设置`$conf`为`$FlumeHome\conf`。那么,为什么还会出现找不到`flume-env.ps1`的警告呢?可能的原因:1.`$FlumeHome\conf`目录不存在。2.虽然存在,但里面没有`flume-env.ps1`文件。因此,我们需要检查:-Flume安装目录下是否有`conf`目录?-`conf`目录中是否有`flume-env.ps1`文件?如果没有,我们可以从模板创建一个:-复制`flume-env.ps1.template`为`flume-env.ps1`。所以,具体步骤:步骤1:检查Flume安装目录下的`conf`子目录是否存在,并确保其中有`flume-env.ps1`文件。步骤2:如果没有,则创建该文件(从模板复制并修改)。步骤3:在`flume-env.ps1`中设置`JAVA_HOME`和`PATH`(如之前所述)。步骤4:确保脚本能正确找到这个配置文件。另外,`CommandNotFoundException`错误也可能是由于`java`命令不在PATH中,且`flume-env.ps1`中设置的`PATH`没有被正确加载。因此,我们可以在`flume-ng.ps1`脚本中显式地添加`JAVA_HOME/bin`到PATH,即使`flume-env.ps1`没有被加载,我们也可以尝试使用默认的Java。但是,修改脚本可能不是用户想要的,因为用户可能没有权限或者不想修改分发版本的脚本。因此,我们给用户提供以下解决方案:解决方案:1.确保Flume的`conf`目录下有`flume-env.ps1`文件。-进入Flume安装目录下的`conf`目录(例如:`E:\apache-flume-1.11.0-bin\conf`)。-检查是否存在`flume-env.ps1`文件。如果不存在,复制`flume-env.ps1.template`并重命名为`flume-env.ps1`。2.编辑`flume-env.ps1`文件,设置Java环境:```powershell$env:JAVA_HOME="C:\ProgramFiles\Java\jdk1.8.0_451"#替换为你的实际路径$env:JAVA_OPTS="-Xmx512m"#将Java的bin目录添加到PATH$env:Path="$env:JAVA_HOME\bin;"+$env:Path```3.如果上述步骤完成后,运行`version`命令仍然出现错误,尝试在运行命令时显式指定`-conf`参数:```powershell.\flume-ng.ps1version-conf../conf```4.如果还是不行,可以尝试在运行脚本之前设置`FLUME_HOME`环境变量(指向Flume的安装目录):```powershell$env:FLUME_HOME="E:\apache-flume-1.11.0-bin".\flume-ng.ps1version```5.作为备用方案,确保系统环境变量中已经设置了`JAVA_HOME`和`PATH`(包含Java的bin目录),这样即使不加载`flume-env.ps1`,Java也是可用的。6.如果问题仍然存在,可能是脚本中的路径计算有误。我们可以临时修改脚本,在开头添加调试信息,打印`$FlumeHome`和`$conf`的值,以便确认路径是否正确。修改`flume-ng.ps1`脚本(在开头部分添加):```powershellWrite-Host"FlumeHome:$FlumeHome"Write-Host"conf:$conf"```然后再次运行,观察输出的路径是否指向正确的`conf`目录。通过以上步骤,应该可以解决`version`命令运行时报错的问题。注意:`CommandNotFoundException`错误通常是PowerShell无法找到某个命令(比如`java`命令),所以核心还是确保Java可执行文件在PATH中。</think>### 解决 Flume version 命令的 CommandNotFoundException 错误 #### 问题原因分析 该错误表明 Flume 无法找到 `flume-env.ps1` 配置文件,核心原因是: 1. **配置文件路径错误**:`flume-env.ps1` 未放在正确的 `conf` 目录中 2. **环境变量未生效**:`FLUME_HOME` 或 `JAVA_HOME` 配置不正确 3. **路径空格问题**:Flume 安装路径包含空格导致路径解析失败 4. **权限问题**:PowerShell 执行策略限制脚本运行 --- ### 解决方案步骤 #### 1. 验证配置文件位置 确保 `flume-env.ps1` 位于正确位置: ```powershell # 正确路径应为 Flume 安装目录下的 conf 文件夹 E:\apache-flume-1.11.0-bin\conf\flume-env.ps1 ``` #### 2. 修复 flume-env.ps1 配置 编辑 `conf/flume-env.ps1` 文件,添加以下内容: ```powershell # 必须设置 FLUME_HOME $env:FLUME_HOME = "E:\apache-flume-1.11.0-bin" # 设置 JAVA_HOME(替换为你的实际路径) $env:JAVA_HOME = "C:\Program Files\Java\jdk1.8.0_451" # 设置 Java 选项 $env:JAVA_OPTS = "-Xmx512m" # 确保 Java 在 PATH 中 $env:Path = "$env:JAVA_HOME\bin;" + $env:Path ``` #### 3. 处理路径空格问题(关键) 如果路径包含空格,使用双引号包裹: ```powershell # 正确写法 $env:FLUME_HOME = "`"E:\Program Files\apache-flume-1.11.0-bin`"" $env:JAVA_HOME = "`"C:\Program Files\Java\jdk1.8.0_451`"" ``` #### 4. 修改 PowerShell 执行策略 以管理员身份运行 PowerShell: ```powershell Set-ExecutionPolicy RemoteSigned -Force ``` #### 5. 验证修复效果 ```powershell cd E:\apache-flume-1.11.0-bin\bin .\flume-ng.ps1 version ``` ✅ 成功标志:显示 Flume 版本信息,无 CommandNotFoundException 错误 --- ### 错误排查技巧 1. **添加调试信息**:在 `flume-ng.ps1` 开头添加: ```powershell Write-Host "FLUME_HOME: $env:FLUME_HOME" Write-Host "JAVA_HOME: $env:JAVA_HOME" Write-Host "当前路径: $PWD" ``` 2. **手动验证路径**: ```powershell Test-Path "$env:FLUME_HOME\conf\flume-env.ps1" ``` > **关键提示**:Flume 在 Windows 下对路径敏感,确保所有路径都使用**英文双引号包裹**,特别是包含空格时[^1]。`FLUME_HOME` 必须指向 Flume 安装的根目录,而非 bin 目录[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值