文档章节

JPPF与Spring集成实现AOP的完整示例

李玉珏
 李玉珏
发布于 2016/02/01 19:56
字数 1639
阅读 511
收藏 7

1.概述

JPPF是一个开放源码的网格计算框架,它可以在一个分布执行环境中 同时运行多个java应用。他历史比较悠久,社区也比较活跃,最新的版本已经更新到5.1.1版本,但是资料较少。 在如今Hadoop以及以Hadoop作为基础设施的各种平台的大红大紫环境下,这个平台的关注度更是不高,但是作为一个备选的解决方案和开发平台,还是有必要展示一下,供做技术选型的人参考。 本文目的有两个:一是用一个简单的例子展示一下JPPF的用法,二是演示了如何与Spring集成实现AOP的方法,仅供参考。

2.环境搭建

JPPF的整个运行环境,需要客户端,服务器(Driver)以及执行具体任务的各个节点,最简单的部署架构如下:

作为一个最简单的运行环境,分别解压从sourceforge上下载的JPPF-5.1.1-admin-ui.zip,JPPF-5.1.1-driver.zip,JPPF-5.1.1-node.zip,无需额外的配置,通过相应的启动脚本分别启动一个driver节点,一个admin-ui节点以及二个node节点,如果看到了节点初始化成功的提示信息,则表示各个节点启动成功。

3.相关代码

官方发布有一个简单的应用模板,JPPF-5.1.1-application-template.zip,这个代码非常简单,如果上述环境启动成功,直接就可以运行,但是需要配置ANT,本文的重点是Spring的集成,所以下面会贴出所有的代码,供大家参考。 与Spring的集成,我们往往需要他的两个很重要的功能特性,一个是组件的组装,这样可以使整个架构设计变的优雅,另一个就是AOP编程,通过注册拦截器,可以实现关注点的分离。这里面需要注意的就是,JPPF在部署上,是使用的分布式类加载器,这是和传统Spring应用最大的一个不同,Spring的AOP实现,最终会利用一些字节码增强技术,这是分布式类加载器不支持的,因此我们无法在任务部署到各个node节点之前就生成AOP代理对象,只能在运行时利用ProxyFactory动态生成,下面是详细的代码:

3.1.程序的入口JPPFExample

package demo;
import java.util.ArrayList;
import java.util.List;

