Un caso completo de computación de flujo de big data Flink de extremo a extremo

Capítulo 1 Introducción

En el artículo anterior, presenté la preparación del entorno relacionado con Flink y completé el establecimiento de un entorno de desarrollo Flink simple; este artículo presenta un caso completo de extremo a extremo que cubre la informática Flink : cliente => Servicio API web = > Kafka => Flink => MySQL. Esta vez seguimos tomando Flink Table API / SQL como ejemplo y lo implementamos en docker-compose. (En el artículo solo se proporciona la parte clave del código. Para obtener el código completo, consulte el github subido por el autor).

 

Capítulo 2 docker-compose

2.1 Agregar archivo docker-compose.yml

version: '2'
services:
  jobmanager:
    image: zihaodeng/flink:1.11.1
    volumes:
      - D:/21docker/flinkDeploy:/opt/flinkDeploy
    hostname: "jobmanager"
    expose:
      - "6123"
    ports:
      - "4000:4000"
    command: jobmanager
    environment:
      - JOB_MANAGER_RPC_ADDRESS=jobmanager
  taskmanager:
    image: zihaodeng/flink:1.11.1
    volumes:
      - D:/21docker/flinkDeploy:/opt/flinkDeploy
    expose:
      - "6121"
      - "6122"
    depends_on:
      - jobmanager
    command: taskmanager
    links:
      - jobmanager:jobmanager
    environment:
      - JOB_MANAGER_RPC_ADDRESS=jobmanager
  zookeeper:
    container_name: zookeeper
    image: zookeeper:3.6.1
    ports:
      - "2181:2181"
  kafka:
    container_name: kafka
    image: wurstmeister/kafka:2.12-2.5.0
    volumes:
      - D:/21docker/var/run/docker.sock:/var/run/docker.sock
    ports:
      - "9092:9092"
    depends_on:
      - zookeeper
    environment:
      #KAFKA_ADVERTISED_HOST_NAME: kafka
      HOSTNAME_COMMAND: "route -n | awk '/UG[ \t]/{print $$2}'"
      KAFKA_CREATE_TOPICS: "order-log:1:1"
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
      #KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://127.0.0.1:9092
      #KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
  mysql:
    image: mysql:5.7
    container_name: mysql
    volumes:
      - D:/21docker/mysql/data/db:/var/lib/mysql/
      - D:/21docker/mysql/mysql-3346.sock:/var/run/mysql.sock
      - D:/21docker/mysql/data/conf:/etc/mysql/conf.d
    ports:
      - 3306:3306
    command:
      --default-authentication-plugin=mysql_native_password
      --lower_case_table_names=1
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      TZ: Asia/Shanghai

2.2 inicio de docker-compose

$ docker-compose up -d

Comprobar funcionamiento

En esta sección, docker-compose está listo, y será muy conveniente iniciar el entorno de trabajo más tarde, a continuación, comience a preparar el programa correspondiente.

 

Capítulo 3 Creación de un proyecto WebApi

3.1 Crear proyecto de interfaz WebApi (Restful API)

Use springboot para crear rápidamente un proyecto de API. El autor aquí usa el formato de interfaz Restful Api; parte del código es el siguiente (consulte el github del autor para obtener el código completo).

Cree una interfaz de publicación para que el cliente llame

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private Sender sender;

    @PostMapping
    public String insertOrder(@RequestBody Order order) {
        sender.producerKafka(order);
        return "{\"code\":0,\"message\":\"insert success\"}";
    }
}

Cree una clase de remitente y envíe datos a Kafka 

public class Sender {
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    private static Random rand = new Random();

    public void producerKafka(Order order){
        order.setPayTime(String.valueOf(new Timestamp(System.currentTimeMillis()+ rand.nextInt(100))));//EventTime
        kafkaTemplate.send("order-log", JSON.toJSONString(order));
    }
}

 

Capítulo 4 Creación de trabajos Flink

