Flink的执行模式有以下三种:

前提是我们已经开启了yarnsession的进程,在下图中可以看到启动的id也就是后续任务需要通过此id进行认证,以及任务分配的master主机。

这里启动时候会报错一个ERROR:org.apache.flink.shaded.curator.org.apache.curator.ConnectionState  - Authentication failed

查阅资料得知:

该错误是因为,kerberos认证失败,cdh6,并没有启动kerberos。所以该错误可以忽略。但是如果已经开启动了kerberos,这个问题就要解决了。

我们这里没有开启Kerberos,所以这个报错我么可以不管。

Session Mode:会话模式

会话模式需要先启动一个集群,保持一个会话,在这个会话中通过客户端提交作业。集群启动时所有资源就都已经确定,所有提交的作业会竞争集群中的资源。适合任务规模小,执行时间短的大量作业。

Flink的作业执行环境会一直保留在集群上,直到会话被显式终止。这样,可以提交多个作业,它们可以共享相同的集群资源和状态,从而实现更高的效率和资源利用。

bin/flink run -yid application_1723708102500_0009  examples/batch/WordCount.jar

重要的是要添加 -yid 这个参数,不添加这个参数会执行不成功,会报错找不到执任务的cluster。

脚本执行参数:

-n(--container):TaskManager的数量。(1.10 已经废弃)

-s(--slots):每个TaskManager的slot数量,默认一个slot一个core,默认每个taskmanager的slot的个数为1,有时可以多一些taskmanager,做冗余。

-jm:JobManager的内存(单位MB)。

-q:显示可用的YARN资源(内存,内核);

-tm:每个TaskManager容器的内存(默认值:MB)

-nm:yarn 的appName(现在yarn的ui上的名字)。  

-d:后台执行。

提交flink任务:

bin/flink run examples/batch/WordCount.jar

Per-Job Mode:单作业模式,我们也是更多的使用这种模式,这个模式会将我们的资源更合理的规划使用。

每个Flink应用程序作为一个独立的作业被提交和执行。

每次提交的Flink应用程序都会创建一个独立的作业执行环境,该作业执行环境仅用于执行该特定的作业。

作业完成后,作业执行环境会被释放,集群关闭,资源释放

bin/flink run -m yarn-cluster ./examples/batch/WordCount.jar

常用参数:

--p 程序默认并行度

下面的参数仅可用于 -m yarn-cluster 模式

--yjm JobManager可用内存,单位兆

--ynm YARN程序的名称

--yq 查询YARN可用的资源

--yqu 指定YARN队列是哪一个

--ys 每个TM会有多少个Slot

--ytm 每个TM所在的Container可申请多少内存,单位兆

--yD 动态指定Flink参数

-yd 分离模式(后台运行,不指定-yd, 终端会卡在提交的页面上)

Application Mode:应用模式

应用模式算是前2种模式的升级,前2种模式中,Flink程序代码是在客户端执行,然后客户端提交给JobManager,客户端需要占用大量网络带宽。

应用模式需要为每一个提交的应用单独启动一个JobManager(应用程序在JobManager执行),也就是创建一个集群。这个JobManager只为执行这一个应用而存在,执行结束之后JobManager关闭。

application 模式使用 bin/flink run-application 提交作业;通过 -t 指定部署环境,目前 application 模式支持部署在 yarn 上(-t yarn-application) 和 k8s 上(-t kubernetes-application);并支持通过 -D 参数指定通用的 运行配置,比如 jobmanager/taskmanager 内存、checkpoint 时间间隔等。

带有 JM 和 TM 内存设置的命令提交,这种方式提交之后会带对应服务器的HDFS的WebUI页面多出一个wordcount_01的文件,该文件记录了程序运行的结果

./bin/flink run-application -t yarn-application \

-Djobmanager.memory.process.size=1024m \

-Dtaskmanager.memory.process.size=1024m \

-Dyarn.application.name="MyFlinkWordCount" \

./examples/batch/WordCount.jar --output hdfs://ddp54:8020/wordcount_01

在上面例子 的基础上自己设置 TaskManager slots 个数为3,以及指定并发数为3:

./bin/flink run-application -t yarn-application -p 3 \

-Djobmanager.memory.process.size=1024m \

-Dtaskmanager.memory.process.size=1024m \

-Dyarn.application.name="MyFlinkWordCount" \

-Dtaskmanager.numberOfTaskSlots=3 \

./examples/batch/WordCount.jar --output hdfs://node1:8020/wordcount/output_52

指定并发还可以使用 -Dparallelism.default=3,而且社区目前倾向使用 -D+通用配置代替客户端命令参数(比如 -p)。所以这样写更符合规范:

./bin/flink run-application -t yarn-application \

-Dparallelism.default=3 \

-Djobmanager.memory.process.size=1024m \

-Dtaskmanager.memory.process.size=1024m \

-Dyarn.application.name="MyFlinkWordCount" \

-Dtaskmanager.numberOfTaskSlots=3 \

./examples/batch/WordCount.jar --output hdfs://node1:8020/wordcount/output_53

以上三种模式就先简述这些,其实还有很多参数没有用到,我们更多的只需要用到第二种pre-job的模式即可。

Yarn-session模式开启成功后,我们进入SQL-Client界面,在这个界面我们可以写SQL来实现系统之间的交互,我接下来以MySQL与Kafka的交互为例:

首先是要在MySQL数据库创建一些库和表当作source数据源:

CREATE TABLE src_mysql_order(
 order_id BIGINT,
 store_id BIGINT,
 sales_amt double,
 PRIMARY KEY (`order_id`)
);

