Flume Interceptors的使用

本文详细介绍了Flume拦截器的功能及使用方法,包括TimestampInterceptor、HostInterceptor等,并通过实例展示了如何利用RegexFilteringInterceptor和TimestampInterceptor实现日志过滤与时间戳添加。

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

对于flume拦截器,我的理解是:在app(应用程序日志)和 source 之间的,对app日志进行拦截处理的。也即在日志进入到source之前,对日志进行一些包装、清新过滤等等动作。

官方上提供的已有的拦截器有:

Timestamp Interceptor
Host Interceptor
Static Interceptor
Regex Filtering Interceptor
Regex Extractor Interceptor

像很多java的开源项目如springmvc中的拦截器一样,flume的拦截器也是chain形式的,可以对一个source指定多个拦截器,按先后顺序依次处理。

Timestamp Interceptor :在event的header中添加一个key叫:timestamp,value为当前的时间戳。这个拦截器在sink为hdfs 时很有用,后面会举例说到
Host Interceptor:在event的header中添加一个key叫:host,value为当前机器的hostname或者ip。
Static Interceptor:可以在event的header中添加自定义的key和value。
Regex Filtering Interceptor:通过正则来清洗或包含匹配的events。
Regex Extractor Interceptor:通过正则表达式来在header中添加指定的key,value则为正则匹配的部分

下面举例说明这些拦截器的用法,首先我们调整一下第一篇文章中的那个WriteLog类:
[java]  view plain  copy
  1. public class WriteLog {  
  2.     protected static final Log logger = LogFactory.getLog(WriteLog.class);  
  3.   
  4.     /** 
  5.      * @param args 
  6.      * @throws InterruptedException 
  7.      */  
  8.     public static void main(String[] args) throws InterruptedException {  
  9.         // TODO Auto-generated method stub  
  10.         while (true) {  
  11.             logger.info(new Date().getTime());  
  12.             logger.info("{\"requestTime\":"  
  13.                     + System.currentTimeMillis()  
  14.                     + ",\"requestParams\":{\"timestamp\":1405499314238,\"phone\":\"02038824941\",\"cardName\":\"测试商家名称\",\"provinceCode\":\"440000\",\"cityCode\":\"440106\"},\"requestUrl\":\"/reporter-api/reporter/reporter12/init.do\"}");  
  15.             Thread.sleep(2000);  
  16.   
  17.         }  
  18.     }  
  19. }  
又多输出了一行日志信息,现在每次循环都会输出两行日志信息,第一行是一个时间戳信息,第二行是一行JSON格式的字符串信息。

接下来我们用regex_filter和 timestamp这两个拦截器来实现这样一个功能:
1 过滤掉LOG4J输出的第一行那个时间戳日志信息,只收集JSON格式的日志信息
2 将收集的日志信息保存到HDFS上,每天的日志保存到以该天命名的目录下面,如2014-7-25号的日志,保存到/flume/events/14-07-25目录下面。

修改后的flume.conf如下:
[plain]  view plain  copy
  1. tier1.sources=source1  
  2. tier1.channels=channel1  
  3. tier1.sinks=sink1  
  4.   
  5. tier1.sources.source1.type=avro  
  6. tier1.sources.source1.bind=0.0.0.0  
  7. tier1.sources.source1.port=44444  
  8. tier1.sources.source1.channels=channel1  
  9.   
  10. tier1.sources.source1.interceptors=i1 i2  
  11. tier1.sources.source1.interceptors.i1.type=regex_filter  
  12. tier1.sources.source1.interceptors.i1.regex=\\{.*\\}  
  13. tier1.sources.source1.interceptors.i2.type=timestamp  
  14.   
  15. tier1.channels.channel1.type=memory  
  16. tier1.channels.channel1.capacity=10000  
  17. tier1.channels.channel1.transactionCapacity=1000  
  18. tier1.channels.channel1.keep-alive=30  
  19.   
  20. tier1.sinks.sink1.type=hdfs  
  21. tier1.sinks.sink1.channel=channel1  
  22. tier1.sinks.sink1.hdfs.path=hdfs://master68:8020/flume/events/%y-%m-%d  
  23. tier1.sinks.sink1.hdfs.fileType=DataStream  
  24. tier1.sinks.sink1.hdfs.writeFormat=Text  
  25. tier1.sinks.sink1.hdfs.rollInterval=0  
  26. tier1.sinks.sink1.hdfs.rollSize=10240  
  27. tier1.sinks.sink1.hdfs.rollCount=0  
  28. tier1.sinks.sink1.hdfs.idleTimeout=60  

