Flume常用source、channel、sink
注:此处的flume版本为1.9
一、常用source
1.1 Avro Source
-
Avro Source监听Avro端口,接收从外部Avro客户端发送来的数据流。和netcat不同的是,avro-source接收到的是经过avro序列化后的数据,然后反序列化数据继续传输。所以,如果是avro-source的话,源数据必须是经过avro序列化后的数据。而netcat接收的是字符串格式。
-
利用Avro source可以实现多级流动、扇出流、扇入流等效果。
-
另外,也可以接收通过flume提供的avro客户端发送的日志信息。
-
必传参数:
- channels:与Source绑定的channel,多个用空格分开
- type:组件类型,这个是:avro
- bind:监听的服务器名或者ip
- port:监听的端口
- …可参考(下同):https://flume.liyifeng.org/#flume-sources
-
参考配置:
a1.sources = r1 a1.channels = c1 a1.sources.r1.type = avro a1.sources.r1.channels = c1 a1.sources.r1.bind = 0.0.0.0 a1.sources.r1.port = 4141
1.2 Exec Source
-
可以将命令产生的输出作为源,支持Linux命令,收集标准输出数据或者通过tail -f file的方式监听指定文件。如cat … 、tail -F …
-
ExecSource可以实现实时的消息传输,但是它不记录已经读取文件的位置,不支持断点续传,如果Exec Source重启或者挂掉都会造成后续增加的消息丢失,建议只是在测试环境使用。
-
为了获得更强的可靠性保证,考虑使用 Spooling Directory Source、Taildir Source或通过SDK直接与Flume集成。
-
必传参数:
- channels:与Source绑定的channel,多个用空格分开
- type:组件类型,这个是:exec
- command:所使用的系统命令,一般是cat 或者tail
-
参考配置:
a1.sources = r1 a1.channels = c1 a1.sources.r1.type = exec a1.sources.r1.command = tail -F /var/log/secure a1.sources.r1.channels = c1
1.3 Spooling Directory Source
-
这个Source允许你把要收集的文件放入磁盘上的某个指定目录。它会将监视这个目录中产生的新文件,并在新文件出现时从新文件中解析数据出来。数据解析逻辑是可配置的。 在新文件被完全读入Channel之后默认会重命名该文件以示完成(也可以配置成读完后立即删除、也可以配置trackerDir来跟踪已经收集过的文件)。
- 使用trackerDir跟踪收集的文件是通过1.9新增加了一个参数trackingPolicy,跟原有的参数组合后新增了一个使用的场景:标记已经被收集完成的文件,但是又不想对原文件做任何改动。
-
与 Exec Source 不同,Spooling Directory Source是可靠的,即使Flume重新启动或被kill,也不会丢失数据。同时作为这种可靠性的代价,指定目录中的被收集的文件必须是不可变的、唯一命名的。Flume会自动检测避免这种情况发生,如果发现问题,则会抛出异常:
- 如果文件在写入完成后又被再次写入新内容,Flume将向其日志文件(这是指Flume自己logs目录下的日志文件)打印错误并停止处理。
- 如果在以后重新使用以前的文件名(即产生重名文件),Flume将向其日志文件打印错误并停止处理。
- 解决方法:生成新文件的时候文件名加上时间戳
-
必传参数:
- channels:与Source绑定的channel,多个用空格分开
- type:组件类型,这个是:spooldir
- spoolDir:Flume Source监控的文件夹目录,该目录下的文件会被Flume收集
-
参考配置:
a1.channels = ch-1 a1.sources = src-1 a1.sources.src-1.type = spooldir a1.sources.src-1.channels = ch-1 a1.sources.src-1.spoolDir = /var/log/apache/flumeSpool # 是否添加文件的绝对路径名(绝对路径+文件名)到header中。 a1.sources.src-1.fileHeader = true
1.4 Taildir Source
-
Taildir Source监控指定的一些文件,并在检测到新的一行数据产生的时候几乎实时地读取它们,如果新的一行数据还没写完,Taildir Source会等到这行写完后再读取。
-
监听一个文件或文件夹,通过正则表达式匹配需要监听的数据源文件,支持文件夹嵌套递归监听(重要source), Taildir Source将通过监听的文件位置写入到文件中实现断点续传,并且能够保证没有重复数据的读取。
-
Taildir Source还可以从任意指定的位置开始读取文件。默认情况下,它将从每个文件的第一行开始读取。
-
文件按照修改时间的顺序来读取。修改时间最早的文件将最先被读取(简单记成:先来先走)。
-
Taildir Source不重命名、删除或修改它监控的文件。当前不支持读取二进制文件。只能逐行读取文本文件。
-
必传参数:
- channels:与Source绑定的channel,多个用空格分开
- type:组件类型,这个是:TAILDIR
- filegroups:被监控的文件夹目录集合,这些文件夹下的文件都会被监控,多个用空格分隔
- filegroups.:被监控文件夹的绝对路径。正则表达式(注意不会匹配文件系统的目录)只是用来匹配文件名
-
参考配置:
a1.sources = r1 a1.channels = c1 a1.sources.r1.type = TAILDIR a1.sources.r1.channels = c1 # 用来设定一个记录每个文件的绝对路径和最近一次读取位置inode的文件,这个文件是JSON格式。默认是~/.flume/taildir_position.json a1.sources.r1.positionFile = /var/log/flume/taildir_position.json # 被监控的文件夹f1 f2 a1.sources.r1.filegroups = f1 f2 # f1的绝对路径下的example.log a1.sources.r1.filegroups.f1 = /var/log/test1/example.log # 给某个文件组下的Event添加一个固定的键值对到header中,值就是value。一个文件组可以配置多个键值对。 a1.sources.r1.headers.f1.headerKey1 = value1 # f2的绝对路径下的所有.xxxlog.xxx文件 a1.sources.r1.filegroups.f2 = /var/log/test2/.*log.* a1.sources.r1.headers.f2.headerKey1 = value2 a1.sources.r1.headers.f2.headerKey2 = value2-2 # 是否在header里面存储文件的绝对路径 a1.sources.r1.fileHeader = true # 控制从同一文件连续读取的行数。 如果数据来源是通过tail多个文件的方式,并且其中一个文件的写入速度很快,则它可能会阻止其他文件被处理,因为这个繁忙文件将被无休止地读取。 在这种情况下,可以调低此参数来避免被一直读取一个文件。默认:Long.MAX_VALUE a1.sources.ri.maxBatchCount = 1000
1.5 Kafka Source
-
Kafka Source就是一个Apache Kafka消费者,它从Kafka的topic中读取消息。 如果运行了多个Kafka Source,则可以把它们配置到同一个消费者组,以便每个source都读取一组唯一的topic分区。
-
如果多个 Kafka Source 同时消费kafka中同一个主题(topic),则 Kafka Source 的kafka.consumer.group.id 应该设置成相同的组id,多个 Kafka Source 之间不会消费重复的数据,每一个Source 都会拉取 Topic 下的不同数据。
-
必传参数:
- channels:与Source绑定的channel,多个用空格分开
- type:组件类型,这个是:
org.apache.flume.source.kafka.KafkaSource
- kafka.bootstrap.servers: Source使用的Kafka集群实例列表
- kafka.topics:将要读取消息的目标 Kafka topic 列表,多个用逗号分隔
- kafka.topics.regex:会被Kafka Source订阅的 topic 集合的正则表达式。这个参数比 kafka.topics 拥有更高的优先级,如果这两个参数同时存在,则会覆盖kafka.topics的配置。
-
参考配置:
-
通过逗号分隔的 topic 列表进行 topic 订阅的示例:
tier1.sources.source1.type = org.apache.flume.source.kafka.KafkaSource tier1.sources.source1.channels = channel1 # 一批写入 channel 的最大消息数,默认1000 tier1.sources.source1.batchSize = 5000 # 一个批次写入 channel 之前的最大等待时间(毫秒)。达到等待时间或者数量达到 batchSize 都会触发写操作。默认1000 tier1.sources.source1.batchDurationMillis = 2000 tier1.sources.source1.kafka.bootstrap.servers = localhost:9092 tier1.sources.source1.kafka.topics = test1, test2 # 消费组的唯一标识符。如果有多个source或者Agent设定了相同的ID,表示它们是同一个消费者组,默认flume tier1.sources.source1.kafka.consumer.group.id = custom.g.id
-
正则表达式 topic 订阅的示例:
tier1.sources.source1.type = org.apache.flume.source.kafka.KafkaSource tier1.sources.source1.channels = channel1 tier1.sources.source1.kafka.bootstrap.servers = localhost:9092 tier1.sources.source1.kafka.topics.regex = ^topic[0-9]$ # the default kafka.consumer.group.id=flume is used
-
1.6 NetCat TCP Source
-
监听一个指定的端口,把从该端口收到的TCP协议的文本数据按行转换为Event,它能识别的是带换行符的文本数据。
-
必传参数:
- channels:与Source绑定的channel,多个用空格分开
- type:组件类型,这个是:netcat
- bind:要监听的 hostname 或者IP地址
- port:监听的端口
-
参考配置:
a1.sources = r1 a1.channels = c1 a1.sources.r1.type = netcat a1.sources.r1.bind = 0.0.0.0 a1.sources.r1.port = 6666 a1.sources.r1.channels = c1
二、常用channels
2.1 Memory Channel
-
内存 channel 是把 Event 队列存储到内存上,队列的最大数量就是 capacity 的设定值。它非常适合对吞吐量有较高要求的场景,但也是有代价的,当发生故障的时候会丢失当时内存中的所有 Event。
-
必传参数:
- type:组件类型,这个是:memory
-
参考配置:
a1.channels = c1 a1.channels.c1.type = memory # 内存中存储 Event 的最大数,默认100 a1.channels.c1.capacity = 10000 # source 或者 sink 每个事务中存取 Event 的操作数量(不能比 capacity 大),默认100 a1.channels.c1.transactionCapacity = 10000 # 指定 Event header 所占空间大小与 channel 中所有 Event 的总大小之间的百分比,默认20 a1.channels.c1.byteCapacityBufferPercentage = 20 # Channel 中最大允许存储所有 Event 的总字节数(bytes)。 # 默认情况下会使用JVM可用内存的80%作为最大可用内存(就是JVM启动参数里面配置的-Xmx的值)。 # 计算总字节时只计算 Event 的主体,这也是提供 byteCapacityBufferPercentage 配置参数的原因。 # 注意,当你在一个 Agent 里面有多个内存 channel 的时候, 而且碰巧这些 channel 存储相同的物理 Event(例如:这些 channel 通过复制机制( 复制选择器 )接收同一个 source 中的 Event), 这时候这些 Event 占用的空间是累加的,并不会只计算一次。如果这个值设置为0(不限制),就会达到200G左右的内部硬件限制。 a1.channels.c1.byteCapacity = 800000 # === 举例说明 byteCapacityBufferPercentage、byteCapacity # 假设JVM最大的可用内存是100M(或者说JVM启动时指定了-Xmx=100m) 例子1:byteCapacityBufferPercentage 设置为20, byteCapacity 设置为52428800(就是50M),此时内存中所有 Event body 的总大小就被限制为50M *(1-20%)=40M,内存channel可用内存是50M。 例子2: byteCapacityBufferPercentage 设置为10, byteCapacity 不设置,此时内存中所有 Event body 的总大小就被限制为100M * 80% *(1-10%)=72M,内存channel可用内存是80M。
2.2 File Channel
-
File Channel是一个持久化的隧道(channel),数据安全并且只要磁盘空间足够,它就可以将数据存储到磁盘上。
-
必传参数:
- type:组件类型,这个是:file
-
默认情况下,文件channel使用默认的用户主目录内的检查点和数据目录的路径(就是checkpointDir参数的默认值)。 如果一个Agent中有多个活动的文件channel实例,而且都是用了默认的检查点文件, 则只有一个实例可以锁定目录并导致其他channel初始化失败。 因此,这时候有必要为所有已配置的channel显式配置不同的检查点文件目录,最好是在不同的磁盘上。 此外,由于文件channel将在每次提交后会同步到磁盘,因此将其与将Event一起批处理的sink/source耦合可能是必要的,以便在多个磁盘不可用于检查点和数据目录时提供良好的性能。
-
参考配置:
a1.channels = c1 a1.channels.c1.type = file # 记录检查点的文件的存储目录,默认 ~/.flume/file-channel/checkpoint a1.channels.c1.checkpointDir = /mnt/flume/checkpoint # 逗号分隔的目录列表,用于存储日志文件。 在不同物理磁盘上使用多个目录可以提高文件channel的性能,默认~/.flume/file-channel/data a1.channels.c1.dataDirs = /mnt/flume/data
三、常用sink
3.1 HDFS Sink
-
这个Sink将Event写入Hadoop分布式文件系统(也就是HDFS)。 目前支持创建文本和序列文件。 它支持两种文件类型的压缩。 可以根据写入的时间、文件大小或Event数量定期滚动文件(关闭当前文件并创建新文件)。 它还可以根据Event自带的时间戳或系统时间等属性对数据进行分区。 存储文件的HDFS目录路径可以使用格式转义符,会由HDFS Sink进行动态地替换,以生成用于存储Event的目录或文件名。 使用此Sink需要安装hadoop, 以便Flume可以使用Hadoop的客户端与HDFS集群进行通信。 注意, 需要使用支持sync() 调用的Hadoop版本 。
-
必传参数:
- channel: 与 Sink 连接的 channel
- type:组件类型,这个是:hdfs
- hdfs.path:HDFS目录路径(例如:hdfs://namenode/flume/webdata/)
-
参考配置:
a2.sinks.k1.type = hdfs a2.sinks.k1.channel = c1 a2.sinks.k1.hdfs.path = /nginx_logs/events/%y-%m-%d/ a2.sinks.k1.hdfs.filePrefix = events- # 是否应将时间戳向下舍入(如果为true,则影响除 %t 之外的所有基于时间的转义符),默认false a2.sinks.k1.hdfs.round = true # 向下舍入(小于当前时间)的这个值的最高倍(单位取决于下面的 hdfs.roundUnit ) # 例子:假设当前时间戳是18:32:01,hdfs.roundUnit = minute 如果roundValue=5,则时间戳会取为:18:30 如果roundValue=7,则时间戳会取为:18:28 如果roundValue=10,则时间戳会取为:18:30 # 默认1 a2.sinks.k1.hdfs.roundValue = 10 # 向下舍入的单位,可选值: second、minute、hour,默认second a2.sinks.k1.hdfs.roundUnit = minute # 使用日期时间转义符时是否使用本地时间戳(而不是使用 Event header 中自带的时间戳),默认false,hfds上目录使用了时间转换符 %y-%m-%d a2.sinks.k1.hdfs.useLocalTimeStamp = true # 使用文本文件,不使用sequenceFile,默认sequenceFile a2.sinks.k1.hdfs.fileType = DataStream # 当前文件写入达到该值时间后触发滚动创建新文件(0表示不按照时间来分割文件),单位:秒,默认30s a2.sinks.k1.hdfs.rollInterval = 0 # 当前文件写入达到该大小后触发滚动创建新文件(0表示不根据文件大小来分割文件),单位:字节,默认1024字节 a2.sinks.k1.hdfs.rollSize = 10240 # 当前文件写入Event达到该数量后触发滚动创建新文件(0表示不根据 Event 数量来分割文件),默认10 a2.sinks.k1.hdfs.rollCount = 0
3.2 Hive Sink
-
此Sink将包含分隔文本或JSON数据的 Event 直接流式传输到 Hive表或分区上。 Event 使用 Hive事务进行写入, 一旦将一组 Event 提交给Hive,它们就会立即显示给Hive查询。 即将写入的目标分区既可以预先自己创建,也可以选择让 Flume 创建它们,如果没有的话。 写入的 Event 数据中的字段将映射到 Hive表中的相应列。
-
必传参数:
- channel: 与 Sink 连接的 channel
- type:组件类型,这个是:hive
- hive.metastore:Hive metastore URI (eg thrift://a.b.com:9083 )
- hive.database:Hive 数据库名
- hive.table:Hive表名
- serializer:序列化器负责解析 Event 中的字段并把它们映射到 Hive表中的列,选择哪种序列化器取决于 Event 中的数据格式,支持的序列化器有:
DELIMITED
和JSON
- JSON :处理UTF8编码的 Json 格式(严格语法)Event,不需要配置。 JSON中的对象名称直接映射到Hive表中具有相同名称的列。 内部使用
org.apache.hive.hcatalog.data.JsonSerDe
,但独立于 Hive表的Serde
。 此序列化程序需要安装 HCatalog。 - DELIMITED: 处理简单的分隔文本 Event。 内部使用 LazySimpleSerde,但独立于 Hive表的 Serde。
- JSON :处理UTF8编码的 Json 格式(严格语法)Event,不需要配置。 JSON中的对象名称直接映射到Hive表中具有相同名称的列。 内部使用
- serializer.fieldnames:从输入字段到Hive表中的列的映射。 指定为Hive表列名称的逗号分隔列表(无空格),按顺序标识输入字段。 要跳过字段,请保留未指定的列名称。 例如, ‘time,ip,message’表示输入映射到hive表中的 time,ip 和 message 列的第1,第3和第4个字段。
-
参考配置:
a1.channels = c1 a1.channels.c1.type = memory a1.sinks = k1 a1.sinks.k1.type = hive a1.sinks.k1.channel = c1 a1.sinks.k1.hive.metastore = thrift://127.0.0.1:9083 a1.sinks.k1.hive.database = logsdb a1.sinks.k1.hive.table = weblogs # 逗号分隔的要写入的分区信息。 # 比如hive表的分区是(continent: string, country :string, time : string), 那么“Asia,India,2014-02-26-01-21”就表示数据会写入到continent=Asia,country=India,time=2014-02-26-01-21这个分区。 a1.sinks.k1.hive.partition = asia,%{country},%y-%m-%d-%H-%M a1.sinks.k1.useLocalTimeStamp = false a1.sinks.k1.round = true a1.sinks.k1.roundValue = 10 a1.sinks.k1.roundUnit = minute a1.sinks.k1.serializer = DELIMITED # (类型:字符串)传入数据中的字段分隔符。 要使用特殊字符,请用双引号括起来,例如“\t” a1.sinks.k1.serializer.delimiter = "\t" # 类型:字符)自定义底层序列化器的分隔符。如果 serializer.fieldnames 中的字段与 Hive表列的顺序相同,则 serializer.delimiter 与 serializer.serdeSeparator 相同, 并且 serializer.fieldnames 中的字段数小于或等于表的字段数量,可以提高效率,因为传入 Event 正文中的字段不需要重新排序以匹配 Hive表列的顺序。 对于’\t’这样的特殊字符使用单引号,要确保输入字段不包含此字符。 注意:如果 serializer.delimiter 是单个字符,最好将本参数也设置为相同的字符。 a1.sinks.k1.serializer.serdeSeparator = '\t' # 从输入字段到Hive表中的列的映射。 指定为Hive表列名称的逗号分隔列表(无空格),按顺序标识输入字段。 要跳过字段,请保留未指定的列名称。 例如, ‘time,,ip,message’表示输入映射到hive表中的 time,ip 和 message 列的第1,第3和第4个字段。 a1.sinks.k1.serializer.fieldnames =id,,msg
3.3 Logger Sink
-
使用INFO级别把Event内容输出到日志中,一般用来测试、调试使用。这个 Sink 是唯一一个不需要额外配置就能把 Event 的原始内容输出的Sink。
-
必传参数:
- channel: 与 Sink 连接的 channel
- type:组件类型,这个是:logger
-
參考配置:
a1.channels = c1 a1.sinks = k1 a1.sinks.k1.type = logger a1.sinks.k1.channel = c1
3.4 Avro Sink
-
这个Sink可以作为 Flume 分层收集特性的下半部分。发送到此Sink的 Event 将转换为Avro Event发送到指定的主机/端口上。Event 从 channel 中批量获取,数量根据配置的 batch-size 而定。
-
必传参数:
- channel: 与 Sink 连接的 channel
- type:组件类型,这个是:avro
- hostname:监听的服务器名(hostname)或者 IP
- port:监听的端口
-
参考配置:
a1.channels = c1 a1.sinks = k1 a1.sinks.k1.type = avro a1.sinks.k1.channel = c1 a1.sinks.k1.hostname = 10.10.10.10 a1.sinks.k1.port = 4545
3.5 HBase Sink
-
此Sink将数据写入 HBase。 Hbase 配置是从classpath中遇到的第一个 hbase-site.xml 中获取的。 配置指定的 HbaseEventSerializer 接口的实现类用于将 Event 转换为 HBase put 或 increments。 然后将这些 put 和 increments 写入 HBase。 该Sink提供与 HBase 相同的一致性保证,HBase 是当前行的原子性。 如果 Hbase 无法写入某些 Event,则Sink将重试该事务中的所有 Event。
-
这个Sink支持以安全的方式把数据写入到 HBase。为了使用安全写入模式,运行 Flume 实例的用户必须有写入 HBase 目标表的写入权限。可以在配置中指定用于对 KDC 进行身份验证的主体和密钥表。 Flume 的 classpath 中的 hbase-site.xml 必须将身份验证设置为 kerberos(有关如何执行此操作的详细信息,请参阅HBase文档)。
-
Flume提供了两个序列化器。第一个序列化器是
SimpleHbaseEventSerializer ( *org.apache.flume.sink.hbase.SimpleHbaseEventSerializer* )
,它把 Event body 原样写入到HBase,并可选增加HBase列,这个实现主要就是提供个例子。 第二个序列化器是RegexHbaseEventSerializer ( *org.apache.flume.sink.hbase.RegexHbaseEventSerializer* )
,它把 Event body 按照给定的正则进行分割然后写入到不同的列中。 -
必传参数:
- channel: 与 Sink 连接的 channel
- type:组件类型,这个是:hbase
- table: 要写入的 Hbase 表名
- columnFamily:要写入的 Hbase 列族
-
参考配置:
a1.channels = c1 a1.sinks = k1 a1.sinks.k1.type = hbase a1.sinks.k1.table = foo_table a1.sinks.k1.columnFamily = bar_cf # 指定序列化器。默认的increment column = “iCol”, payload column = “pCol”。 # 默认是 org.apache.flume.sink.hbase.SimpleHbaseEventSerializer a1.sinks.k1.serializer = org.apache.flume.sink.hbase.RegexHbaseEventSerializer a1.sinks.k1.channel = c1
-
HBase2Sink:
-
参数同上,除了type = hbase2
-
参考配置:
a1.channels = c1 a1.sinks = k1 a1.sinks.k1.type = hbase2 a1.sinks.k1.table = foo_table a1.sinks.k1.columnFamily = bar_cf a1.sinks.k1.serializer = org.apache.flume.sink.hbase2.RegexHBase2EventSerializer a1.sinks.k1.channel = c1
-