1. 涉及技术及下载

项目开发使用到的软件有:Myeclipse2014,JDK1.8。Hadoop2.6,MySQL5.6。EasyUI1.3.6,jQuery2.0,Spring4.1.3,Hibernate4.3.1。Struts2.3.1。Maven3.2.1,Mahout0.10。

项目下载地址:https://github.com/fansy1990/mahout1.0,项目部署參考:http://blog.csdn.net/fansy1990/article/details/46481409

2. 项目介绍

此项目是在Hadoop Web项目–Friend Find系统 基础之上整理Mahout0.10版本号中MR程序的调用測试而成,重点演示怎样调用Mahout0.10的MR算法、怎样把MR算法嵌入到Web项目中,附带数据生成及数据查看、MR 任务监控等功能。

Mahout0.10的MR算法主要參考以下的文件:



此文档里面含有了覆盖经常使用工具类、聚类算法、分类算法、推荐算法等的MR调用mahout命令以及其相应的实现类。

此篇博客接下来将依照以下的内容进行编写:

  1. 项目部署及执行;
  2. 项目实现原理;
  3. 怎样进行项目二次开发;
  4. 项目眼下功能简介;
  5. 总结;

3. 项目部署及执行

3.1 下载、部署

  1. 下载project,參考上面的连接https://github.com/fansy1990/mahout1.0,并參考http://blog.csdn.net/fansy1990/article/details/46481409把它部署到Tomcat上;
  2. (默认,在上面步骤中已经配置好了mysql数据库,数据库的配置參考src/main/resources/db.properties文件)这里直接在Tomcat上执行项目。就可以初始化好mysql相应的数据表(这里仅仅有一个,即Hadoop集群配置表)。打开浏览器在左边导航栏訪问Hadoop集群配置表页面。进行配置(配置自己的集群);或直接在mysql数据库中进行配置就可以。配置项包含(这里默认是使用node101机器的配置):

mapreduce.app-submission.cross-platform=true

fs.defaultFS=hdfs://node101:8020

mapreduce.framework.name=yarn

yarn.resourcemanager.address=node101:8032

yarn.resourcemanager.scheduler.address=node101:8030

mapreduce.jobhistory.address=node101:10020

3.2 注意事项

  1. 设置Hadoop云平台系统linux的时间和执行tomcat的机器的时间一样,由于在云平台任务监控的时候使用了时间作为监控停止的信号。否则。监控模块将会有问题。

  2. 此项目中并没有开发不论什么MR程序。所以不须要拷贝源代码到Hadoop的lib文件夹(假设在进行二次开发时。开发了相关的MR,则须要拷贝)。

    项目部署好后,訪问项目url,就可以看到以下的界面:

4. 实现原理

项目组织架构:

4.1 页面框架

页面採用html+jQuery+easyUI开发,整个页面使用easyUI的layout标签,左边导航栏使用easyUI的tree标签,其数据使用json格式存储在src\main\webapp\tree_data.json文件里。

针对某个页面,其json配置例如以下:

{

“id”:152,

“text”:”fkmeans+”,

“attributes”:{

“folder”:”0”,

“url”:”clustering/fuzzykmeans.jsp”

}

}

这样在点击左边导航栏fkmeans+导航时。就可以在右边弹出clustering/fuzzykmeans.jsp页面。其js代码例如以下:

$('#navid').tree({
onClick: function(node){
// alert(node.text+","+node.url); // alert node text property when clicked
console.info("click:"+node.text);
if(node.attributes.folder=='1'){
return ;
}
console.info("open url:"+node.attributes.url)
var url;
if (node.attributes.url) {
url = node.attributes.url;
} else {
url = '404.jsp';
}
console.info("open "+url);
layout_center_addTabFun({
title : node.text,
closable : true,
iconCls : node.iconCls,
href : url
});
}
});

当中 layout_center_addTabFun函数例如以下:

function layout_center_addTabFun(opts) {

var t = $(‘#layout_center_tabs’);

if (t.tabs(‘exists’, opts.title)) {

t.tabs(‘select’, opts.title);

} else {

t.tabs(‘add’, opts);

}

console.info(“打开页面:”+opts.title);

}

这个函数主要是推断右边窗体是否有名字为给定title的页面,假设没有,则打开这个页面。

js全部代码例如以下:

当中basic.js是首页的js文件,包含一些公共的js函数等;hconstants.js主要是针对Hadoop配置表进行的操作。jquery*.js相应的两个文件为jQuery的必须文件;mr*.js相应则是MR不同类别算法相应的js处理文件;preprocess.js为数据构造、数据查看的js处理;

4.2 请求提交逻辑

请求提交主要包含:MR算法任务提交。非MR算法任务提交。其它请求提交。这里都採用统一的提交逻辑,例如以下:

4.2.1 页面提交

这里全部页面提交都直接使用easyUI的< a > 标签,同一时候在js里面绑定其提交的点击触发函数。

在函数里面须要首先获取页面參考(假设是MR监控任务。则须要先推断是否已经有监控页面。须要提示关闭当前监控页面),接着弹出框提示正在执行,最后统一提交到公共函数callByAJax中。这里列举三种提交的典型js代码:

1. 提交MR任务个数固定的MR任务

//evaluateFactorization---
$('#evaluateFactorization_submit').bind('click', function(){
// 检查是否有“MR监控页面”,假设有,则退出,并提示关闭
if(exitsMRmonitor()){
return ;
}
var input=$('#evaluateFactorization_input').val();
var output=$('#evaluateFactorization_output').val();
var userFeatures=$('#evaluateFactorization_userFeatures').val();
var itemFeatures=$('#evaluateFactorization_itemFeatures').val();
// 弹出进度框
popupProgressbar('推荐MR','evaluateFactorization任务提交中...',1000);
// ajax 异步提交任务
callByAJax('cloud/cloud_submitJob.action',{algorithm:"EvaluateFactorizationRunnable",jobnums:'1', arg1:input,arg2:output,arg3:userFeatures,arg4:itemFeatures});
});
// ------evaluateFactorization

2 提交MR个数不固定的MR任务

// kmeans---
$('#kmeans_submit').bind('click', function(){
// 检查是否有“MR监控页面”。假设有。则退出。并提示关闭
if(exitsMRmonitor()){
return ;
}
var input=$('#kmeans_input').val();//
var output=$('#kmeans_output').val();//
var clusters=$('#kmeans_clusters').val();//
var k=$('#kmeans_k').val();
var convergenceDelta=$('#kmeans_convergenceDelta').val();
var maxIter=$('#kmeans_maxIter').val();
var clustering=$('#kmeans_clustering').combobox("getValue");
var distanceMeasure=$('#kmeans_distanceMeasure').combobox("getValue");
var jobnums_=parseInt(k); // 一共的MR个数
if("true"==clustering){
jobnums_=jobnums_+1;
}
jobnums_=jobnums_+"";
// 弹出进度框
popupProgressbar('聚类MR','kmeans任务提交中...',1000);
// ajax 异步提交任务
callByAJax('cloud/cloud_submitIterMR.action',{algorithm:"KMeansDriverRunnable",jobnums:jobnums_,
arg1:input,arg2:output,arg3:clusters,arg4:k,
arg5:convergenceDelta,arg6:maxIter,arg7:clustering,arg8:distanceMeasure});
});
// ------kmeans

这里把不定MR个数的任务和定MR个数的任务区分开来了,事实上是能够不用区分的。由于在返回结果都是一个Map,依据map结果来进行操作的。只是须要在不同的实现中设置标志位(详细參考以下的实现分析)

3 提交非MR任务

$('#upload_submit').bind('click', function(){
var input=$('#upload_input').val();
var output=$('#upload_output').val();
// 弹出进度框
popupProgressbar('数据上传','数据上传中...',1000);
// ajax 异步提交任务
callByAJax('cloud/cloud_submitJobNotMR.action',{algorithm:'Upload',
arg1:input,arg2:output});
});

这里要注意MR任务和非MR任务是须要区分的,由于非MR任务使用的是同步模式(这里同步模式不是指aJax的同步。而是指实现方式),即用户点击后。会一直弹出正在处理的提示,然后等后台处理完毕。返回结果才会关闭弹窗,同一时候把结果直接展如今原网页。可是MR的任务会启动多线程,当多线程成功启动后。直接关闭提示框,同一时候打开MR任务监控页面。开启页面定时刷新任务,向后台获取任务执行情况信息。

callByAJax函数例如以下:

// 调用ajax异步提交
// 任务返回成功。则提示成功。否则提示失败的信息
function callByAJax(url,data_){
$.ajax({
url : url,
data: data_,
async:true,
dataType:"json",
context : document.body,
success : function(data) {
closeProgressbar();
console.info("close the progressbar,flag:"+data.flag);
var retMsg;
if("true"==data.flag){
retMsg='操作成功!';
if(typeof data.return_show !="undefined"){// 读取文件
var return_id = "#"+data.return_show+"";
// var obj=document.getElementById(data.return_show);
$(return_id).html(data.return_txt);
console.info('defined:'+data.return_show);
}
}else{
retMsg='操作失败! ';
if(typeof data.return_show !="undefined"){// 读取文件
var return_id = "#"+data.return_show+"";
$(return_id).html(data.msg);
}
}
$.messager.show({
title : '提示',
msg : retMsg
});
if("true"==data.flag&&"true"==data.monitor){// 加入监控页面
// 使用单独Tab的方式
layout_center_addTabFun({
title : 'MR算法监控',
closable : true,
href : 'monitor/monitor.jsp'
});
}
}
});
}

4.2.2 MR实现

全部的MR任务提交到Action后,都会启动一个线程来专门执行MR任务。这样就能够直接返回前台页面。提示任务已经成功提交。

Action中相应的代码例如以下:

/**
* 提交变jobnum的任务,暂未加入
*
*/
public void submitIterMR(){
Map<String ,Object> map = new HashMap<String,Object>();
try {
//提交一个Hadoop MR任务的基本流程
// 1. 设置提交时间阈值,并设置这组job的个数
//使用当前时间就可以,当前时间往前10s,以防server和云平台时间相差
HUtils.setJobStartTime(System.currentTimeMillis()-10000);//
// 由于不知道循环多少次完毕。所以这里设置为最大值,
// 当全部MR完毕的时候,在监控代码处又一次设置JOBNUM;
HUtils.setALLJOBSFINISHED(false);
HUtils.JOBNUM=Integer.parseInt(jobnums);
// 2. 使用Thread的方式启动一组MR任务
// 2.1 生成Runnable接口
RunnableWithArgs runJob = (RunnableWithArgs) Utils.getClassByName(
Utils.THREADPACKAGES+algorithm);
// 2.2 设置參数
runJob.setArgs(new String[]{arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11});
// 2.3 启动Thread
new Thread(runJob).start();
// 3. 启动成功后。直接返回到监控,同一时候监控定时向后台获取数据,并在前台展示;
map.put("flag", "true");
map.put("monitor", "true");
} catch (Exception e) {
e.printStackTrace();
map.put("flag", "false");
map.put("monitor", "false");
map.put("msg", "任务启动失败! ");
}
Utils.write2PrintWriter(JSON.toJSONString(map));
}

这里採用统一接口把全部的提交都整合到一个函数中。算法參数採用匿名的方式,无论前台传送了多少个,都用全部的參数来接收。

然后使用Java反射来生成实际执行任务的类。并启动多线程。

最后返回的map数据依据须要须要设置监控的flag为true(和callByAJax函数中的标识相应)。

全部MR任务都必须实现以下的接口:

/**
* 带有參数的Runnable接口
* @author fansy
* @date 2015-8-4
*/
public interface RunnableWithArgs extends Runnable {
public abstract void setArgs(String[] args);
}

该接口有两点须要注意,其一。它继承了Runnable接口。其二,它自己定义了一个setArgs函数;

以下来看一个实现,以kmeans算法的调用为例:

/**
* @author fansy
* @date 2015-8-4
*/
public class KMeansDriverRunnable implements RunnableWithArgs {
private String input;
private String output;
private String clusters;
private String k;
private String convergenceDelta;
private String maxIter;
private String clustering;
private String distanceMeasure;
@Override
public void run() {
String[] args=null;
if("true".equals(clustering)){
args=new String[17];
args[16]="-cl";
}else{
args= new String[16];
}
args[0]="-i";
args[1]=input;
args[2]="-o";
args[3]=output;
args[4]="-c";
args[5]=clusters;
args[6]="-k";
args[7]=k;
args[8]="-cd";
args[9]=convergenceDelta;
args[10]="-x";
args[11]=maxIter;
args[12]="-dm";
args[13]=distanceMeasure;
args[14]="--tempDir";
args[15]="temp";
Utils.printStringArr(args);
try {
HUtils.delete(output);
HUtils.delete("temp");
HUtils.delete(clusters);
int ret = ToolRunner.run(HUtils.getConf() ,new KMeansDriver() , args);
if(ret==0){// 全部任务执行完毕
HUtils.setALLJOBSFINISHED(true);
}
} catch (Exception e) {
e.printStackTrace();
// 任务中,报错,须要在任务监控界面体现出来
HUtils.setRUNNINGJOBERROR(true);
Utils.simpleLog("KMeansDriver任务错误!");
}
}
@Override
public void setArgs(String[] args) {
this.input=args[0];
this.output=args[1];
this.clusters=args[2];
this.k=args[3];
this.convergenceDelta=args[4];
this.maxIter=args[5];
this.clustering=args[6];
this.distanceMeasure=args[7];
}
}

首先,这里须要实现setArgs函数,这个函数就是把匿名的算法參数全部实名化(实际上,这里能够不用这一步操作的,可是为了代码的可读性。还是建议这样做)。

接着,在run函数中,依据传进来的算法參数构造MR算法须要使用的算法參数。然后直接提交MR任务就可以。

这里须要注意:

1. 当任务执行出错时须要设置标志位。方便在任务监控时,前台向后台获取任务状态信息时,提示错误;

2. 固定个数的MR任务和非固定个数的MR任务的不同点是当非固定个数的MR提前执行完毕(比方kmeans算法假设设置了循环次数为10,那么假如当循环次数达到了8次时。其阈值满足条件。退出了循环)。那么就要实时更改MR任务的次数(非固定个数MR任务最開始设置任务全部个数是依照最大值来设置的),并设置相关标识,即不用再进行监控。

4.2.3 非MR实现

与MR实现相似,非MR实现的Action函数例如以下:

/**
* 提交非MR的任务
* 算法详细參数意思对比jsp页面理解,每一个实体类会把arg1~arg11 转换为实际的意思
* @throws ClassNotFoundException
* @throws IllegalAccessException
* @throws InstantiationException
*/
public void submitJobNotMR() throws InstantiationException, IllegalAccessException, ClassNotFoundException{
Map<String ,Object> map = new HashMap<String,Object>();
INotMRJob runJob = (INotMRJob) Utils.getClassByName(
Utils.THREADNOTPACKAGES+algorithm);
// 2.2 设置參数
runJob.setArgs(new String[]{arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11});
map= runJob.runJob();
Utils.write2PrintWriter(JSON.toJSONString(map));
return ;
}

全部非MR任务都要实现INotMRJob接口,该接口定义例如以下:

/**
* 提交非MR任务的基类
* @author fansy
* @date 2015年8月5日
*/
public interface INotMRJob {
public void setArgs(String[] args);
public Map<String,Object> runJob();
}

两个函数分别相应RunnableWithArgs的两个函数。

一个读取HDFS文件的详细实现例如以下:

/**
* 读取HDFS txt文件
* @author fansy
* @date 2015年8月5日
*/
public class ReadTxt implements INotMRJob {
private String input;
private String lines;
@Override
public void setArgs(String[] args) {
this.input=args[0];
this.lines=args[1];
}
@Override
public Map<String, Object> runJob() {
Map<String ,Object> map = new HashMap<String,Object>();
String txt =null;
map.put("return_show", "readtxt_return");
try{
txt = HUtils.readTxt(input, lines, "<br>");
txt ="文件的内容是:<br>"+txt;
map.put("flag", "true");
map.put("return_txt", txt);
}catch(Exception e){
e.printStackTrace();
map.put("flag", "false");
map.put("monitor", "false");
map.put("msg", input+"读取失败!");
}
return map;
}
}

4.2.4 结果返回

非MR任务结果返回直接在原网页展示,在callByAJax中推断相应的标志位假设不为空。那么就是须要展示在原网页的,原网页中必须有相应的组件来显示,比方以下的网页代码:

<div id="upload_return" style="padding-left: 30px;font-size: 20px;padding-top:10px;"></div>

MR的任务则会开启监控。在监控页面展现任务的执行情况。

5. 二次开发

二次开发实际就是在此版本号的基础上加入自己的功能而已。

一共包含以下几个步骤:

1. 编写測试函数

比方要加入一个fuzzykmeans的算法,那么就在src/test/java里面编写測试函数,例如以下:

编写測试函数的主要目的是,研究算法的參数以及输入数据的格式等。

2. 加入json导航栏数据

在tree_data.json中加入相应的算法,例如以下:



3. 编写页面

參考1.中的全部算法须要參数来编写jsp页面,例如以下图:



4. 编写页面处理js

依据jsp页面中的button,来编写button的触发事件,例如以下:



5. 实现请求提交接口实现

编写请求提交接口的实现分为两种,假设是MR任务则实现RunnableWithArgs接口,假设是非MR任务则实现INotMRJob接口就可以。例如以下图所看到的:



6. 执行项目并測试

打开浏览器。訪问刚开发的功能,点击页面中的button进行測试,例如以下:

6. 项目功能介绍

  1. Hadoop集群配置连接查看、改动

在这里能够进行集群參数的配置。主要是连接Hadoop集群的參数;

2. 数据构造和查看

文件上传界面例如以下:

文件上传主要包含两个功能,其一就是把本地文件上传到HDFS文件;其二就是针对各个算法的数据初始化,这里的初始化基本都是把本地文件(这些文件在src/main/resources/data中已经存在)上传到HDFS指定文件夹,这里关于文件夹构造能够參考Upload.java文件:

/**

* 数据上传

* 统一命名:

上传本地文件:WEB-INF/classes/data//.

上传HDFS文件:/user/root///input.

* @author fansy

* @date 2015年8月5日

*/

其它的基本是数据查看之类的。最后一个分类数据生成,是针对输入数据须要是序列化的数据。所以这里直接生成序列化数据在HDFS指定的文件夹就可以。

3. 相关Mahout算法

相关MR算法中,页面都有默认的參数,比方:

这里的输入数据路径是依据前面Upload里面生成的路径是一致的,有些MR算法须要先执行其它MR算法,然后才干执行,这时其输入路径就是上一个MR算法相应的输出了。

7. 总结

  1. Mahout MR算法调用事实上并不难,难在了解算法的输入数据格式、算法的參数设置等。
  2. 本篇在 MR调用上面事实上并没有非常多内容。较多的是js的处理以及ssh框架的应用。
  3. 在MR的监控上面实现的思路也是能够借鉴的;
  4. 能够git该项目。然后自己编程实现某个算法的全部过程。这样学习起来乐趣很多其它(建议实现TrainLogistic相关);
  5. Mahout MR算法已经不再更新,建议能够在Hadoop MR的基础上学习Spark。

分享,成长。快乐

脚踏实地,专注

转载请注明blog地址:http://blog.csdn.net/fansy1990

Hadoop Web项目--Mahout0.10 MR算法集锦的更多相关文章

  1. Hadoop Web项目--Friend Find系统

    项目使用软件:Myeclipse10.0,JDK1.7,Hadoop2.6,MySQL5.6.EasyUI1.3.6.jQuery2.0,Spring4.1.3. Hibernate4.3.1,str ...

  2. Myeclipse 10 Maven 构建 Java Web 项目

    主要介绍如何使用 Myeclipse 10 构建 Maven Web 项目,关于 Maven 的介绍就略过了. 工具/原料 myeclipse apache-maven-3.1.0 方法/步骤 1 下 ...

  3. macOS Sierra Version 10.12.6 环境下Tomcat的下载与安装以及InterlliJ IDEA 2017.2 环境下配置Tomcat 与创建Web项目

    一.Tomcat的下载与安装 1.官网(http://tomcat.apache.org/)下载Tomcat 9.0 Core:zip包: 2.解压到指定的文件夹即可安装完成: 3.测试是否安装成功 ...

  4. web项目在iis配置好后不能正确访问问题集锦,以及IIS常规设置

    6.IIS配置好,项目无法访问,注意项目对应的应用程序池的net版本是否正确,是否集成(一般都是集成,很少是经典) 本项目用的4.0,可IIS默认程序池为2.0,将2.0改为4.0就行.   7.HT ...

  5. 那些年做过的 .NET Web 项目和 iOS 之路的一些思考

    从2010年3月份出来工作到2015年初,做过的大大小小的 .NET Web 项目如下: (1)售楼系统产品    「Role: Team Member」 (2)中弘合同管理系统    「Role: ...

  6. 真分布式SolrCloud+Zookeeper+tomcat搭建、索引Mysql数据库、IK中文分词器配置以及web项目中solr的应用(1)

    版权声明:本文为博主原创文章,转载请注明本文地址.http://www.cnblogs.com/o0Iris0o/p/5813856.html 内容介绍: 真分布式SolrCloud+Zookeepe ...

  7. web项目中遇到的Maven包依赖冲突问题解决

      在搭建web项目时,出现一个比较诡异的问题,任何JSP页面突然都不能够正常地显示,系统爆出HTTP:500(服务器内部错误)的页面   HTTP Status 500 - java.lang.No ...

  8. maven命令行创建web项目报错:java.lang.NoClassDefFoundError: org/apache/commons/lang/StringUtils

    早上一上班就想新建一个web项目玩玩,没想到一敲命令创建就失败了,真是出师不利.各种折腾无果,当然我也可以用eclipse直接创建的,就是不甘心被这破问题给耍了.刚刚才发现问题原因,这个结果我也是醉了 ...

  9. (转)shiro权限框架详解06-shiro与web项目整合(下)

    http://blog.csdn.net/facekbook/article/details/54962975 shiro和web项目整合,实现类似真实项目的应用 web项目中认证 web项目中授权 ...

随机推荐

  1. [hihocoder][Offer收割]编程练习赛57

    1-偏差排列 斐波那契数列 #pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> ...

  2. Android java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@412d7230

    近期遇到了如标题这种错误,再次记录解决方法.本文參考帖子: http://bbs.csdn.net/topics/390196217 出现此bug的原因是在内存回收上.里面用Bitamp的代码为: t ...

  3. Beta Edition [ Group 1 ]

    DeltaFish Beta Edition 一.七月开发过程 小组会议 DeltaFish 校园物资共享平台 第八次小组会议 GITHUB https://github.com/DeltaFishS ...

  4. WEB开发模式浅析

    WEB技术随着互联网的崛起而崛起,又随着移动互联网的发展而呈现更加多样化的趋势. 黑暗时代:大约在2005年以前,所谓的WEB开发主要还是美工的活,HTML/CSS占主导,Dreamwaver做为页面 ...

  5. Java中的接口详解

    接口 是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量.构造方法和成员方法,那么接口的内部主要就是封装了方法,包含抽象方法(JDK 7及以前),默认方法和静态方法(JDK 8) ...

  6. linux虚拟主机的三种方法

    虚拟主机虚拟主机是将一台(或者一组)服务器的资源(系统资源.网络带宽.存储空间等)按照一定的比例分割成若干相对独立的“小主机”的技术.每一台这样的“小主机”在功能上都可以实现WWW.FTP.Mail等 ...

  7. Html5 WebSocket详细介绍

    什么是WebSocket?看过html5的同学都知道,WebSocket protocol 是HTML5一种新的协议.它是实现了浏览器与服务器全双工通信(full-duplex).HTML5定义了We ...

  8. What is the difference between rhel 6 and rhel7

    What is the difference between rhel 6 and rhel7 difference rhel 6 RHEL 7 release date 10 NOV 2010 as ...

  9. Cat VS Dog HDU_3829(最大独立集最大匹配)

    Cat VS Dog 题意:一群小朋友去动物园,如果每个小朋友喜欢的动物是猫,那么不喜欢的动物一定是狗,反之也是.现在动物园的管理者要拿走一些动物,如果拿走的是某个小朋友不喜欢的动物,那这个小朋友就非 ...

  10. 使用scrapy爬取的数据保存到CSV文件中,不使用命令

    pipelines.py文件中 import codecs import csv # 保存到CSV文件中 class CsvPipeline(object): def __init__(self): ...