我们对source1添加了两个拦截器i1和i2,i1为regex_filter,过滤的正则为\\{.*\\},注意正则的写法用到了转义字符,不然source1无法启动,会报错。
i2为timestamp,在header中添加了一个timestamp的key,然后我们修改了sink1.hdfs.path在后面加上了/%y-%m-%d这一串字符,这一串字符要求event的header中必须有timestamp这个key,这就是为什么我们需要添加一个timestamp拦截器的原因,如果不添加这个拦截器,无法使用这样的占位符,会报错。还有很多占位符,请参考官方文档。

然后运行WriteLog,去hdfs上查看对应目录下面的文件,会发现内容只有JSON字符串的日志,与我们的功能描述一致。

补充知识:
a1.sources.r1.interceptors.i1.regex = (\\d):(\\d):(\\d)
a1.sources.r1.interceptors.i1.serializers = s1 s2 s3
a1.sources.r1.interceptors.i1.serializers.s1.name = one
a1.sources.r1.interceptors.i1.serializers.s2.name = two
a1.sources.r1.interceptors.i1.serializers.s3.name = three

The extracted event will contain the same body but the following headers will have been added one=>1, two=>2, three=>3


### Flume 自定义拦截器不生效解决方案 #### 1. 检查配置文件语法正确性 确保 `flume-conf.properties` 文件中的配置项书写无误。特别是对于自定义拦截器部分,应严格按照官方文档格式编写。例如,在给定的配置中: ```properties a1.sources.r1.interceptors.i2.type = cn.doitedu.flume.custom.EncryptInterceptor$EncryptInterceptorBuilder ``` 此行指定了名为 `i2` 的拦截器及其构建类路径[^2]。 #### 2. 校验依赖库加载情况 确认项目打包时已将所有必要的 JAR 包放置于 FLUME_CLASSPATH 中,尤其是包含自定义拦截器实现逻辑的那个 jar 文件。这一步骤至关重要,因为缺少相应的 class 可能导致初始化失败而不会抛出明显错误提示。 #### 3. 日志级别设置适当 为了更好地排查问题所在,建议临时提高 flume agent 运行期间的日志输出等级至 DEBUG 或 TRACE 级别。通过查看更详细的日志记录来定位具体原因。可以编辑启动脚本或直接修改配置文件内的 logger 设置: ```bash agent.logger.rootLogger=DEBUG,LOGFILE,R ``` #### 4. 测试环境验证 尝试创建一个最简单的测试场景来进行功能验证。比如先去掉其他复杂组件干扰因素,仅保留最基本的 source-channel-sink 组合加上待调试的 interceptor 。这样有助于排除外部变量影响并快速锁定核心问题。 #### 5. 完整示例代码展示 下面给出一段完整的 Java 类作为参考,用于说明如何开发及注册一个新的加密型拦截器(`EncryptInterceptor`) : ```java package cn.doitedu.flume.custom; import org.apache.flume.Context; import org.apache.flume.Event; import org.apache.flume.interceptor.Interceptor; import javax.crypto.Cipher; import java.util.ArrayList; import java.util.List; public class EncryptInterceptor implements Interceptor { private static final String ALGORITHM = "AES"; @Override public void initialize() {} @Override public Event intercept(Event event) { try{ byte[] bodyBytes = event.getBody(); Cipher cipher = Cipher.getInstance(ALGORITHM); // ... 加密处理 ... event.setBody(cipher.doFinal(bodyBytes)); return event; }catch(Exception e){ System.err.println("Encryption failed."); return null; } } @Override public List<Event> intercept(List<Event> events) { List<Event> interceptedEvents = new ArrayList<>(events.size()); for (Event event : events) { Event interceptedEvent = intercept(event); if(interceptedEvent != null){ interceptedEvents.add(interceptedEvent); } } return interceptedEvents; } @Override public void close(){} public static class Builder implements Interceptor.Builder { @Override public Interceptor build(){ return new EncryptInterceptor(); } @Override public void configure(Context context){} } } ``` 上述代码片段展示了如何基于 Apache Flume API 创建一个实现了 `org.apache.flume.interceptor.Interceptor` 接口的新类型,并提供了配套的工厂方法以便实例化对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值