如何在servlet中使用spark集群计算功能

时间:2014-05-20 06:27:29

标签: tomcat servlets apache-spark

我正在开发一个动态网络项目。我想编写一个servlet类来响应帧提交请求,并使用apache spark执行一些集群计算任务(例如,计算pi)。 servlet的doGet函数(名为Hello)如下:

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    String [] args=new String[2];
    args[0]="local";
    args[1]="4";
    double count=0;
    count=performSpark.cpi(args);
    //double count=3.14;
    String text1 =String.valueOf(count);
    response.sendRedirect("wresultjsp.jsp?text1=" + text1);  
}

performSpark类如下:

public class performSpark {
    static double cpi(String[] input)
    {
        JavaSparkContext jsc = new JavaSparkContext(input[0], "performspark",
        System.getenv("SPARK_HOME"), JavaSparkContext.jarOfClass(performSpark.class));

        int slices = (input.length == 2) ? Integer.parseInt(input[1]) : 2;
        int n = 1000000 * slices;
        List<Integer> l = new ArrayList<Integer>(n);
        for (int i = 0; i < n; i++) 
        {
            l.add(1);
        }

        JavaRDD<Integer> dataSet = jsc.parallelize(l);

        int count = dataSet.map(new Function<Integer, Integer>() {
            @Override
            public Integer call(Integer integer) {
                double x = Math.random() * 2 - 1;             
                double y = Math.random() * 2 - 1;
                return (x * x + y * y < 1) ? 1 : 0;
            }
        }).reduce(new Function2<Integer, Integer, Integer>() {
            @Override
            public Integer call(Integer integer, Integer integer2) {
                return integer + integer2;
            }
        });

        double result=4.0 * count / n;      
        return result;
    }
}

spark-assemply-2.10-0.9.1-hadoop2.2.0.jar被复制到WEB-INF/lib。 构建成功但是当我在tomcat7服务器中运行servlet时,在创建JavaSparkContext时会报告java.lang.ClassNotFoundException

  

用于servlet [Hello]的Servlet.service()与path的上下文   [/ sparkdemo]抛出异常[Servlet执行抛出异常]   根本原因java.lang.ClassNotFoundException:   org.apache.spark.api.java.function.Function at   org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)     在   org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)     在Hello.doGet(Hello.java:54)的Hello.doPost(Hello.java:74)at   javax.servlet.http.HttpServlet.service(HttpServlet.java:646)at at   javax.servlet.http.HttpServlet.service(HttpServlet.java:727)

任何人都知道如何纠正这个问题?

2 个答案:

答案 0 :(得分:1)

最后,我找到了解决方案如下。

当tomcat服务器启动时,它会加载spark-assemply-2.10-0.9.1-hadoop2.2.0.jar并报告错误:validateJarFile (.....) - jar not loaded. See Servlet Spec3.0 ......,这表示存在一些重叠的jar依赖关系。

然后我打开spark-assemply-2.10-0.9.1-hadoop2.2.0.jar并在javax / servlet中找到重叠的文件夹。删除servlet文件夹后,spark-assemply-2.10-0.9.1-hadoop2.2.0.jar在tomcat中成功加载,ClassNotFoundException消失。

答案 1 :(得分:0)

我们在项目中有一个类似的用例,我们要提交用户查询以从Web项目中以交互方式触发。 实现此目标的方法是,首先创建一个spark会话,然后将其自定义servlet附加到:.attachHandler()

在自定义servlet的attachHandler方法中,我们将Servlet类附加到spark的ServletContextHandler:

ServletContextHandler handler = new ServletContextHandler();
HttpServlet servlet = new <CustomServlet>(spark);
ServletHolder sh = new ServletHolder(servlet);
handler.setContextPath(<root context>);
handler.addServlet(sh, <path>);
spark.sparkContext().ui().get().attachHandler(handler);

现在,该Servlet已在端口4040上附加到Spark UI,例如,您可以直接向其提交请求。我们覆盖了servlet的doGet方法,以接受包含要运行的SQL的JSON,并使用
提交了SQL     ds = this.spark.sql(query); 迭代返回的数据集,并将其添加到响应对象。

另一种方法是利用Apache Livy。

希望这会有所帮助。