flume收集到的日志,采用ElasticSearch作为存储,运行一段时间后,发现每天早点八点才会创建索引文件,比北京时间晚了8个小时,导致0点到8点这段时间的数据并没有存储到今天的索引文件中,而是存储在前一天的索引中,当时以为数据丢失了,全文检索后发现数据被存在了前一天的索引文件中。首先确定系统的时间是准备的,基本定位到应该是flume自身创建索引的时候除了问题,查看源代码。
flume创建ElasticSearch索引文件的代码如下
if (indexRequestBuilderFactory == null) {
indexRequestBuilder = client
.prepareIndex(indexNameBuilder.getIndexName(event), indexType)
.setSource(serializer.getContentBuilder(event).bytes());
} else {
indexRequestBuilder = indexRequestBuilderFactory.createIndexRequest(
client, indexNameBuilder.getIndexPrefix(event), indexType, event);
}
下面看indexNameBuilder.getIndexName(event)获取索引
@Override
public String getIndexName(Event event) {
TimestampedEvent timestampedEvent = new TimestampedEvent(event);
long timestamp = timestampedEvent.getTimestamp();
return new StringBuilder(indexPrefix).append('-')
.append(fastDateFormat.format(timestamp)).toString();
}
TimestampedEvent(Event base) {
setBody(base.getBody());
Map<String, String> headers = Maps.newHashMap(base.getHeaders());
String timestampString = headers.get("timestamp");
if (StringUtils.isBlank(timestampString)) {
timestampString = headers.get("@timestamp");
}
if (StringUtils.isBlank(timestampString)) {
this.timestamp = DateTimeUtils.currentTimeMillis();
headers.put("timestamp", String.valueOf(timestamp ));
} else {
this.timestamp = Long.valueOf(timestampString);
}
setHeaders(headers);
}
TimestampedEvent会先获取事件中的timestamp,如果事件中没有timestamp,就取当前的毫秒时间。
fastDateFormat会格式化timestamp,也就是生成索引后面的日期,如flume-2015-01-01,fastDateFormat默认会采用Etc/UTC时区,也就是会比北京时间晚8小时,北京时间早上8点,获取到的就是0点。
private FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyy-MM-dd",
TimeZone.getTimeZone("Etc/UTC"));
另外可以通过配置文件来配置fastDateFormat的时区,我们采用即可
a1.sinks.k1.timeZone=Asia/Shanghai
使用ElasticSearch sink的时候,要加上上面这句话,这样就可以解决创建索引晚8小时的问题了。