flink集成springboot案例_Spring Boot整合Flink

本文介绍了如何在非Web项目中将Spring Boot 2.1.6与Flink 1.6.1集成,通过实现CommandLineRunner接口创建流处理逻辑,并在Flink的Sink中利用Spring容器中的类。详细讲解了遇到的Gson库版本冲突和日志冲突问题的解决方法,以及在YARN上提交Flink作业时指定classpath的注意事项。
摘要由CSDN通过智能技术生成

软件版本:Spring Boot 2.1.6+Flink1.6.1+JDK1.8

程序主体:

@SpringBootApplication

public class HadesTmsApplication implements CommandLineRunner {

public static void main(String[] args) {

SpringApplication application = new SpringApplication(HadesTmsApplication.class);

application.setBannerMode(Banner.Mode.OFF);

application.run(args);

}

@Override

public void run(String... args) {

StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

FlinkKafkaConsumer010 kafkaConsumer = new FlinkKafkaConsumer010<>("topic-name"), new SimpleStringSchema(), getProperties());

DataStream dataStream = env.addSource(kafkaConsumer);

// 此处省略处理逻辑

dataStream.addSink(new MySink());

}

private Properties getProperties() {

Properties properties = new Properties();

properties.setProperty("bootstrap.servers", bootstrap_servers);

properties.setProperty("zookeeper.connect", zookeeper_connect);

properties.setProperty("group.id", group_id);

properties.setProperty("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");

properties.setProperty("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

return properties;

}

}

说明一下:因为是非web项目,所以实现CommandLineRunner接口,重写run方法。在里面编写流处理逻辑。

如果在MySink中需要使用spring容器中的类,而MySink是一个普通的类,那么是无法访问到的。会引发空指针异常。可能有人想到了ApplicationContextAware这个接口,实现这个接口获取ApplicationContext,也即是:

@Component

public class ApplicationContextUtil implements ApplicationContextAware, Serializable {

private static final long serialVersionUID = -6454872090519042646L;

private static ApplicationContext applicationContext = null;

@Override

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

if (ApplicationContextUtil.applicationContext == null) {

ApplicationContextUtil.applicationContext = applicationContext;

}

}

public static ApplicationContext getApplicationContext() {

return applicationContext;

}

//通过name获取 Bean.

public static Object getBean(String name) {

return getApplicationContext().getBean(name);

}

//通过class获取Bean.

public static T getBean(Class clazz) {

return getApplicationContext().getBean(clazz);

}

//通过name,以及Clazz返回指定的Bean

public static T getBean(String name, Class clazz) {

return getApplicationContext().getBean(name, clazz);

}

}

这种做法实际上在flink流处理中也是不可行的,在我之前的flink文章中 Flink读写系列之-读mysql并写入mysql 其中读和写阶段有一个open方法,这个方法专门用于进行初始化的,那么我们可以在这里进行spring bean的初始化。那么MySink改造后即为:

@EnableAutoConfiguration

@MapperScan(basePackages = {"com.xxx.bigdata.xxx.mapper"})

public class SimpleSink extends RichSinkFunction {

TeacherInfoMapper teacherInfoMapper;

@Override

public void open(Configuration parameters) throws Exception {

super.open(parameters);

SpringApplication application = new SpringApplication(SimpleSink.class);

application.setBannerMode(Banner.Mode.OFF);

ApplicationContext context = application.run(new String[]{});

teacherInfoMapper = context.getBean(TeacherInfoMapper.class);

}

@Override

public void close() throws Exception {

super.close();

}

@Override

public void invoke(String value, Context context) throws Exception {

List teacherInfoList = teacherInfoMapper.selectByPage(0, 100);

teacherInfoList.stream().forEach(teacherInfo -> System.out.println("teacherinfo:" + teacherInfo.getTeacherId() + "," + teacherInfo.getTimeBit() + "," + teacherInfo.getWeek()));

}

}

在invoke中就可以访问spring容器中的Mapper方法了。

pom如下:

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

4.0.0

org.springframework.boot

spring-boot-starter-parent

2.1.6.RELEASE

com.xxx.bigdata

flink-project

1.0.0

flink-project

jar

My project for Spring Boot

UTF-8

UTF-8

1.8

1.6.1

true

1.8

1.8

org.springframework.boot

spring-boot-starter

ch.qos.logback

logback-classic

org.apache.flink