import org.jppf.client.JPPFClient;
import org.jppf.client.JPPFConnectionPool;
import org.jppf.client.JPPFJob;
import org.jppf.client.Operator;
import org.jppf.node.protocol.DataProvider;
import org.jppf.node.protocol.MemoryMapDataProvider;
import org.jppf.node.protocol.Task;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class JPPFExample {
	public static void main(String[] args) {
		try (JPPFClient jppfClient = new JPPFClient()) {
			JPPFExample runner = new JPPFExample();
			runner.executeMultipleConcurrentJobs(jppfClient, 4);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public JPPFJob createJob(final String jobName) throws Exception {
		ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
		JPPFJob job = new JPPFJob();
		job.setName(jobName);

		Task<?> task = job.add(ac.getBean("jppfTask"));
		task.setId(jobName + " - 任务");
		return job;
	}

	public void executeMultipleConcurrentJobs(final JPPFClient jppfClient, final int numberOfJobs) throws Exception {
		ensureNumberOfConnections(jppfClient, numberOfJobs);
		final List<JPPFJob> jobList = new ArrayList<>(numberOfJobs);
		for (int i = 1; i <= numberOfJobs; i++) {
			String jobName = "非阻塞作业: " + i;
			JPPFJob job = createJob(jobName);
            //DataProvider是JPPF提供的数据共享机制
			DataProvider dataProvider = new MemoryMapDataProvider();
			dataProvider.setParameter("jobName", jobName);
			job.setDataProvider(dataProvider);
            //非阻塞
			job.setBlocking(false);
            //提交作业
			jppfClient.submitJob(job);
			jobList.add(job);
		}
		System.out.println("作业执行中 ...");
		for (JPPFJob job : jobList) {
			List<Task<?>> results = job.awaitResults();
			processExecutionResults(job.getName(), results);
		}
	}

	public synchronized void processExecutionResults(final String jobName, final List<Task<?>> results) {
		System.out.printf("作业的结果 '%s' :\n", jobName);
		for (Task<?> task : results) {
			String taskName = task.getId();
			if (task.getThrowable() != null) {
				System.out.println(taskName + ", 抛出了异常: " + task.getThrowable().getMessage());
			} else {
				System.out.println(taskName + ", 执行结果: " + task.getResult());
			}
		}
	}

	public void ensureNumberOfConnections(final JPPFClient jppfClient, final int numberOfConnections) throws Exception {
		JPPFConnectionPool pool = jppfClient.awaitActiveConnectionPool();
		if (pool.getConnections().size() != numberOfConnections) {
			pool.setSize(numberOfConnections);
		}
		pool.awaitActiveConnections(Operator.AT_LEAST, numberOfConnections);
	}
}

通过上述代码,我们创建了四个非阻塞的任务,并行地发送给node节点去执行。

3.2.在node节点上执行的任务

package demo;

import org.jppf.node.protocol.AbstractTask;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.annotation.Autowired;

public class JPPFTask extends AbstractTask<String>{
	
	@Autowired
	private JPPFService jppfService;
	
	@Autowired
	private JPPFServiceInterceptor jppfServiceInterceptor;

	@Override
	public void run() {
		System.out.println("这是执行任务的节点!");
        //这个是关健,通过下面的代码动态地为service添加拦截器
		ProxyFactory pf = new ProxyFactory(jppfService);
		pf.setProxyTargetClass(true);
		pf.addAdvice(jppfServiceInterceptor);
		JPPFService service = (JPPFService)pf.getProxy();
		String jobName = this.getDataProvider().getParameter("jobName");
	    try {
			setResult(service.execute(jobName));
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

3.3.拦截器

这个没啥特别的:

package demo;

import java.io.Serializable;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

//要实现Serializable接口,否则无法序列化
public class JPPFServiceInterceptor implements MethodInterceptor,Serializable {

	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		System.out.println("拦截器执行开始:");
		Object obj = mi.proceed();
		System.out.println("拦截器执行结束:");
		return obj;
	}
}

3.4.业务Service

package demo;

import java.io.Serializable;

//要实现Serializable接口,否则无法序列化
public class JPPFService implements Serializable {
	
	public String execute(String name) throws InterruptedException{
		System.out.println("任务名称:" + name);
		Thread.currentThread().sleep(10000);
		return "任务执行成功!";
	}

}

3.5.配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
	<context:annotation-config/>
	
	<bean id="jppfTask" class="demo.JPPFTask"/>
	<bean id="jppfService" class="demo.JPPFService"/>
	<bean id="jppfServiceInterceptor" class="demo.JPPFServiceInterceptor"/>
</beans>

代码非常简单。 之后可以在eclipse中运行JPPFExample,就可以在node节点的控制台上看到运行的结果。

4.控制台

JPPF的控制台如下图所示:

这个控制台功能还是很丰富的,不只是监控,还有作业的管理和维护功能。

5.总结

JPPF还是比较成熟的,和其他的网格计算平台相比,有两个突出的优点,一是虽然各种资料较少,但是文档质量较高,二是有一个非常不错的控制台,这是其他平台所不具备的,或者是收费的。 缺点呢,一是社区虽然活跃,但是不够强大,推广上或者影响力不足;二是在部署上,在复杂的拓扑环境下配置比Ignite等采用对等架构的要复杂,整体维护管理成本要高些;三是目前看不到太多的应用案例,采用这个技术的太少了,性能,稳定性等等大家更为关心的都还未知。

© 著作权归作者所有

李玉珏

李玉珏

粉丝 387
博文 79
码字总数 149758
作品 0
沈阳
架构师
私信 提问
IOC/AOP工具 - jBeanBox

jBeanBox是一个微形但功能较齐全的IOC/AOP工具适用于JAVA7+,利用了Java的初始化块实现的Java配置代替XML。jBeanBox采用Apache License 2.0开源协议。 其他一些IOC/AOP框架的问题: 1)Sprin...

yong9981
2016/07/25
3.3K
15
这15个经典的Spring面试常见问题你都了解吗?来看看吧

点关注,不迷路;持续更新Java架构相关技术及资讯热文!!! 这篇文章主要是想通过一些问题,加深大家对于 Spring 的理解,所以不会涉及太多的代码!这篇文章整理了挺长时间,下面的很多问题...

Java_苏先生
06/05
0
0
2014-03-09 Spring的学习(0)-----Spring目录文件组织

Spring压缩包目录说明 目录名 相关介绍 aspectj 在Spring框架下使用aspectj的源代码和测试程序文, 是java最早的提供AOP的应用框架 dist Spring 的发布包,关于发布包下面会详细进行说明。 do...

查封炉台
2014/03/09
151
0
Spring中基于AOP的XML架构

以下内容引用自http://wiki.jikexueyuan.com/project/spring/aop-with-spring-framenwork/xml-schema-based-aop-with-spring.html: 为了使用aop命名空间标签,需要导入spring-aop架构,如下......

easonjim
2017/05/25
0
0
Java程序员从笨鸟到菜鸟之(六十七)细谈Spring(一)spring简介

Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。 然而...

长平狐
2012/11/12
153
0

没有更多内容

加载失败,请刷新页面

加载更多

springboot初探---spring-boot-starter-web究竟干了啥

上一篇已经简单介绍了启动类的部分,这一篇主要讨论一下springboot引入的哪些依赖 我们都知道想用springboot做一个web应用,首先要做的是引入相关依赖,两步操作: 1、添加spring-boot-start...

计算机狼
57分钟前
6
0
基于Rocket.chat搭建内网聊天系统(使用docker,本机不需要安装meteor)

您可能不希望使用标准的Docker命令,而是希望对部署进行更多的自动化管理。这就是使用Docker-compose可能会派上用场的地方。 确保您已安装Docker和Docker-compose并且可以正常运行。 docker...

吴伟祥
59分钟前
8
0
conda 更新源

更新conda 源为阿里源 conda config --add channels http://mirrors.aliyun.com/pypi/simple conda config --set show_channel_urls yes 阿里云: http://mirrors.aliyun.com/pypi/simple/ 豆......

Mr_Tea伯奕
59分钟前
5
0
java 泛型使用

每次写泛型方法都翻下百度,还是自己记录下把。 1、定义一个泛型方法,使用传入参数类型来传递泛型。这种用法在封装json序列化工具类应该会用到。 List<xxx> aa = getList(xxx.class);pr...

朝如青丝暮成雪
今天
7
0
深入了解Java模板引擎Freemarker

前言 常用的Java模板引擎包括:JSP、Freemarker、Thymeleaf、Velocity,从Github上查阅到这几款主流的模板引擎的性能的对比,总体上看,JSP、Freemarker、Thymeleaf、Velocity在性能上差别不...

code-ortaerc
今天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部