flink监听kafka的数据

说明
flink是一个快速的实时处理引擎,他可以在收到数据的一瞬间就把数据给处理成我们想要的样子,是目前最高效率的实时数据处理技术,那么我们常用于手机实时数据的kafka中的数据flink可以实时接收并处理吗?
答案是肯定的,但是几个步骤
步骤
1.flink只兼容kafka2.2.X以上的版本,没有的小伙伴及时更新
2.在你的idea中导入kafka的连接依赖

 <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-kafka_2.11</artifactId>
            <version>1.10.0</version>
 </dependency>

3.在程序当中创建一个properties实例,而后.setProperty()各种各样你需要的参数
4.创建一个flink个kafka的生产者的一个连接器并传参
new FlinkKafkaConsumer(话题名称,一个简单的框架,属性)
5.而后再add.Source(连接器的名字)添加一个来源
具体代码

public class ConnectKafka {
    public static void main(String[] args)throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //new 一个实例!
        Properties properties = new Properties();

        //告诉程序我们要接收那台机器上生产的数据
        properties.setProperty("bootstrap.servers","doit01:9092,doit02:9092,doit03:9092");

        //告诉程序开启分区,已经分区名称
        properties.setProperty("group.id","qwer");

        //告诉程序我需要开启一个偏移量的记录,并且是从头开始读的
        properties.setProperty("auto.offset.reset","earliest");

        //告诉kafka你不要自动提交偏移量了,每次搜自动提交偏移量
        properties.setProperty("enable.auto.commit","false");

        //如果FlinkKafkaConsumer没有开启checkpoint功能,为了不重复读取
        //这种方式无法实现Exactly-Once(只执行一次)
        FlinkKafkaConsumer <String>flinkKafkaConsumer = new FlinkKafkaConsumer("wordcount2", new SimpleStringSchema(), properties);

        DataStreamSource<String> lines = env.addSource(flinkKafkaConsumer);

        lines.print();

        env.execute( "wordcoun");
//而后flink就可以监听kafka之中的数据了
    }
}

当然这样的程序是不健壮的,也许有个报错就会导致程序废掉,所以我们要做到Exactly-Once(执行且只执行一次),就会让我们的程序变得很健壮,不会因为一点小病小灾就会夭折!
步骤
1.开启一个检查站(巡回执行,巡回检查),存储策略和执行(伪重启)策略
env.enableCheckpointing(时间参数毫秒级的例如:30000(30秒))
env.setStateBackend(new FsStateBackend(args[0]));
env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3,5000));
2.复制一个wordcount的逻辑到程序中程序
3.开启flink的服务而后将程序打成jar包在web页面去执行
目标
我们要将我们实时处理的程序写入到hfds中!
问题
当值你直接执行的时候会报Server Response Message:
Internal server error.(内部服务器异常)
我们需要将将提前准备好的跟flink对应版本的hadoop包(flink-shaded-hadoop-2-uber-2.7.5-10.0.jar)直接放在flink的集群中一劳永益
代码思路

读取kafka的数据写入到redis数据库中去,并且保证程序健壮
我们为了让程序只执行一次,更加健壮
我们将数据结果写入redis数据库中
1.首先我们导入连接redis数据库的依赖
<dependency>
            <groupId>org.apache.bahir</groupId>
            <artifactId>flink-connector-redis_2.11</artifactId>
            <version>1.0</version>
        </dependency>
2.
	(1)调用sink将将计算好的结果保存到redis中
	(redis支持多种数据类型的数据k,v类型的写到redis里面的数据必须是String)
	我们在程序当中直接将官网当中的代码考过来(路径自己看)
	
3.	//创建jedis(客户端)连接配置信息
	new FlinkjedisPoolConfig.Builder()传入参数
	
4.	//添加一个sink路径
	addSink(new RedisSink<>(conf,new RedisWordCountMapper()));
	RedisWordCountMapper是要重写的传入名称和k,v的字段位置即可将结果写入到redis中

代码实现


public class ConnectKafka {
    public static void main(String[] args)throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        //1.开启一个检查站Checkpoint,
        //2.(存储策略)将快照的数据存到一个指定的存储系统里面
        //3.(重启策略)设置检查站每隔多长时间检查一次,一共检查多少次
        env.enableCheckpointing(30000);
        env.setStateBackend(new FsStateBackend(args[0]));
        env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3,5000));

        //new 一个实例!
        Properties properties = new Properties();

        //告诉程序我们要接收那台机器上生产的数据
        properties.setProperty("bootstrap.servers","doit01:9092,doit02:9092,doit03:9092");

        //告诉程序开启分区,已经分区名称
        properties.setProperty("group.id","args[1]");

        //告诉程序我需要开启一个偏移量的记录,并且是从头开始读的
        properties.setProperty("auto.offset.reset","earliest");

        //告诉kafka你不要自动提交偏移量了,每次搜自动提交偏移量
        properties.setProperty("enable.auto.commit","false");

        //如果FlinkKafkaConsumer没有开启checkpoint功能,为了不重复读取
        //这种方式无法实现Exactly-Once(只执行一次)
        FlinkKafkaConsumer <String>flinkKafkaConsumer = new FlinkKafkaConsumer("wordcount2", new SimpleStringSchema(), properties);

        //检查的时候将kafka的偏移量保存到kafka特殊的topic,默认的是ture
        flinkKafkaConsumer.setCommitOffsetsOnCheckpoints(false);

        DataStreamSource<String> lines = env.addSource(flinkKafkaConsumer);



        //我拷贝过来的wordcount的逻辑
        SingleOutputStreamOperator<Tuple2<String, Integer>> wordAndOne = lines.flatMap(new FlatMapFunction<String, Tuple2<String, Integer>>() {
            @Override
            public void flatMap(String line, Collector<Tuple2<String, Integer>> out) throws Exception {
                String[] words = line.split(" ");
                for (String word : words) {
                    out.collect(Tuple2.of(word, 1));
                }
            }
        });
        //分组
        KeyedStream<Tuple2<String, Integer>, Tuple> keyed = wordAndOne.keyBy(0);
        //聚合
        SingleOutputStreamOperator<Tuple2<String, Integer>> summed = keyed.sum(1);
        //调用sink
        FlinkJedisPoolConfig conf = new FlinkJedisPoolConfig.Builder()
                .setHost(args[3])
                .setPassword(args[4])
                .build();
        summed.addSink(new RedisSink<>(conf,new RedisWordCountMapper()));

        env.execute( "wordcoun");

    }

    //重写的程序
    private static class RedisWordCountMapper implements RedisMapper<Tuple2<String, Integer>> {
        @Override
        public RedisCommandDescription getCommandDescription() {
        //指定写入Redis中的方法和最外面的大key的名称
            return new RedisCommandDescription(RedisCommand.HSET,"wc");
        }

        @Override
        public String getKeyFromData(Tuple2<String, Integer> data) {
           //将数据中的哪个字段作为key写入
            return data.f0;
        }

        @Override
        public String getValueFromData(Tuple2<String, Integer> data) {
            //将数据中的那个字段作为value写入
            return data.f1.toString();
        }
    }
}


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值