flink-java

${flink.version}

org.apache.flink

flink-streaming-java_2.11

${flink.version}

org.apache.flink

flink-connector-kafka-0.10_2.11

${flink.version}

com.cloudera

ImpalaJDBC41

2.6.4

com.zaxxer

HikariCP

3.2.0

org.mybatis.spring.boot

mybatis-spring-boot-starter

1.3.1

com.alibaba

fastjson

1.2.47

org.projectlombok

lombok

true

org.springframework.boot

spring-boot-starter-test

test

src/main/java

src/main/resources

true

application.properties

application-${package.environment}.properties

org.springframework.boot

spring-boot-maven-plugin

true

com.xxx.bigdata.xxx.Application

repackage

org.mybatis.generator

mybatis-generator-maven-plugin

1.3.5

${basedir}/src/main/resources/generatorConfig.xml

true

true

com.cloudera

ImpalaJDBC41

2.6.4

dev

dev

true

pre

pre

pro

pro

项目打包使用了默认的spring boot插件,配置了skip为true,如果不配置此项,打包后会多一个BOOT-INF目录,运行时会引起ClassNotFoundException等各种异常,比如KafkaStreming问题,甚至需要反转flink的类加载机制,由child-first变为parent-first(修改flink配置文件)等等。

遇到的问题:

1. java.lang.NoSuchMethodError: com.google.gson.GsonBuilder.setLenient()Lcom/google/gson/GsonBuilder

GsonBuilder类来自gson-xxx.jar包,而我在自己的项目中执行mvn dependency:tree并没有发现依赖这个包。莫非在flink运行时会使用自己lib库下的gson包,转而去flink的lib库下,发现flink-dist_2.11-1.6.1.jar里包含了gson-xxx包,但是打开这个包一看类中没有setLenient方法,于是在服务器上建立一个commlib,把gson-2.8.0.jar(包含setLenient方法)放进去,然后使用flink run提交时,指定classpath即可。

2.日志冲突

Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.Log4jLoggerFactory loaded from file:/opt/flink-1.6.1/lib/slf4j-log4j12-1.7.7.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.impl.Log4jLoggerFactory

排除springboot中的日志即可:

org.springframework.boot

spring-boot-starter

ch.qos.logback

logback-classic

3.flink run提交作业到yarn上时,如果需要指定classpath,则需要指定到确定的jar包,指定目录不可行。那么假如所有依赖包已经放置在目录中,拼接的shell可以这么写:

lib_classpath="";

for jar in `ls /home/hadoop/lib`

do

jar_suffix=${jar##*.}

if [ "$jar_suffix" = "jar" ]

then

jar_path=" --classpath file:///home/hadoop/lib/$jar "

lib_classpath=${lib_classpath}${jar_path}

else(http://www.my516.com)

echo "the jar file $jar it not legal jar file,skip appendig"

fi

done

拼接后的lib_classpath值如下效果:

--classpath file:///home/hadoop/lib/accessors-smart-1.2.jar --classpath file:///home/hadoop/lib/akka-actor_2.11-2.4.20.jar

---------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBootFlink是两个不同的框架,它们可以进行集成。在集成过程中,可能会遇到一些问题。根据引用内容,我可以给出以下回答: 1. 打包问题:在集成过程中,可能会遇到部署打包的问题。根据引用\[1\],可以使用不同的插件进行打包,例如使用SpringBoot的插件进行SpringBoot项目的打包,使用Flink的插件进行FlinkTask的打包。打包时需要注意META-INF下的MANIFEST.MF文件的内容,因为SpringBoot项目和FlinkTask的jar文件的MANIFEST.MF文件内容可能有区别。 2. 序列化问题:在集成过程中,可能会遇到序列化问题。根据引用\[3\],可以通过使用maven父子项目来解决这个问题。主项目依赖全用Flink相关的配置,子项目使用SpringBoot来快速开发并提供主项目数据。这种方式可以解决一些序列化问题。 总结起来,集成SpringBootFlink需要注意打包和序列化问题。可以根据具体情况选择合适的打包方式,并使用maven父子项目来解决序列化问题。 #### 引用[.reference_title] - *1* *2* [SpringBoot集成Flink部署与打包](https://blog.csdn.net/zwrlj527/article/details/124750228)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [springboot整合flink(三)](https://blog.csdn.net/paulwang040/article/details/127702032)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值