SpringMVC 与 spark 整合教程

有时候 我们会遇到一些 需要通过API调用来启动spark的job的问题 

         这时候 我们会想到 一个项目 spark jobserver 他是一个rest风格的spark 管理接口让spark服务方式运行

        昨天有小伙伴问我,我也是java服务器的,我们希望直接本地可以调试的 本地可以直接运行的 ,在springMVC上 Ok 

        这一章我们讲一下 怎么配置springMVC 与 Spark整合

         其实主要原因是tomcat servlet会与spark的servlet有冲突,如果你用的jetty服务器根本不会冲突,所以下面的配置是针对你是tomcat服务器的用户来说的。

  1. POM文件配置 关键的一些部分

 <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.10</artifactId>
            <version>1.6.0</version>
            <exclusions>
            
            <exclusion>
            <artifactId>javax.servlet</artifactId>
            <groupId>org.eclipse.jetty.orbit</groupId>
            </exclusion>
            <exclusion>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
</exclusion>
            <exclusion>
            <artifactId>
            jersey-test-framework-grizzly2
            </artifactId>
            <groupId>
            com.sun.jersey.jersey-test-framework
            </groupId>
            </exclusion>
            
            </exclusions>
  </dependency>
 <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.4.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-scala_2.10</artifactId>
<version>2.4.4</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

   2.我们知道spring IOC 控制反转 有几种方式 1.接口  2. 构造 3,set  另外还有工厂方式 

    下面我们来定义一个spring 的bean 

     

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaSparkContext;
import org.springframework.beans.factory.FactoryBean;

public class SparkContextFactoryBean implements FactoryBean<JavaSparkContext>{

	
	
	private String master;//主
	
	
	private String appName;
	
	
	
	
	

	public String getAppName() {
		return appName;
	}

	public void setAppName(String appName) {
		this.appName = appName;
	}

	public String getMaster() {
		return master;
	}

	public void setMaster(String master) {
		this.master = master;
	}

	
	
	
	@Override
	public JavaSparkContext getObject() throws Exception {
		 SparkConf conf = new SparkConf().setAppName(appName).setMaster(master);
		 //另外一些环境变量的添加
		 conf.set("spark.serializer","org.apache.spark.serializer.KryoSerializer");
		 //.set("spark.executor.memory", "1g")
//		 .set("spark.executor.memory", "128m")
//         .set("spark.cores.max", "1")
//         .set("spark.default.parallelism", "3");

		 return  new JavaSparkContext(conf);
	}

	@Override
	public Class<?> getObjectType() {
		
		return JavaSparkContext.class;
	}

	@Override
	public boolean isSingleton() {
		
		return true;
	}

}

    spring.xml配置文件中配置一下 bean

    

  <bean id="sparkContext" class="com.zsuper.ignite.service.SparkContextFactoryBean" scope="singleton">
    <property name="master" value="local"></property>
    <property name="appName" value="sparkdeepSpark"></property>
    </bean>

   下面我们在controller中定义一些测试

   

private static final FlatMapFunction<String, String> WORDS_EXTRACTOR =
		      new FlatMapFunction<String, String>() {
		        @Override
		        public Iterable<String> call(String s) throws Exception {
		          return Arrays.asList(s.split(" "));
		        }
		      };

		  private static final PairFunction<String, String, Integer> WORDS_MAPPER =
		      new PairFunction<String, String, Integer>() {
		        @Override
		        public Tuple2<String, Integer> call(String s) throws Exception {
		        	//logger("================"+s);
		          return new Tuple2<String, Integer>(s, 1);
		        }
		      };

		  private static final Function2<Integer, Integer, Integer> WORDS_REDUCER =
		      new Function2<Integer, Integer, Integer>() {
		        @Override
		        public Integer call(Integer a, Integer b) throws Exception {
		        	System.out.println("###############"+(a+b));
		          return a + b;
		        }
		      };
	  private static Logger logger = LoggerFactory.getLogger(TestController.class);
	 
	  private static List<File> getFiles(String fileName) {
		    File file=new File(fileName);
		    return Lists.newArrayList(file.listFiles(new FilenameFilter() {
				
				@Override
				public boolean accept(File dir, String name) {
					if(name.endsWith(".jpg")||name.endsWith(".png")) return true;
					return false;
				}
			}));
	  }
	  
	  
	  @RequestMapping(value="/test",method=RequestMethod.GET)
	  @ResponseBody
	  public Json test(HttpServletRequest request,HttpServletResponse response){
		 
		SparkIgniteService service=ServiceGenerator.createIgniteService(ignite,"sparkIgniteServiceNode",SparkIgniteService.class, false);
		JavaSparkContext context=service.getSparkContext();
		JavaRDD<String> file = context.textFile("C:/iris_training.txt");
	    JavaRDD<String> words = file.flatMap(WORDS_EXTRACTOR);
	    JavaPairRDD<String, Integer> pairs = words.mapToPair(WORDS_MAPPER);
	    JavaPairRDD<String, Integer> counter = pairs.reduceByKey(WORDS_REDUCER);

	    counter.repartition(1).saveAsTextFile("C:/baidu/test.txt");
		
		Json json=new Json();
		json.setKey("it is ok");
		return json;
	  }

    这里 我使用的是上面的spring的bean 再次整合到Apache ignite里面,我一直喜欢使用apache ignite 网格计算的优越性 大家也许不能深有体会,我使用了快一年了,怎么说呢,apache ignite 可以做到storm的实时云计算的效果,可以做到memcache redis缓存的效果,可以做到分布式负载 计算 等效果,最吸引人的地方是 能够更高性能的控制CPU 线程 内存,于是我抛弃了dubbo一类的分布式的RPC平台,性能比起网格计算来说 只是一个负载均衡 而已,不能充分利用CPU ,使用apache ignite 有什么好处呢,这里我举个例子,加入我一个接口 在正常一台服务器上执行需要1s 但是 你们传统的dubbo 或者 其他的LVS 通过DNS 或者其他反向代理负载均衡的 本质上还是调用到某一台服务器上,而apache ignite 能够保证每一次任务都是所有的服务器并行网格计算。所以2台服务器接口就只需要0.5s 3台可能只需要0.3s 服务器数目越多,最后真是0.00s就执行完了 ,我深有体会,使用了一年多来,10台服务器 apache ignite的计算能力 已经 远远比我storm速度还要快。这是真实体验。

     下面我也贴出来apache ignite整合 与 上面的spring spark的bean

     