Aquí, Flink Table API / SQL se utiliza para implementar un cálculo de ventana de caída: los datos leídos en Kafka se escriben en MySQL después de resumir el cálculo de la ventana.

public class Kafka2MysqlByEnd2End {
    public static void main(String[] args) throws Exception {
        // Kafka source
        String sourceSQL="CREATE TABLE order_source (\n" +
                "   payTime VARCHAR,\n" +
                "   rt as TO_TIMESTAMP(payTime),\n" +
                "   orderId BIGINT,\n" +
                "   goodsId INT,\n" +
                "   userId INT,\n" +
                "   amount DECIMAL(23,10),\n" +
                "   address VARCHAR,\n" +
                "   WATERMARK FOR rt as rt - INTERVAL '2' SECOND\n" +
                " ) WITH (\n" +
                "   'connector' = 'kafka-0.11',\n" +
                "   'topic'='order-log',\n" +
                "   'properties.bootstrap.servers'='kafka:9092',\n" +
                "   'format' = 'json',\n" +
                "   'scan.startup.mode' = 'latest-offset'\n" +
                ")";

        //Mysql sink
        String sinkSQL="CREATE TABLE order_sink (\n" +
                "   goodsId BIGINT,\n" +
                "   goodsName VARCHAR,\n" +
                "   amount DECIMAL(23,10),\n" +
                "   rowtime TIMESTAMP(3),\n" +
                "   PRIMARY KEY (goodsId) NOT ENFORCED\n" +
                " ) WITH (\n" +
                "   'connector' = 'jdbc',\n" +
                "   'url' = 'jdbc:mysql://mysql:3306/flinkdb?characterEncoding=utf-8&useSSL=false',\n" +
                "   'table-name' = 'good_sale',\n" +
                "   'username' = 'root',\n" +
                "   'password' = '123456',\n" +
                "   'sink.buffer-flush.max-rows' = '1',\n" +
                "   'sink.buffer-flush.interval' = '1s'\n" +
                ")";

        // 创建执行环境
        EnvironmentSettings settings = EnvironmentSettings
                .newInstance()
                .useBlinkPlanner()
                .inStreamingMode()
                .build();
        //TableEnvironment tEnv = TableEnvironment.create(settings);
        StreamExecutionEnvironment sEnv = StreamExecutionEnvironment.getExecutionEnvironment();

        //sEnv.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, Time.of(1, TimeUnit.SECONDS)));
        //sEnv.enableCheckpointing(1000);
        //sEnv.setStateBackend(new FsStateBackend("file:///tmp/chkdir",false));

        StreamTableEnvironment tEnv= StreamTableEnvironment.create(sEnv,settings);

        Configuration configuration = tEnv.getConfig().getConfiguration();
        //设置并行度为1
        configuration.set(CoreOptions.DEFAULT_PARALLELISM, 1);

        //注册souuce
        tEnv.executeSql(sourceSQL);
        //注册sink
        tEnv.executeSql(sinkSQL);

        //UDF 在作业中定义UDF
        tEnv.createFunction("exchangeGoods", ExchangeGoodsName.class);

        String strSQL=" SELECT " +
                "   goodsId," +
                "   exchangeGoods(goodsId) as goodsName, " +
                "   sum(amount) as amount, " +
                "   tumble_start(rt, interval '5' seconds) as rowtime " +
                " FROM order_source " +
                " GROUP BY tumble(rt, interval '5' seconds),goodsId";

        //查询数据 插入数据
        tEnv.sqlQuery(strSQL).executeInsert("order_sink");

        //执行作业
        tEnv.execute("统计各商品营业额");
    }
}

 

Capítulo 5 Creación de tablas de bases de datos MySQL

5.1 Construir una biblioteca

mysql> create database flinkdb;

5.2 Crear una tabla

mysql> create table good_sale(goodsId bigint primary key, goodsName varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci, amount decimal(23,10), rowtime timestamp);

