在生产环境消费kafka传输过来的flume的采集信息的时候,发现flume的header的头信息有乱码现象出现,例如<0x04><0x10>hostname<0x1a>wangdong-test<0x10>filename<0x1a>test-log.....
这种现象导致我们在写消费者程序的时候,无法通过正常格式化json的方式或者字符串切割的方式去做解析,经查找,发现flume内部采用了apache的消息格式中间件avro,数据被source采集上来的时候直接序列化成了AvroFlumeEvent对象,在sink的时候可以直接通过getHeaders的方式获取头信息,于是,在消费者端,如果想要精准的解析头信息的话,需要先反序列化AvroFlumeEvent对象,再从中拿出header信息和body信息,下面贴一下代码:
import org.apache.avro.io.BinaryDecoder;
import org.apache.avro.io.DecoderFactory;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.flume.source.avro.AvroFlumeEvent;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
public void getHeaders(String stream)
{
AvroFlumeEvent result = null;
ByteBuffer data = null;
Map<CharSequence, CharSequence> map = null;
byte[] bytes = stream.getBytes();
/**解码还原为flumeEvent**/
SpecificDatumReader<AvroFlumeEvent> reader = new SpecificDatumReader<AvroFlumeEvent>(AvroFlumeEvent.class);
BinaryDecoder decoder = DecoderFactory.get().binaryDecoder(bytes, null);
try{
result = reader.read(null, decoder);
map = result.getHeaders();
data = result.getBody();
}catch (IOException e){
e.printStackTrace();
}
catch (Exception e)
{
e.printStackTrace();
return;
}
/**输出header信息和body信息**/
System.out.println("header: ");
for (Map.Entry<CharSequence, CharSequence>entry: map.entrySet()){
System.out.println(entry.getKey() + " : " + entry.getValue());
}
String bodyData = new String(data.array());
System.out.println("body: " + bodyData);
}
这里我的pom依赖是
<dependency>
<groupId>org.apache.flume</groupId>
<artifactId>flume-ng-sdk</artifactId>
<version>1.8.0</version>
</dependency>
和
<dependency>
<groupId>org.apache.avro</groupId>
<artifactId>avro</artifactId>
<version>1.8.1</version>
</dependency>
请各位用java开发flume日志消费的小伙伴了解一下。