流式处理平台
流式处理平台阶段:流式处理平台是对「计算」或者说处理数据时的抽象,在这抽象基础上它更能充分利用系统的资源(一个大的任务被拆分多个小任务,然后分发到不同的机器上执行)
这些流处理平台都会数据处理进行了抽象,让我们更加方便且高效去处理数据,比如一般会以下的功能:
系统提前设计了一部分的埋点信息了,在日志上打印下来:
/**
* 打点信息枚举
*/
@Getter
@ToString
@AllArgsConstructor
public enum AnchorState implements PowerfulEnum {
/**
* 消息接收成功(获取到请求)
*/
RECEIVE(10, "消息接收成功"),
/**
* 消息被丢弃(从Kafka消费后,被丢弃)
*/
DISCARD(20, "消费被丢弃"),
/**
* 消息被夜间屏蔽(模板设置了夜间屏蔽)
*/
NIGHT_SHIELD(22, "夜间屏蔽"),
/**
* 消息被夜间屏蔽(模板设置了夜间屏蔽,次日9点再发送)
*/
NIGHT_SHIELD_NEXT_SEND(24, "夜间屏蔽(次日早上9点发送)"),
/**
* 消息被内容去重(重复内容5min内多次发送)
*/
CONTENT_DEDUPLICATION(30, "消息被内容去重"),
/**
* 消息被频次去重(同一个渠道短时间内发送多次消息给用户)
*/
RULE_DEDUPLICATION(40, "消息被频次去重"),
/**
* 白名单过滤(非正式环境,不在白名单内)
*/
WHITE_LIST(50, "白名单过滤"),
/**
* 下发成功(调用渠道接口成功)
*/
SEND_SUCCESS(60, "消息下发成功"),
/**
* 下发失败(调用渠道接口失败)
*/
SEND_FAIL(70, "消息下发失败"),
/**
* 点击(下发的消息被点击)
*/
CLICK(64, "消息被点击");
private final Integer code;
private final String description;
}
接入流式处理平台就能对这一部分数据进行清洗(根据下发者维度、根据模板消息维度等等),得到清洗后的数据再给到接口去展示或者排查问题使用,能大大提高排查或者业务方的使用效率.
flink
Flink从2018年开始流行,现在已经有很多的公司都在用Flink作为实时大数据处理的流式平台。
首先安装下Flink,docker-compose.yml文件内容:
version: "2.2"
services:
jobmanager:
image: flink:latest
ports:
- "8081:8081"
command: jobmanager
environment:
- |
FLINK_PROPERTIES=
jobmanager.rpc.address: jobmanager
- SET_CONTAINER_TIMEZONE=true
- CONTAINER_TIMEZONE=Asia/Shanghai
- TZ=Asia/Shanghai
taskmanager:
image: flink:latest
depends_on:
- jobmanager
command: taskmanager
scale: 1
environment:
- |
FLINK_PROPERTIES=
jobmanager.rpc.address: jobmanager
taskmanager.numberOfTaskSlots: 2
- SET_CONTAINER_TIMEZONE=true
- CONTAINER_TIMEZONE=Asia/Shanghai
- TZ=Asia/Shanghai
完了之后直接docker-compose up -d就可以启动flink了,我们访问在浏览器输入ip:8081端口就能看到flink的后台了。
看看后台,就能知道我们在本地开发完打包成jar就可以在Submit New Job提交jar包给Flink去跑了。
在写代码的时候,可以参考官方文档给出的mvn命令去构建Flink的基础环境。
/**
* flink启动类
*/
@Slf4j
public class FlinkBootStrap {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
/**
* 1.获取KafkaConsumer
*/
KafkaSource<String> kafkaConsumer = MessageQueueUtils.getKafkaConsumer(AustinFlinkConstant.TOPIC_NAME, AustinFlinkConstant.GROUP_ID, AustinFlinkConstant.BROKER);
DataStreamSource<String> kafkaSource = env.fromSource(kafkaConsumer, WatermarkStrategy.noWatermarks(), AustinFlinkConstant.SOURCE_NAME);
/**
* 2. 数据转换处理
*/
SingleOutputStreamOperator<AnchorInfo> dataStream = kafkaSource.flatMap(new AustinFlatMapFunction()).name(AustinFlinkConstant.FUNCTION_NAME);
/**
* 3. 将实时数据多维度写入Redis(已实现),离线数据写入hive(未实现)
*/
dataStream.addSink(new AustinSink()).name(AustinFlinkConstant.SINK_NAME);
env.execute(AustinFlinkConstant.JOB_NAME);
}
}
主要实现了将数据实时聚合到Redis,分了两个维度:用户和消息模板(对应的Redis结构都已经写在了代码的注释上了)
接着只要在kafka创建对应的topic(我这里定义的topicName是austinLog),并且在AustinFlinkConstant中填写Kafka的Broker信息以及Redis信息后,编译打包就完了。
/**
* Flink常量信息
*/
public class AustinFlinkConstant {
/**
* Kafka 配置信息
* !!! TODO 使用前配置kafka broker ip:port
*/
public static final String GROUP_ID = "austinLogGroup";
public static final String TOPIC_NAME = "austinTraceLog";
public static final String BROKER = "austin-kafka:9092";
/**
* redis 配置
* !!! TODO 使用前配置redis ip:port
*/
public static final String REDIS_IP = "austin-redis";
public static final String REDIS_PORT = "6379";
public static final String REDIS_PASSWORD = "austin";
/**
* Flink流程常量
*/
public static final String SOURCE_NAME = "austin_kafka_source";
public static final String FUNCTION_NAME = "austin_transfer";
public static final String SINK_NAME = "austin_sink";
public static final String JOB_NAME = "AustinBootStrap";
private AustinFlinkConstant() {
}
}