1、程序入口 com.cloudera.oryx.serving.Main
public static void main(String[] args) throws Exception {
try (ServingLayer servingLayer = new ServingLayer(ConfigUtils.getDefault())) {
JVMUtils.closeAtShutdown(servingLayer);
servingLayer.start();
servingLayer.await();
}
}
try (ServingLayer servingLayer = new ServingLayer(ConfigUtils.getDefault())) {
JVMUtils.closeAtShutdown(servingLayer);
servingLayer.start();
servingLayer.await();
}
}
调用Lambda层的com.cloudera.oryx.lambda.serving.SpeedLayer.start()
属性的配置文件有2个:
1)oryx-common下面的reference.conf
2)运行项目时提供的oryx.conf
SpeedLayer.start()主要做的事情就是: 配置并启动Tomcat
1、重点分析makeContext()这个方法
要加载的哪些应用都是在makeContext里配置
this.
appResourcesPackages =
config.getString("
oryx.serving.application-resources") + "," + "
com.cloudera.oryx.lambda.serving";
// OryxApplication only needs one config value, so just pass it
context.addParameter(OryxApplication.class.getName() + ".packages",
appResourcesPackages);
tomcat会加载
oryx.serving.application-resources指定的类
和com.cloudera.oryx.lambda.serving下面的类。
2、com.cloudera.oryx.lambda.serving.ModelManagerListener
ModelManagerListener继承了ServletContextListener
在
ModelManagerListener 里,会做2件事
1)生成一个input-topic的生产者producer,放入到servletContext里面
2)生成一个update-topic的消费者consumer, 加载实现ServingModelManager接口的子类,例如:ALSServingModelManager。
然后单独起一个线程从update-topic里获取模型(modelManager.consume(consumer ))
3、WEBAPI部分
以recommend为例,有一个对应的Recommend 类来处理对/recommend的请求
@Path(
"/recommend")
public final class Recommend extends AbstractALSResource {
public final class Recommend extends AbstractALSResource {
在Recommend里,会去获取相应的model,然后给出topN个结果model.topN
ALSServingModel model = getALSServingModel()
;
Stream<Pair<String
,Double>> topIDDots = model.topN(
new DotsFunction(userVector) ,
rescoreFn ,
howManyOffset ,
allowedFn) ;
return toIDValueResponse(topIDDots , howMany , offset) ;
new DotsFunction(userVector) ,
rescoreFn ,
howManyOffset ,
allowedFn) ;
return toIDValueResponse(topIDDots , howMany , offset) ;
暴露webapi需要定义自己对请求处理的类
例如Recommend或者example里的ADD,需要实现OryxResource接口
**
* Responds to a POST request to { @code /add/[line]}. Adds a new line of input for processing.
* Also responds to a POST to { @code /add} which contains lines in the request body.
*/
@Path( "/add")
public final class Add extends OryxResource {
@POST
@Path( "{line}")
public void add( @PathParam( "line") String line) {
getProducer().send( null, line) ;
}
@POST
@Consumes({MediaType. TEXT_PLAIN , MediaType. APPLICATION_JSON})
public void post(Reader reader) throws IOException {
TopicProducer<? ,String> inputProducer = getProducer() ;
BufferedReader buffered = new BufferedReader(reader) ;
for (String line ; (line = buffered.readLine()) != null;) {
inputProducer.send( null, line) ;
}
}
private TopicProducer<? ,String> getProducer() {
@SuppressWarnings( "unchecked")
TopicProducer<? ,String> inputProducer = (TopicProducer<? ,String>) getInputProducer() ;
return inputProducer ;
}
* Responds to a POST request to { @code /add/[line]}. Adds a new line of input for processing.
* Also responds to a POST to { @code /add} which contains lines in the request body.
*/
@Path( "/add")
public final class Add extends OryxResource {
@POST
@Path( "{line}")
public void add( @PathParam( "line") String line) {
getProducer().send( null, line) ;
}
@POST
@Consumes({MediaType. TEXT_PLAIN , MediaType. APPLICATION_JSON})
public void post(Reader reader) throws IOException {
TopicProducer<? ,String> inputProducer = getProducer() ;
BufferedReader buffered = new BufferedReader(reader) ;
for (String line ; (line = buffered.readLine()) != null;) {
inputProducer.send( null, line) ;
}
}
private TopicProducer<? ,String> getProducer() {
@SuppressWarnings( "unchecked")
TopicProducer<? ,String> inputProducer = (TopicProducer<? ,String>) getInputProducer() ;
return inputProducer ;
}