实现功能:定时日志采集并上传至HDFS文件系统的Java API实现
环境+工具:windows + 虚拟机Centos * 2 + eclipse + windows下编译的Hadoop jar包 + Hadoop集群
一、流程
1)启动一个定时任务,规划各种路径
——定时探测日志源目录 (本地目录) F:/logs/get_log/ ;
——获取需要采集的文件 (文件过滤器,比如以get_log开头);
——移动这些文件到一个待上传临时目录 F:/logs/uptoload/ ;
——遍历临时文件目录,逐一传输至HDFS的目标路径(若不存在则创建) /access_log/logs_日期/
上传以后HDFS文件系统中重命名的前缀:get_log_ ; 文件的后缀:.log
——同时将传输完成的文件移动到备份目录(若不存在则创建) F:/logs/backup_日期/
启动第二个定时任务
2)采用log4j输出文件采集日志
实现代码:
1.创建LogAccess类
package hdfs_log;
import java.util.Timer;
import java.util.TimerTask;
public class LogAccess {
public static void main(String[] args) {
//定义一个定时器对象,每隔1小时运行一次日志获取任务
Timer tm = new Timer();
//继承TimerTask类,重新run方法
tm.schedule(new AccessTask(), 0, 60*60*1000L);
}
}
2.Timer schedule方法中的第一个参数为 TimerTask的子类,并重写run()方法
package hdfs_log;
import java.io.File;
import java.io.FilenameFilter;
import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.TimerTask;
import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.log4j.Logger;
public class AccessTask extends TimerTask {
@Override
public void run() {
// TODO Auto-generated method stub
//构造一个log4j日志对象
Logger logger = Logger.getLogger("logRollingFile");
//获取日志采集日期,用于命名
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH");
String date = sdf.format(new Date());
//创建本地日志源目录,通过文件过滤实现特定文件提取,存储在文件列表中
File srcDir = new File("f:/logs/get_log/");
File[] srcList = srcDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
// 提取以get_log为前缀的日志文件
if(name.startsWith("get_log.")) {
return true;
}else {
return false;
}
}
});
//输出日志信息
logger.info("探测到如下文件需要采集" + Arrays.toString(srcList));
//移动文件至待上传临时目录
try {
File toupload = new File("f:/logs/toupload/");
for(File srcfile: srcList) {
FileUtils.moveFileToDirectory(srcfile, toupload, true);
}
//输出日志信息
logger.info("文件上传至临时目录:" + toupload.getAbsolutePath());
//建立hdfs访问,将临时目录内文件上传至hdfs文件系统
FileSystem fs = FileSystem.get(new URI("hdfs://192.168.235.143:9000/"), new Configuration(), "hadoop000");
File[] toupload_List = toupload.listFiles();
//判断hdfs和备份目录是否存在,若不存在则创建
Path hdfsDir = new Path("/access_log/logs4" + date);
if(!fs.exists(hdfsDir)){
fs.mkdirs(hdfsDir);
}
File backupDir = new File("f:/logs/backup" + date);
if(!backupDir.exists()) {
backupDir.mkdirs();
}
//上传文件至hdfs文件
for(File load_file:toupload_List) {
Path hdfs_dst = new Path("/access_log/logs4"+date+"/get_log_"+UUID.randomUUID()+".log");
fs.copyFromLocalFile(new Path(load_file.getAbsolutePath()), hdfs_dst);
//输出日志信息
logger.info("日志上传至HDFS文件目录:" + hdfs_dst);
//将文件移动至备份文件目录,输出日志信息
FileUtils.moveFileToDirectory(load_file, backupDir, true);
logger.info("日志备份至如下文件目录:" + backupDir);
}
fs.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
3.运行结果
输出日志信息:
2018-八月-24 11:23:16-[TS] INFO Timer-0 logRollingFile - 探测到如下文件需要采集[f:\logs\get_log\get_log.1, f:\logs\get_log\get_log.3]
2018-八月-24 11:23:16-[TS] INFO Timer-0 logRollingFile - 文件上传至临时目录:f:\logs\toupload
2018-八月-24 11:23:22-[TS] INFO Timer-0 logRollingFile - 日志上传至HDFS文件目录:/access_log/logs42018-08-24-11/get_log_787bb116-6d14-4cd3-bddf-a33e28740aec.log
2018-八月-24 11:23:22-[TS] INFO Timer-0 logRollingFile - 日志备份至如下文件目录:f:\logs\backup2018-08-24-11
2018-八月-24 11:23:22-[TS] INFO Timer-0 logRollingFile - 日志上传至HDFS文件目录:/access_log/logs42018-08-24-11/get_log_f75f220a-3202-4b2f-be1f-f5c4c3a06095.log
2018-八月-24 11:23:22-[TS] INFO Timer-0 logRollingFile - 日志备份至如下文件目录:f:\logs\backup2018-08-24-11