/**
 * 独立模式 全局一个 保证sparkContext上下文一直
 * @author zhuyuping
 * 2016年2月28日
 */
public class SparkIgniteServiceImpl implements SparkIgniteService,Service{
	
	
	@IgniteInstanceResource
	private Ignite ignite;
	
	
	
	private String master="local";
	
	private String appName="imagesearch";
	
	private Integer batchinteval=100;
	
	public void setBatchinteval(Integer batchinteval) {
		this.batchinteval = batchinteval;
	}

	public void setMaster(String master) {
		this.master = master;
	}

	public void setAppName(String appName) {
		this.appName = appName;
	}

	@Override
	public void cancel(ServiceContext ctx) {
		
		
	}

	@Override
	public void init(ServiceContext ctx) throws Exception {
		System.setProperty("hadoop.home.dir", "C:\\spark\\hadoop-2.6.0");
		System.out.println(System.getenv("HADOOP_HOME"));
		System.out.println("########################ignite Spark 服务启动 #########################");
		
	}

	@Override
	public void execute(ServiceContext ctx) throws Exception {
		
		
	}

	@Override
	public JavaSparkContext getSparkContext() {
//		 SparkConf conf = new SparkConf().setAppName(appName).setMaster(master);
//		 //另外一些环境变量的添加
//		 conf.set("spark.serializer","org.apache.spark.serializer.KryoSerializer");
//		 //.set("spark.executor.memory", "1g")
////		 .set("spark.executor.memory", "128m")
////         .set("spark.cores.max", "1")
////         .set("spark.default.parallelism", "3");
//		 return  new JavaSparkContext(conf);
		return (JavaSparkContext) SpringContextHolder.getApplicationContext().getBean("sparkContext");
	}

	

	@Override
	public ApplicationContext getSpringContext() {
		
		return SpringContextHolder.getApplicationContext();
	}

}

    下面 是controller中 我们添加测试的接口 。当成功了 返回it is ok

     

@Controller
@RequestMapping("/image")
public class TestController extends BaseController{

	 private static final FlatMapFunction<String, String> WORDS_EXTRACTOR =
		      new FlatMapFunction<String, String>() {
		        @Override
		        public Iterable<String> call(String s) throws Exception {
		          return Arrays.asList(s.split(" "));
		        }
		      };

		  private static final PairFunction<String, String, Integer> WORDS_MAPPER =
		      new PairFunction<String, String, Integer>() {
		        @Override
		        public Tuple2<String, Integer> call(String s) throws Exception {
		        	//logger("================"+s);
		          return new Tuple2<String, Integer>(s, 1);
		        }
		      };

		  private static final Function2<Integer, Integer, Integer> WORDS_REDUCER =
		      new Function2<Integer, Integer, Integer>() {
		        @Override
		        public Integer call(Integer a, Integer b) throws Exception {
		        	System.out.println("###############"+(a+b));
		          return a + b;
		        }
		      };
	  private static Logger logger = LoggerFactory.getLogger(TestController.class);
	 
	  private static List<File> getFiles(String fileName) {
		    File file=new File(fileName);
		    return Lists.newArrayList(file.listFiles(new FilenameFilter() {
				
				@Override
				public boolean accept(File dir, String name) {
					if(name.endsWith(".jpg")||name.endsWith(".png")) return true;
					return false;
				}
			}));
	  }
	  
	  
	  @RequestMapping(value="/test",method=RequestMethod.GET)
	  @ResponseBody
	  public Json test(HttpServletRequest request,HttpServletResponse response){
		 
		SparkIgniteService service=ServiceGenerator.createIgniteService(ignite,"sparkIgniteServiceNode",SparkIgniteService.class, false);
		JavaSparkContext context=service.getSparkContext();
		JavaRDD<String> file = context.textFile("C:/iris_training.txt");
	    JavaRDD<String> words = file.flatMap(WORDS_EXTRACTOR);
	    JavaPairRDD<String, Integer> pairs = words.mapToPair(WORDS_MAPPER);
	    JavaPairRDD<String, Integer> counter = pairs.reduceByKey(WORDS_REDUCER);

	    counter.repartition(1).saveAsTextFile("C:/baidu/"+UUID.randomUUID().toString()+".txt");
		
		Json json=new Json();
		json.setKey("it is ok");
		return json;
	  }

   上面只是一个测试的例子,其实就是map reducer 进行统计countSpringMVC 与 spark 整合教程_第1张图片

    下面我们启动运行结果

     SpringMVC 与 spark 整合教程_第2张图片

   下面执行 http://localhost:8080/spark-webdeeptest/image/test 是否会执行spark计算 同时把结果保存到c:/baidu/下面的txt文件里面

   SpringMVC 与 spark 整合教程_第3张图片      

SpringMVC 与 spark 整合教程_第4张图片

 因为spring 容器管理spark 的context 所以 下次会比较快。

再次执行以下 

SpringMVC 与 spark 整合教程_第5张图片

你可能感兴趣的:(apache,spark,spark,springMVC,springMVC,ignite)