Flink加载自定义Jar包

本文介绍了如何在Flink中使用FlinkSQ构建实时计算任务时动态加载自定义UDF,通过pipeline.classpaths配置和URLClassLoader加载Jar包,以及如何在HDFS高可用场景下获取active节点的HTTP路径。期待Flink未来提供更便捷的RESTAPI接口来管理用户自定义Jar包。
背景

用户只需要编写Fink SQ就可以快速构建实时计算任务,通过yarn session模式试运行或者语法校验需要自定义udf,其中用户可以通过上传Jar包的方式支持自定义函数UDF,这里就需要在启动作业的时候能够动态加载自定义Jar包。

解决

Flink 官方文档可以招待找到关于 pipeline.classpath 参数配置的描述,通过该配置项来加载classpath。yarn的api并没有提供该配置项目的参数入口,所以在作业的 main 函数中直接通过反射获取 Configuration 对象,并且直接设置 pipeline.classpaths 的值。

private static void loadPipelineClassPaths(StreamExecutionEnvironment env, List<String> jarList) throws Exception{
        Field configuration = StreamExecutionEnvironment.class.getDeclaredField("configuration");
        configuration.setAccessible(true);
        Configuration o = (Configuration)configuration.get(env);
 
        Field confData = Configuration.class.getDeclaredField("confData");
        confData.setAccessible(true);
        Map<String,Object> temp = (Map<String,Object>)confData.get(o);
        temp.put("pipeline.classpaths", jarList);
 }

同时还需要在作业的 main 方法里动态加载Jar包到 URLClassloader里:

public static void loadJar(URL jarUrl) {
        //从URLClassLoader类加载器中获取类的addURL方法
        Method method = null;
        try {
            method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
        } catch (NoSuchMethodException | SecurityException e1) {
            e1.printStackTrace();
        }
        assert method != null;
        boolean accessible = method.isAccessible();
        try {
            if (!accessible) {
                method.setAccessible(true);
            }
            URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
            method.invoke(classLoader, jarUrl);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            method.setAccessible(accessible);
        }
  }

-C参数使用的类加载进行加载与user jar是一个类加载器,taskManager运行的时候会加载并且相应的job停止时自动卸载,同时每个job都会有自己的ClassLoader实现相互隔离。希望Flink 后续版能够在Rest API 层面能够直接提供参数来加载用户自定义的Jar包,并且能够直接读取HDFS文件来加载Jar包。

暂时将用户自定义的Jar包上传到hdfs并获取到hdfs的http连接地址,形式如下:
http://hadoop1:50070/webhdfs/v1/test.jar?op=OPEN&namenoderpcaddress=nnCluster&offset=0
对hdfs高可用场景,可以通过如下方式获取到active节点连接地址:

public static String getActiveHttpPath(Hdfs hdfsCon) throws IOException {
        HdfsFileSystem hdfsFileSystem = SpringUtils.getBean(HdfsFileSystem.class);
        InetSocketAddress active = HAUtil.getAddressOfActive(hdfsFileSystem.getHdfs(hdfsCon));
        String httpPath = "http://" + active.getAddress().getHostAddress() + ":50075/webhdfs/v1";
        return httpPath;
 }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风卷残尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值