vlambda博客
学习文章列表

一文教您如何通过 Java 压缩文件,打包一个 tar.gz 采集器包

回复“资源”,领取全网最火的Java核心知识总结~


来源:小哈学Java



一、背景

最近,小哈主要在负责日志中台的开发工作, 等等,啥是日志中台?

一文教您如何通过 Java 压缩文件,打包一个 tar.gz 采集器包

俺只知道中台概念,这段时间的确很火,但是日志中台又是用来干啥的?

这里小哈尽量地通俗的说下日志中台的职责,再说日志中台之前,我们先扯点别的?

一文教您如何通过 Java 压缩文件,打包一个 tar.gz 采集器包

相信大家对集中式日志平台 ELK 都知道一些,生产环境中, 稍复杂的架构,服务一般都是集群部署,这样,日志就会分散在每台服务器上,一旦发生问题,想要查看日志就会非常繁琐,你需要登录每台服务器找日志,因为你不确定请求被打到哪个节点上。另外,任由开发人员登录服务器查看日志本身就存在安全隐患,不小心执行了 rm-rf* 咋办?

通过 ELK , 我们可以方便的将日志收集到一处( Elasticsearch 集群)来进行多维度的分析。

但是部署高性能、高可用的 ELK 是有门槛的,业务组想要快速的拥有集中式日志分析的能力,往往需要经过前期的技术调研,测试,踩坑,才能将这个平台搭建起来。

日志中台的使命就是让业务线能够快速拥有这种能力,只需傻瓜式的在日志平台完成接入操作即可。

一文教您如何通过 Java 压缩文件,打包一个 tar.gz 采集器包

臭嗨!说了这么多,跟你这篇文章的主题有啥关系?

额,小哈这就进入主题。

既然想统一管理日志,总得将这些分散的日志采集起来吧,那么,就需要一个日志采集器, LogstashFilebeat 都有采集日志的能力,但是 Filebeat 相较于 Logstash 的笨重, 它更轻量级,几乎零占用服务器系统资源,这里我们选型 Filebeat

业务组在日志平台完成相关接入流程后,平台会提供一个采集器包。接入方需要做的就是,下载这个采集器包并扔到指定服务器上,解压运行,即可开始采集日志,然后,就可以在日志平台的管控页面分析&搜索这些被收集的日志了。

这个 Filebeat 采集器包里面,包含了采集日志文件路径,输出到 Kafka 集群,以及一些个性化的采集规则等等。

怎么样?是不是感觉很棒呢?

二、如何通过 Java 打包文件?

2.1 添加 Maven 依赖

 
   
   
 
  1. <dependency>

  2. <groupId>org.apache.commons</groupId>

  3. <artifactId>commons-compress</artifactId>

  4. <version>1.12</version>

  5. </dependency>

2.2 打包核心代码

通过 Apachecompress 工具打包思路大致如下:

  • ①:创建一个 FileOutputStream 到输出文件(.tar.gz)文件。

  • ②:创建一个 GZIPOutputStream,用来包装 FileOutputStream对象。

  • ③:创建一个 TarArchiveOutputStream,用来包装 GZIPOutputStream对象。

  • ④:接着,读取文件夹中的所有文件。

  • ⑤:如果是目录,则将其添加到 TarArchiveEntry

  • ⑥:如果是文件,依然将其添加到 TarArchiveEntry 中,然后还需将文件内容写入 TarArchiveOutputStream 中。

