前言
为了学习分布式系统, 于是做了这个项目来练练手, 这篇文章记录了这次实战的思考和踩过的坑. 由于刚入门, 因而文章可能会有错误, 请读者勘误.
简单概述
项目采用 Spark 和 HDFS 做分布式计算和存储, 利用 Spring Boot 提供 web 服务, 利用 Redis 存储任务标识符以便于集群扩展.
用户上传包含 Word 文档的压缩文件, Web 服务器所在机器解压压缩文件, 接着提取文档内容并分词, 然后将结果存储至 HDFS 上, 再利用 Spark 进行相似度计算并返回结果.
HDFS 依赖问题
搭建 HDFS 很简单只需做简单配置便可, 但问题都出在操作文件的代码编写上.
先是依赖问题, 官网及网上都没有具体 Hadoop 依赖说明 (也可能自己没找到), 导致对需要导入那些依赖包很疑惑, 下面是自己测试的操作 HDFS 所需要的最小依赖.
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-common</artifactId>
- <version>${hadoop.version}</version>
- </dependency>
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-hdfs-client</artifactId>
- <version>${hadoop.version}</version>
- </dependency>
HDFS 配置问题
获取 FileSystem 实例前需要创建一个 Configuration 实例, 而在这之前必须设置本地 Hadoop 的目录, 和设置远程机器的用户名. 虽然这样做才能不报错, 但一直不明白为什么操作远程机器的 HDFS, 还需要本地安装的 Hadoop 目录. 不过官方也提供了 HDFS 的 REST API, 可以不依赖本地安装 Hadoop.
- System.setProperty("HADOOP_USER_NAME", userName);
- System.setProperty("hadoop.home.dir", home);
- Configuration conf = new Configuration();
- FileSystem.get(new URI("hdfs://host:port"), conf);
Spark 序列化问题
利用 Spark 进行计算时, 最主要先获取 JavaSparkContext 的实例, 以下为创建其实例的流程.
- SparkConf conf = new SparkConf();
- conf.setMaster("spark://host:port");
- conf.setAppName("demo");
- JavaSparkContext context = new JavaSparkContext(conf);
看似挺简单的流程, 但问题就出在集群模式上. 若是本地模式即指定 conf.setMaster("local") 进行调试, 进行计算的代码可以完美运行, 但是集群模式上就会出现序列化问题.
由于需要将代码分发给 Slave 节点的 Worker 进行计算, 所以会产生代码的网络传输, 而为了减少网络传输的延迟, Spark 只会分发部分代码, 所以分发的代码若是不能进行序列化就会产生问题.
还有集群模式必须指定计算代码的 Jar 包路径, 为了减少 Jar 的大小利于传输, 采用了重新建立一个项目方案, 然后在将该项目作为依赖导入主项目中, 下面为利用计算代码中的 ComputingTask 来获取 Jar 包的路径.
- String jarFile = ComputingTask.class.
- getProtectionDomain().getCodeSource().getLocation().getFile();
- context.addJar(jarFile);
Spark 数据源问题
数据源问题同样也是集群所导致的, 本地模式下运行可以使用本地文件, 但若是集群模式, 由于 Slave 节点的 Woker 获取不到本地文件就会报错. 因而数据源必须选择那些能远程使用的, 例如分布式文件系统, 数据库或者 FTP 服务器上的文件.
context.textFile("hdfs://host:port/test.txt"); // Don't use local file in cluster mode.
分词组件加载问题
项目中需要中文分词, 所以选用了 Word 分词组件, 但是每次头次加载都会花费很长时间, 于是必须进行预加载, 解决方案可以在该项目的 https://github.com/ysc/word/issues/57 中找到.
相似度计算
由于对该方面的算法了解不过, 所以对文档的相似度计算, 采用了简单地对两个文档进行杰卡德相似系数的计算, 其定义为 A 与 B 交集的大小与 A 与 B 并集的大小的比值, 下面为公式:
J(A,B) = |A ^ B| / |A v B|
项目计划
提供多种相似度的计算算法
提供 Dockerfile 方便环境的搭建
改造项目的简陋前端界面
解决无法清理临时文件问题
解决回收任务标识符问题
提供 Word 文档实时预览
项目地址为 https://github.com/linzhehuang/docdetect , 觉得不错的话欢迎 Star !
来源: https://www.cnblogs.com/linzhehuang/p/10604633.html