CREATE TABLE src_mysql_order_detail(
 order_id BIGINT,
 store_id BIGINT,
 goods_id BIGINT,
 sales_amt double,
 PRIMARY KEY (order_id,store_id,goods_id)
);

CREATE TABLE dim_store(
 store_id BIGINT,
 store_name varchar(100),
 PRIMARY KEY (`store_id`)
);

CREATE TABLE dim_goods(
 goods_id BIGINT,
 goods_name varchar(100),
 PRIMARY KEY (`goods_id`)
);

CREATE TABLE dwa_mysql_order_analysis (
   store_id BIGINT,
   store_name varchar(100),
   sales_goods_distinct_nums bigint,
   sales_amt double,
   order_nums bigint,
   PRIMARY KEY (store_id,store_name)
);

Source:在MySQL中创建完成之后我们要在SQL client界面进行映射在这里以src_mysql_order表为例,执行成功如以下界面:

CREATE TABLE src_mysql_order(

 order_id BIGINT,

 store_id BIGINT,

 sales_amt double,

 PRIMARY KEY (`order_id`) NOT ENFORCED

) WITH (

 'connector' = 'mysql-cdc',

 'hostname' = 'xxx',

 'port' = '3306',

 'username' = 'xxx',

 'password' = 'xxx',

 'database-name' = 'xxx',

 'table-name' = 'xxx',

 'scan.incremental.snapshot.enabled' = 'false'

);

Sink:对MySQL做完source映射之后,我们要将MySQL的数据导入到Kafka,因此我们也要做一些Kafka表的映射,执行成功界面如下:

CREATE TABLE ods_kafka_order (

 order_id BIGINT,

 store_id BIGINT,

 sales_amt double,

 PRIMARY KEY (`order_id`) NOT ENFORCED

) WITH (

 'connector' = 'upsert-kafka',

 'topic' = 'Kafka主题',

 'properties.bootstrap.servers' = 'Kafka集群的IP+端口号',

  'key.format' = 'json',

 'value.format' = 'json'

);

两张表都映射完成之后,我们先在MySQL添加一些测试用例:

insert into src_mysql_order values

(20221210001,10000,50),

(20221210002,10000,20),

(20221210003,10001,10);

接下来就将MySQL与Kafka实现交互,即将MySQL数据插入到Kafka作业中:

insert into ods_kafka_order_2 select * from src_mysql_order;

在这个过程中,有可能会报错:

这个报错是找不到表的元数据信息,我这里是将表名写错了,这个是比较庆幸的,但是还有一种原因就是:没有MySQLCDC或者Kafka的依赖,导致连接的元数据信息无法保存到catalog中,因此我们就需要添加MySQLCDC和Kafka的连接依赖:

进入到Flink安装路径的lib目录下:使用 rz 指令将依赖jar包上传,上传完毕之后使用 scp 指令远程复制给集群的其它机器,我们的是ddp54、ddp55:

scp -r lib/flink-sql-connector-kafka-1.16.2.jar  root@ddp54:$PWD/lib

scp -r lib/flink-sql-connector-kafka-1.16.2.jar  root@ddp55:$PWD/lib

Jar包上传完之后,我们在基础平台将Flink集群重启

集群重启之后,我们重新开启一个yarnsession进程来执行后续提交的任务。

进入yarn的web页面来查看进程启动的状况。

接下来我们重走一遍MySQL的source和Kafka的sink流程,走完之后进入SQL client界面执行交互指令,即MySQL数据插入到Kafka,执行完成之后没有报错,但是查看flink的web页面发现并没有作业在执行或执行完成,于是查看日志得知:问题是MySQL的系统时间跟所在地区时间不匹配导致的,我们可以在命令行进行时区的设置,也可以在配置文件中进行时区的设置,我选择了在my.cnf配置文件中进行时区的更改:在[mysqld]下添加默认时区设置即可,与此同时,MySQL也要开启binlog日志,可以保障数据一致性,主要用于复制和数据恢复。配置完成之后重启MySQL服务。

开启binlog日志

# 服务ID
server-id=1
# binlog 配置 只要配置了log_bin地址 就会开启
log_bin = /var/lib/mysql/mysql_bin
# 日志存储天数 默认0 永久保存
# 如果数据库会定期归档,建议设置一个存储时间不需要一直存储binlog日志,理论上只需要存储归档之后的日志
expire_logs_days = 30
# binlog最大值
max_binlog_size = 1024M
# 规定binlog的格式,binlog有三种格式statement、row、mixad,默认使用statement,建议使用row格式
binlog_format = ROW
# 在提交n次事务后,进行binlog的落盘,0为不进行强行的刷新操作,而是由文件系统控制刷新日志文件,如果是在线交易和账有>关的数据建议设置成1,如果是其他数据可以保持为0即可
sync_binlog = 1

 查看日志得知是MySQL的时区问题导致任务提交不成功

在 my.cnf 对时区和binlog日志进行修改

上边的MySQL配置完成之后,需要重启MySQL服务

docker restart mysql

接下来在SQL client界面再次执行指令:

insert into ods_kafka_order select * from src_mysql_order;

打开Flink的web界面,发现Flink的作业任务正在执行:

我们在SQL client界面查询MySQL的数据表信息:

SET sql-client.execution.result-mode=tableau; 

select * from src_mysql_order;

可以查看插入到MySQL的数据信息和数据的更新信息[Flink中 +I 代表插入数据 ; +U 代表更新数据 ; -U代表撤回数据]

与此同时,我们去Kafka查看数据是否到来,通过Kafka Tool查看到数据已经成功到Kafka。

至此我们实现了MySQL到Kafka的实时数据的接入以及在这个过程中遇到的一些问题以及解决办法。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