Flink 动态加载 Jar 包,实现自定义算子加载执行

Flink 动态加载 Jar 包,实现自定义算子加载执行

动态加载Jar

对应的参数:

  • path:Jar 的存放路径。
  • env:Flink 的环境实例。
  • classPath:动态Jar的类路径。
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.flink.configuration.Configuration;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import com.ygsoft.dataprocess.exception.LoadFunctionException;

/**
 * 动态加载jar
 * @author yinlilan
 *
 */
public class LoadFunction {

	public static Class<?> loadJar(final String path, final StreamExecutionEnvironment env, final String classPath) throws LoadFunctionException {
		
		final String newPath = "file:///" + path;
		
		try {
			loadJar(new URL(newPath));

			Field configuration = StreamExecutionEnvironment.class.getDeclaredField("configuration");
			configuration.setAccessible(true);
			Configuration o = (Configuration) configuration.get(env);

			Field confData = Configuration.class.getDeclaredField("confData");
			confData.setAccessible(true);
			
			@SuppressWarnings("unchecked")
			Map<String, Object> temp = (Map<String, Object>) confData.get(o);
			List<String> jarList = new ArrayList<>();
			jarList.add(newPath);
			temp.put("pipeline.classpaths", jarList);
			
			Class<?> result = Class.forName(classPath);
			
			return result;
		} catch(Exception e) {
			throw new LoadFunctionException("加载动态jar包异常");
		}
	}

	// 动态加载Jar
	private static void loadJar(final URL jarUrl) {
		// 从URLClassLoader类加载器中获取类的addURL方法
		Method method = null;
		try {
			method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
		} catch (NoSuchMethodException | SecurityException e1) {
			e1.printStackTrace();
		}
		// 获取方法的访问权限
		boolean accessible = method.isAccessible();
		try {
			// 修改访问权限为可写
			if (accessible == false) {
				method.setAccessible(true);
			}
			// 获取系统类加载器
			URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
			// jar路径加入到系统url路径里
			method.invoke(classLoader, jarUrl);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			method.setAccessible(accessible);
		}
	}
}

动态Jar调用方式

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import com.ygsoft.dataprocess.exception.LoadFunctionException;
import com.ygsoft.dataprocess.load.LoadFunction;
import com.ygsoft.dataprocess.sdk.domain.NodeParam;
import com.ygsoft.dataprocess.sdk.flow.IFlow;
import com.ygsoft.dataprocess.vo.flow.CustomCondition;

/**
 * 自定义算子实现
 * @author yinlilan
 *
 */
public class CustomConditionFlow implements IFlow {

	private StreamExecutionEnvironment env;
	
	public CustomConditionFlow(StreamExecutionEnvironment env) {
		this.env = env;
	}
	
	@Override
	public DataStream<Map<String, String>> execute(final DataStream<Map<String, String>> input, final NodeParam param) {
		final Object nodeParams = param.getParams();
		final CustomCondition condition = new CustomCondition(nodeParams);
		
		final String jarPath = condition.getJarPath();
		final String classPath = condition.getClassPath();
		final String methodName = condition.getMethod();
		
		try {
			Class<?> c = LoadFunction.loadJar(jarPath, env, classPath);
			
			Object obj = c.newInstance();
			
			// 获取方法对象
			Method method = obj.getClass().getMethod(methodName, DataStream.class, param.getClass());
			
			// 执行方法
			@SuppressWarnings("unchecked")
			DataStream<Map<String, String>> result = (DataStream<Map<String, String>>) method.invoke(obj, input, param);
			
			return result;
		} catch (LoadFunctionException e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} catch (InstantiationException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (SecurityException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Flink支持动态加载Jar包,可以在运行时动态添加、移除Jar包,以便于实时更新应用程序。下面是一个简单的示例: 1. 创建一个Flink应用程序,例如WordCount,打Jar包。 2. 在Flink集群中启动一个JobManager和一个或多个TaskManager。 3. 使用Flink提供的命令行工具flink run启动WordCount应用程序,例如: ``` flink run -c com.example.WordCount /path/to/wordcount.jar ``` 4. 在运行WordCount应用程序时,可以使用Flink提供的REST API或Web界面动态添加或移除Jar包。例如,可以使用以下REST API请求动态添加Jar包: ``` POST /jars/upload Content-Type: multipart/form-data Upload-Jar: true <file upload> ``` 注意,需要将Upload-Jar头设置为true,以便告诉Flink上传的文件是Jar包。 5. 添加Jar包后,可以使用Flink提供的REST API或Web界面启动新的作业,并使用新添加的Jar包。例如,可以使用以下REST API请求启动新的作业: ``` POST /jobs Content-Type: application/json { "jarPath": "/jars/myjar.jar", "className": "com.example.MyJob", "args": ["arg1", "arg2"] } ``` 这将启动一个新的作业,使用新添加的Jar包,并调用MyJob类的main方法,传递arg1和arg2参数。 注意,需要将jarPath设置为新添加的Jar包的路径,而不是原始的WordCount应用程序的路径。 6. 移除Jar包时,可以使用Flink提供的REST API或Web界面删除Jar包。例如,可以使用以下REST API请求删除Jar包: ``` DELETE /jars/myjar.jar ``` 这将删除名为myjar.jarJar包,如果有作业正在使用该Jar包,则会在作业完成后删除Jar包。 总之,Flink动态Jar包加载功能非常强大,可以帮助用户实现实时更新应用程序的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值