Oryx-Batch层解析

来源:互联网 发布:店铺怎么加淘宝客 编辑:程序博客网 时间:2024/06/08 18:38
1、程序入口 com.cloudera.oryx.batch.Main

public static void main(String[] args) throws Exception {
  try (BatchLayer<?,?,?> batchLayer = new BatchLayer<>(ConfigUtils.getDefault())) {
    HadoopUtils.closeAtShutdown(batchLayer);
    batchLayer.start();
    batchLayer.await();
  }
}


调用Lambda层的com.cloudera.oryx.lambda.batch.BatchLayer.start()
属性的配置文件有2个:
1)oryx-common下面的reference.conf
2)运行项目时提供的oryx.conf


BatchLayer.start()主要做的事情按顺序如下:
1、构建SparkStreamingContext, 默认批次间隔6小时(6*3600)    
generation-interval-sec 21600

2、设置SparkStreaming Checkpoint

3、构建KafkaDStream

4、对hdfs里读取的历史数据和从kafka input-topic里读取的新数据做处理,  并把处理结果推送到kafka update-topic
     这部分由BatchUpdateFunction 来处理。
     BatchUpdateFunction主要是读取data目录下的数据作为历史数据pastData.(历史数据位置 dataDirString + "/*/part-*"),
    然后调用BatchLayerUpdate接口的子类的runUpdate方法来处理历史数据pastdata和新数据newdata

5、保存从kafka input-topic里读取的新数据Data to HDFS (数据来源是Kafka InputTopic)

6、更新Kafka Offsets

7、删除data目录下过期的数据 (过期时间由maxDataAgeHours 指定)

8、删除model目录下过期的数据 (过期时间由maxModelAgeHours指定)


以ALS-Example为例详细说明下
ALS-Example 在第4步runUpdate() 处理包括: 
1) 结合历史数据pastData和新数据newData构建基于ALS的推荐模型,并筛选出最佳推荐模型
2) 把最佳推荐模型转换成PMML后保存到HDFS的model目录下, 
3) 推送模型或模型的引用到Kafka Update Topic

Oryx里专门为机器学习提供了 MLUpdate类,MLUpdate是BatchLayerUpdate的一个实现,里面包装好了很多细节处理,
自己的算法只需要再写个类,继承MLUpdate就可以了。
这边这个例子是写了一个ALSUpdate类继承MLUpdate

MLUpdate的runUpdate 的具体过程:
void runUpdate(JavaSparkContext sparkContext,
               long timestamp,
               JavaPairRDD<K,M> newData,
               JavaPairRDD<K,M> pastData,
               String modelDirString,
               TopicProducer<String,U> modelUpdateTopic)
    throws IOExceptionInterruptedException;

 4.1)把历史数据pastData和实时接收的数据newData 放进spark缓存
 4.2) 选择模型参数,创建候选模型目录,
               模型目录是 ${modelDir}  ,
               临时模型目录是 ${modelDir}/.temporary,
               候选的模型目录是 ${modelDir}/.temporary/${当前时间戳}
 4.3) 找到最佳候选模型 
               调用findBestCandidatePath(sparkContext, newData, pastData, hyperParameterCombos, candidatesPath);
               由 buildAndEval()得到模型跟评分,然后根据评分的高低找到最佳模型。
               buildAndEval的具体实现:
               1) splitTrainTest(...) 把数据拆分成训练集和测试集
               2) buildModel(...) 构建模型 //在 MLUpdate的子类ALSUpdate 里实现
               3) evaluate(...) 评估模型     //在 MLUpdate的子类ALSUpdate 里实现

 4.4)如果找到最佳候选模型,则把这个模型所在目录冲重命名为${modelDir}/${当前时间戳},并删除
              候选的模型目录${modelDir}/.temporary/${当前时间戳}

4.5)if(找到最佳候选模型){
                  PMML bestModel = null
                  if(模型需要更新 || 模型大小没有超过maxMessageSize的限制){
                         bestModel = PMMLUtils.read(in);
                  }
                  
                  if(模型大小没有超过maxMessageSize的限制){
                       //把模型直接发送到updateTopic
                       modelUpdateTopic.send("MODEL", PMMLUtils.toString(bestModel));
                  } else {
                       //超过大小限制的则把模型在HDFS上的引用位置发送到updateTopic
                       modelUpdateTopic.send("MODEL-REF", fs.makeQualified(bestModelPath).toString());
                  }

           
                  if ( 模型需要更新) {
                       publishAdditionalModelData(
                           sparkContext, bestModel, newData, pastData, finalPath, modelUpdateTopic);
                   }
                 
              }


注:
如果是采用scala 编写,实现ScalaBatchLayerUpdate trait的子类会被包装成ScalaBatchLayerUpdateAdapter,
而ScalaBatchLayerUpdateAdapter同样实现了BatchLayerUpdate接口。 也就是说最终传给BatchUpdateFunction的是实现了BatchLayerUpdate接口的子类。

总结:

BatchLayer  --> BatchUpdateFunction --> BatchLayerUpdate 实现类



以wordcount-Example为例详细说明下
在batch层,提供了ExampleBatchLayerUpdate 实现了BatchLayerUpdate
ExampleBatchLayerUpdate在runUpdate里的处理:

public void runUpdate(...) throws IOException {
  结合历史数据和新数据统计每个单词的个数.
  转成json串
  发送到kafka Update Topic// modelUpdateTopic.send("MODEL", modelString);
}


原创粉丝点击