接下来,直接上代码:

 
   
   
 
  1. import org.apache.commons.compress.archivers.tar.TarArchiveEntry;

  2. import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;

  3. import org.apache.commons.io.IOUtils;


  4. import java.io.*;

  5. import java.util.zip.GZIPOutputStream;


  6. /**

  7. * @date 2019-07-15

  8. * @time 16:15

  9. * @discription

  10. **/

  11. public class TarUtils {


  12. /**

  13. * 压缩

  14. * @param sourceFolder 指定打包的源目录

  15. * @param tarGzPath 指定目标 tar 包的位置

  16. * @return

  17. * @throws IOException

  18. */

  19. public static void compress(String sourceFolder, String tarGzPath) throws IOException {

  20. createTarFile(sourceFolder, tarGzPath);

  21. }


  22. private static void createTarFile(String sourceFolder, String tarGzPath) {

  23. TarArchiveOutputStream tarOs = null;

  24. try {

  25. // 创建一个 FileOutputStream 到输出文件(.tar.gz)

  26. FileOutputStream fos = new FileOutputStream(tarGzPath);

  27. // 创建一个 GZIPOutputStream,用来包装 FileOutputStream 对象

  28. GZIPOutputStream gos = new GZIPOutputStream(new BufferedOutputStream(fos));

  29. // 创建一个 TarArchiveOutputStream,用来包装 GZIPOutputStream 对象

  30. tarOs = new TarArchiveOutputStream(gos);

  31. // 若不设置此模式,当文件名超过 100 个字节时会抛出异常,异常大致如下:

  32. // is too long ( > 100 bytes)

  33. // 具体可参考官方文档:http://commons.apache.org/proper/commons-compress/tar.html#Long_File_Names

  34. tarOs.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);

  35. addFilesToTarGZ(sourceFolder, "", tarOs);

  36. } catch (IOException e) {

  37. e.printStackTrace();

  38. }finally{

  39. try {

  40. tarOs.close();

  41. } catch (IOException e) {

  42. e.printStackTrace();

  43. }

  44. }

  45. }


  46. public static void addFilesToTarGZ(String filePath, String parent, TarArchiveOutputStream tarArchive) throws IOException {

  47. File file = new File(filePath);

  48. // Create entry name relative to parent file path

  49. String entryName = parent + file.getName();

  50. // 添加 tar ArchiveEntry

  51. tarArchive.putArchiveEntry(new TarArchiveEntry(file, entryName));

  52. if (file.isFile()) {

  53. FileInputStream fis = new FileInputStream(file);

  54. BufferedInputStream bis = new BufferedInputStream(fis);

  55. // 写入文件

  56. IOUtils.copy(bis, tarArchive);

  57. tarArchive.closeArchiveEntry();

  58. bis.close();

  59. } else if (file.isDirectory()) {

  60. // 因为是个文件夹,无需写入内容,关闭即可

  61. tarArchive.closeArchiveEntry();

  62. // 读取文件夹下所有文件

  63. for (File f : file.listFiles()) {

  64. // 递归

  65. addFilesToTarGZ(f.getAbsolutePath(), entryName + File.separator, tarArchive);

  66. }

  67. }

  68. }


  69. public static void main(String[] args) throws IOException {

  70. // 测试一波,将 filebeat-7.1.0-linux-x86_64 打包成名为 filebeat-7.1.0-linux-x86_64.tar.gz 的 tar 包

  71. compress("/Users/a123123/Work/filebeat-7.1.0-linux-x86_64", "/Users/a123123/Work/tmp_files/filebeat-7.1.0-linux-x86_64.tar.gz");

  72. }


  73. }

至于代码每行都是什么意思,小伙伴们可以看代码注释,说的已经比较清楚了。

接下来,执行 main 方法,测试一下,看看打包是否成功:

一文教您如何通过 Java 压缩文件,打包一个 tar.gz 采集器包

生成采集器 tar.gz 包成功后,业务组只需将 tar.gz 下载下来,并扔到指定服务器,解压运行即可完成采集任务啦~

一文教您如何通过 Java 压缩文件,打包一个 tar.gz 采集器包

三、结语

本文主要还是介绍如何通过 Java 来完成打包功能,关于 ELK 相关的知识,小哈会在后续的文章中分享给大家,本文只是提及一下,欢迎小伙伴们持续关注哟,下期见~

四、Ref

  • https://netjs.blogspot.com/2017/05/creating-tar-file-and-gzipping-multiple-files-java.html


- END -


PS: 另外,小哈建了个学习交流群,禁广告、推广,群内氛围非常不错的,大家有啥问题也可以在群里提问,有需要的小伙伴可以加一下~

加群方式 - 扫描下方👇笔者二维码,备注:加群

一文教您如何通过 Java 压缩文件,打包一个 tar.gz 采集器包

有热门推荐👇


1. 

2. 

3. 

4. 

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)