Nota: la clave principal es la misma que la clave principal definida por el flink job ddl. La clave principal se define en el flink ddl, y el conector está en el modo upsert (Flink decidirá si insertar una nueva fila o actualizar una fila existente de acuerdo con la clave principal para garantizar la idempotencia), si no La definición es modo de adición (modo de inserción de inserción, si la clave principal entra en conflicto, la inserción fallará).

En este punto, se han preparado el entorno y el código y luego se comienza a ejecutar la verificación.

 

Capítulo 6 Ejecución de trabajos

6.1 Verificación de depuración local

6.1.1 Iniciar el clúster

Usando el método del Capítulo 2, inicie nuestro entorno de clúster preparado:

$ docker-compose up -d

 

6.1.2 Iniciar trabajo

Inicie el proyecto WebApi y el proyecto de trabajo Flink en IDEA local .

6.1.3 Iniciar una solicitud

Aquí se utiliza una herramienta http para simular que el cliente inicie una solicitud y envíe datos en formato json:

6.1.4 Ver el estado de ejecución de los trabajos de flink

Ver el registro directamente en la consola de IDEA

6.1.5 Ver resultados

Ver los resultados en MySQL

 

En este paso, puede ver que el trabajo depurado por el IDE local ha extraído con éxito los datos de la fuente y, después del cálculo de flink, los datos se escriben en MySQL. A continuación, completaremos el envío del trabajo al clúster para que se ejecute.

6.2 Verificación del funcionamiento del clúster

6.2.1 Embalaje

Empaquetado del paquete jar del proyecto WebAPI

Vaya al directorio lotemall-webapi (proyecto WebApi del autor) para ejecutar el comando de empaquetado

mvn clean package -DskipTests

Prepare el Dockerfile y colóquelo en el mismo directorio que el paquete jar. Ejecute el siguiente comando para crear imágenes

$ docker build -t lotemall-webapi .

Empaque el paquete del tarro de trabajo de Flink

Vaya al directorio flink-kafka2mysql (proyecto de trabajo de Flink del autor) para ejecutar el comando de empaquetado

Tenga en cuenta que debido a que enviamos al contenedor para su uso, la IP de configuración de la conexión de origen y receptor debe cambiarse del host local original al nombre del contenedor

mvn clean package -DskipTests

Coloque el paquete jar empaquetado en el directorio de montaje de Docker

6.2.2 Iniciar el clúster

Usando el método del Capítulo 2, inicie nuestro entorno de clúster preparado: 

$ docker-compose up -d

6.2.3 Iniciar proyecto WebAPI

Ejecute el comando docker run para iniciar el proyecto WebAPI

$ docker run --link kafka:kafka --net flink-online_default -e TZ=Asia/Shanghai -d -p 8090:8080 lotemall-webapi

6.2.4 Ejecutar trabajo de Flink

Ingrese al contenedor flink jobmanager y ejecute el trabajo

$ docker exec -it flink-online_jobmanager_1 /bin/bash
$ bin/flink run -c sql.Kafka2MysqlByEnd2End /opt/flinkDeploy/flink-kafka2mysql-0.0.1.jar -d

O envíe el paquete del jar del trabajo a través de la interfaz web

Después de enviar el trabajo, verifique la interfaz web de Flink, puede ver que el trabajo que enviamos ha comenzado a ejecutarse

6.2.5 Iniciar una solicitud

También use la herramienta http para simular que el cliente inicie una solicitud y envíe datos en formato json:

6.2.6 Ver el estado de ejecución de los trabajos de Flink

Envíe al clúster para que se ejecute, puede ver directamente el estado de ejecución del trabajo en la interfaz web de Flink

 Ver la marca de agua generada

6.2.7 Ver resultados 

Ver los resultados en MySQL

El registro cuyo GoodsName es "cake" en la primera línea es el resultado del cálculo de Flink en este grupo. 

 

En resumen , este artículo presenta la implementación conveniente de clústeres mediante docker-compose y completa un caso completo de informática de flujo Flink.

Supongo que te gusta

Origin blog.csdn.net/dzh284616172/article/details/109251225
Recomendado
Clasificación