Flink数据流写入Elasticsearch实战

目录

[1. 代码结构](#1. 代码结构)

[2. 代码解析](#2. 代码解析)

[(1) 主程序入口](#(1) 主程序入口)

[(2) 配置 Elasticsearch 集群](#(2) 配置 Elasticsearch 集群)

[(3) 定义 Elasticsearch Sink Function](#(3) 定义 Elasticsearch Sink Function)

[(4) 添加 Elasticsearch Sink](#(4) 添加 Elasticsearch Sink)

[(5) 执行任务](#(5) 执行任务)

[3. 验证命令](#3. 验证命令)


这段代码是一个使用 Apache Flink 将数据流(Event 对象)写入 Elasticsearch 的示例。以下是对代码的详细解析和说明:

1. 代码结构

  • 包声明package sink

    定义了代码所在的包。

  • 导入依赖

    导入了必要的 Java 和 Flink 相关类库,包括:

    • java.util:用于使用 ArrayListHashMap
    • org.apache.flink:Flink 的核心类库。
    • org.apache.flink.streaming.connectors.elasticsearch:Flink 的 Elasticsearch Sink 相关类。
    • org.elasticsearch.client.Requests:Elasticsearch 的请求工具类。
  • Event

    定义了一个简单的 Event 类,包含三个字段:

    • user:用户名称。
    • url:访问的 URL。
    • timestamp:时间戳。
  • sinkToEs 对象

    主程序入口,包含 Flink 流处理逻辑和 Elasticsearch Sink 的配置。

Scala 复制代码
package sink

import java.util

import org.apache.flink.api.common.functions.RuntimeContext
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.connectors.elasticsearch.{ElasticsearchSinkFunction, RequestIndexer}
import org.apache.flink.streaming.connectors.elasticsearch6.ElasticsearchSink
import org.apache.http.HttpHost
import org.elasticsearch.client.Requests
import source.ClickSource

case class Event(user:String,url:String,timestamp:Long)
/**
 *
 * @PROJECT_NAME: flink1.13
 * @PACKAGE_NAME: sink
 * @author: 赵嘉盟-HONOR
 * @data: 2023-11-20 15:04
 * @DESCRIPTION
 *
 */
object sinkToEs {
  def main(args: Array[String]): Unit = {
    val env = StreamExecutionEnvironment.getExecutionEnvironment
    val data = env.fromElements(
      Event("Mary", "./home", 100L),
      Event("Sum", "./cart", 500L),
      Event("King", "./prod", 1000L),
      Event("King", "./root", 200L)
    )

    //定义es集群主机列表
    val hosts = new util.ArrayList[HttpHost]()
    hosts.add(new HttpHost("master",9200))

    //定义一个esSinkFunction
    val esFun = new ElasticsearchSinkFunction[Event] {
      override def process(t: Event, runtimeContext: RuntimeContext, requestIndexer: RequestIndexer): Unit = {
        val data = new util.HashMap[String, String]()
        data.put(t.user, t.url)
        //包装要发送的http请求
        val request = Requests.indexRequest()
          .index("clicks") //表名
          .source(data) //数据
          .`type`("event") //类型
        //发送请求
        requestIndexer.add(request)
      }
    }
    data.addSink(new ElasticsearchSink.Builder[Event](hosts,esFun).build())
    //验证命令
    //curl 'localhost:9200/_cat/indices?v'
    //curl 'localhost:9200/clicks/_search?pretty'
    env.execute("sinkRedis")
  }
}

基于scala使用flink将读取到的数据写入到ES

发送完毕后可以使用以下命令进行验证:

bash 复制代码
curl 'localhost:9200/_cat/indices?v'
curl 'localhost:9200/clicks/_search?pretty'

2. 代码解析

(1) 主程序入口
复制代码
def main(args: Array[String]): Unit = {
  val env = StreamExecutionEnvironment.getExecutionEnvironment
  val data = env.fromElements(
    Event("Mary", "./home", 100L),
    Event("Sum", "./cart", 500L),
    Event("King", "./prod", 1000L),
    Event("King", "./root", 200L)
  )
  • 创建 Flink 流处理环境 StreamExecutionEnvironment
  • 使用 fromElements 方法生成一个包含 4 个 Event 对象的流。
(2) 配置 Elasticsearch 集群
复制代码
val hosts = new util.ArrayList[HttpHost]()
hosts.add(new HttpHost("master", 9200))
  • 创建一个 ArrayList,用于存储 Elasticsearch 集群的主机信息。
  • 添加一个 Elasticsearch 节点(master,端口 9200)。
(3) 定义 Elasticsearch Sink Function
复制代码
val esFun = new ElasticsearchSinkFunction[Event] {
  override def process(t: Event, runtimeContext: RuntimeContext, requestIndexer: RequestIndexer): Unit = {
    val data = new util.HashMap[String, String]()
    data.put(t.user, t.url)
    val request = Requests.indexRequest()
      .index("clicks") // 索引名称
      .source(data)    // 数据
      .`type`("event") // 类型
    requestIndexer.add(request)
  }
}
  • 实现 ElasticsearchSinkFunction 接口,定义如何将 Event 对象写入 Elasticsearch。
  • process 方法中:
    • Event 对象的 userurl 字段存入 HashMap
    • 使用 Requests.indexRequest() 创建一个索引请求。
    • 指定索引名称(clicks)、数据源(data)和类型(event)。
    • 通过 requestIndexer.add(request) 发送请求。
(4) 添加 Elasticsearch Sink
复制代码
data.addSink(new ElasticsearchSink.Builder[Event](hosts, esFun).build())
  • 使用 ElasticsearchSink.Builder 构建 Elasticsearch Sink。
  • 将 Sink 添加到数据流中。
(5) 执行任务
复制代码
env.execute("sinkRedis")
  • 启动 Flink 流处理任务,任务名称为 sinkRedis

3. 验证命令

  • 查看 Elasticsearch 索引

    bash

    复制代码
    curl 'localhost:9200/_cat/indices?v'

    检查 clicks 索引是否创建成功。

  • 查询索引数据

    bash

    复制代码
    curl 'localhost:9200/clicks/_search?pretty'

    查看 clicks 索引中的数据。

相关推荐
Elasticsearch1 天前
Elasticsearch:使用 AI Agent 来创建 workflows
elasticsearch
渣渣盟1 天前
当反压问题解决后,如何进一步优化 Flink 作业的 Checkpoint 性能,让大状态作业也能稳定运行?
大数据·flink
gll7731 天前
RAG 检索层实战:Redis 缓存 + ES 混合检索 + BGE-Rerank 重排全链路落地与踩坑
elasticsearch
Elasticsearch1 天前
ES 存日志很贵?我用 ES 9.5 把日志从 4.5G 压到 412M 压缩比11.2倍,日志硬扫每秒128万行!
elasticsearch
Elasticsearch1 天前
Elasticsearch 作为统一平台:引入第二套数据系统究竟要付出什么代价
elasticsearch
Elastic 中国社区官方博客1 天前
Elasticsearch:列式索引模式 - Columnar index mode
大数据·数据库·elasticsearch·搜索引擎·全文检索
Elasticsearch1 天前
Elasticsearch 的批量查询阶段如何在大规模场景下提升搜索性能
elasticsearch
渣渣盟1 天前
当 Redis 写入不再是瓶颈后,Flink 任务的反压可能来自哪里?如何系统性地定位和解决 Flink 反压问题?
数据库·redis·flink
渣渣盟1 天前
当 Redis 集群发生主从切换(Failover)时,Flink 任务会崩溃吗?如何利用 Sentinel 实现高可用?
redis·flink·sentinel
Ramboooooooo1 天前
SkyWalking-10.4.0 Docker + Nacos + Elasticsearch 生产级部署手册
elasticsearch·docker·skywalking