乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Flink處理函數(shù)實(shí)戰(zhàn)之五:CoProcessFunction(雙流處理)

       小樣樣樣樣樣樣 2021-07-04

      歡迎訪問(wèn)我的GitHub

      https://github.com/zq2599/blog_demos

      內(nèi)容:所有原創(chuàng)文章分類(lèi)匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;

      歡迎訪問(wèn)我的GitHub

      這里分類(lèi)和匯總了欣宸的全部原創(chuàng)(含配套源碼):https://github.com/zq2599/blog_demos

      Flink處理函數(shù)實(shí)戰(zhàn)系列鏈接

      1. 深入了解ProcessFunction的狀態(tài)操作(Flink-1.10)

      2. ProcessFunction;

      3. KeyedProcessFunction類(lèi)

      4. ProcessAllWindowFunction(窗口處理);

      5. CoProcessFunction(雙流處理);

      本篇概覽

      • 本文是《Flink處理函數(shù)實(shí)戰(zhàn)》系列的第五篇,學(xué)習(xí)內(nèi)容是如何同時(shí)處理兩個(gè)數(shù)據(jù)源的數(shù)據(jù);

      • 試想在面對(duì)兩個(gè)輸入流時(shí),如果這兩個(gè)流的數(shù)據(jù)之間有業(yè)務(wù)關(guān)系,該如何編碼實(shí)現(xiàn)呢,例如下圖中的操作,同時(shí)監(jiān)聽(tīng)99989999端口,將收到的輸出分別處理后,再由同一個(gè)sink處理(打印):
        在這里插入圖片描述

      • Flink支持的方式是擴(kuò)展CoProcessFunction來(lái)處理,為了更清楚認(rèn)識(shí),我們把KeyedProcessFunctionCoProcessFunction的類(lèi)圖擺在一起看,如下所示:
        在這里插入圖片描述

      • 從上圖可見(jiàn),CoProcessFunction和KeyedProcessFunction的繼承關(guān)系一樣,另外CoProcessFunction自身也很簡(jiǎn)單,在processElement1和processElement2中分別處理兩個(gè)上游流入的數(shù)據(jù)即可,并且也支持定時(shí)器設(shè)置;

      編碼實(shí)戰(zhàn)

      接下來(lái)咱們開(kāi)發(fā)一個(gè)應(yīng)用來(lái)體驗(yàn)CoProcessFunction,功能非常簡(jiǎn)單,描述如下:

      1. 建兩個(gè)數(shù)據(jù)源,數(shù)據(jù)分別來(lái)自本地99989999端口;

      2. 每個(gè)端口收到類(lèi)似aaa,123這樣的數(shù)據(jù),轉(zhuǎn)成Tuple2實(shí)例,f0是aaa,f1是123;

      3. 在CoProcessFunction的實(shí)現(xiàn)類(lèi)中,對(duì)每個(gè)數(shù)據(jù)源的數(shù)據(jù)都打日志,然后全部傳到下游算子;

      4. 下游操作是打印,因此99989999端口收到的所有數(shù)據(jù)都會(huì)在控制臺(tái)打印出來(lái);

      5. 整個(gè)demo的功能如下圖所示:
        在這里插入圖片描述

      • 接下來(lái)編碼實(shí)現(xiàn)上述功能;

      源碼下載

      如果您不想寫(xiě)代碼,整個(gè)系列的源碼可在GitHub下載到,地址和鏈接信息如下表所示(https://github.com/zq2599/blog_demos):

      名稱(chēng)鏈接備注
      項(xiàng)目主頁(yè)https://github.com/zq2599/blog_demos該項(xiàng)目在GitHub上的主頁(yè)
      git倉(cāng)庫(kù)地址(https)https://github.com/zq2599/blog_demos.git該項(xiàng)目源碼的倉(cāng)庫(kù)地址,https協(xié)議
      git倉(cāng)庫(kù)地址(ssh)git@github.com:zq2599/blog_demos.git該項(xiàng)目源碼的倉(cāng)庫(kù)地址,ssh協(xié)議

      這個(gè)git項(xiàng)目中有多個(gè)文件夾,本章的應(yīng)用在flinkstudy文件夾下,如下圖紅框所示:
      在這里插入圖片描述

      Map算子

      1. 做一個(gè)map算子,用來(lái)將字符串aaa,123轉(zhuǎn)成Tuple2實(shí)例,f0是aaa,f1是123;

      2. 算子名為WordCountMap.java

      package com.bolingcavalry.coprocessfunction;
      
      import org.apache.flink.api.common.functions.MapFunction;
      import org.apache.flink.api.java.tuple.Tuple2;
      import org.apache.flink.util.StringUtils;
      
      public class WordCountMap implements MapFunction<String, Tuple2<String, Integer>> {
          @Override
          public Tuple2<String, Integer> map(String s) throws Exception {
      
              if(StringUtils.isNullOrWhitespaceOnly(s)) {
                  System.out.println("invalid line");
                  return null;
              }
      
              String[] array = s.split(",");
      
              if(null==array || array.length<2) {
                  System.out.println("invalid line for array");
                  return null;
              }
      
              return new Tuple2<>(array[0], Integer.valueOf(array[1]));
          }
      }

      便于擴(kuò)展的抽象類(lèi)

      • 開(kāi)發(fā)一個(gè)抽象類(lèi),將前面圖中提到的監(jiān)聽(tīng)端口、map處理、keyby處理、打印都做到這個(gè)抽象類(lèi)中,但是CoProcessFunction的邏輯卻不放在這里,而是交給子類(lèi)來(lái)實(shí)現(xiàn),這樣如果我們想進(jìn)一步實(shí)踐和擴(kuò)展CoProcessFunction的能力,只要在子類(lèi)中專(zhuān)注做好CoProcessFunction相關(guān)開(kāi)發(fā)即可,如下圖,紅色部分交給子類(lèi)實(shí)現(xiàn),其余的都是抽象類(lèi)完成的:
        在這里插入圖片描述

      • 抽象類(lèi)AbstractCoProcessFunctionExecutor.java,源碼如下,稍后會(huì)說(shuō)明幾個(gè)關(guān)鍵點(diǎn):

      package com.bolingcavalry.coprocessfunction;
      
      import org.apache.flink.api.java.tuple.Tuple;
      import org.apache.flink.api.java.tuple.Tuple2;
      import org.apache.flink.streaming.api.datastream.KeyedStream;
      import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
      import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
      import org.apache.flink.streaming.api.functions.co.CoProcessFunction;
      
      /**
       * @author will
       * @email zq2599@gmail.com
       * @date 2020-11-09 17:33
       * @description 串起整個(gè)邏輯的執(zhí)行類(lèi),用于體驗(yàn)CoProcessFunction
       */
      public abstract class AbstractCoProcessFunctionExecutor {
      
          /**
           * 返回CoProcessFunction的實(shí)例,這個(gè)方法留給子類(lèi)實(shí)現(xiàn)
           * @return
           */
          protected abstract CoProcessFunction<
                  Tuple2<String, Integer>,
                  Tuple2<String, Integer>,
                  Tuple2<String, Integer>> getCoProcessFunctionInstance();
      
          /**
           * 監(jiān)聽(tīng)根據(jù)指定的端口,
           * 得到的數(shù)據(jù)先通過(guò)map轉(zhuǎn)為T(mén)uple2實(shí)例,
           * 給元素加入時(shí)間戳,
           * 再按f0字段分區(qū),
           * 將分區(qū)后的KeyedStream返回
           * @param port
           * @return
           */
          protected KeyedStream<Tuple2<String, Integer>, Tuple> buildStreamFromSocket(StreamExecutionEnvironment env, int port) {
              return env
                      // 監(jiān)聽(tīng)端口
                      .socketTextStream("localhost", port)
                      // 得到的字符串"aaa,3"轉(zhuǎn)成Tuple2實(shí)例,f0="aaa",f1=3
                      .map(new WordCountMap())
                      // 將單詞作為key分區(qū)
                      .keyBy(0);
          }
      
          /**
           * 如果子類(lèi)有側(cè)輸出需要處理,請(qǐng)重寫(xiě)此方法,會(huì)在主流程執(zhí)行完畢后被調(diào)用
           */
          protected void doSideOutput(SingleOutputStreamOperator<Tuple2<String, Integer>> mainDataStream) {
          }
      
          /**
           * 執(zhí)行業(yè)務(wù)的方法
           * @throws Exception
           */
          public void execute() throws Exception {
              final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
      
              // 并行度1
              env.setParallelism(1);
      
              // 監(jiān)聽(tīng)9998端口的輸入
              KeyedStream<Tuple2<String, Integer>, Tuple> stream1 = buildStreamFromSocket(env, 9998);
      
              // 監(jiān)聽(tīng)9999端口的輸入
              KeyedStream<Tuple2<String, Integer>, Tuple> stream2 = buildStreamFromSocket(env, 9999);
      
              SingleOutputStreamOperator<Tuple2<String, Integer>> mainDataStream = stream1
                      // 兩個(gè)流連接
                      .connect(stream2)
                      // 執(zhí)行低階處理函數(shù),具體處理邏輯在子類(lèi)中實(shí)現(xiàn)
                      .process(getCoProcessFunctionInstance());
      
              // 將低階處理函數(shù)輸出的元素全部打印出來(lái)
              mainDataStream.print();
      
              // 側(cè)輸出相關(guān)邏輯,子類(lèi)有側(cè)輸出需求時(shí)重寫(xiě)此方法
              doSideOutput(mainDataStream);
      
              // 執(zhí)行
              env.execute("ProcessFunction demo : CoProcessFunction");
          }
      }
      • 關(guān)鍵點(diǎn)之一:一共有兩個(gè)數(shù)據(jù)源,每個(gè)源的處理邏輯都封裝到buildStreamFromSocket方法中;

      • 關(guān)鍵點(diǎn)之二:stream1.connect(stream2)將兩個(gè)流連接起來(lái);

      • 關(guān)鍵點(diǎn)之三:process接收CoProcessFunction實(shí)例,合并后的流的處理邏輯就在這里面;

      • 關(guān)鍵點(diǎn)之四:getCoProcessFunctionInstance是抽象方法,返回CoProcessFunction實(shí)例,交給子類(lèi)實(shí)現(xiàn),所以CoProcessFunction中做什么事情完全由子類(lèi)決定;

      • 關(guān)鍵點(diǎn)之五:doSideOutput方法中啥也沒(méi)做,但是在主流程代碼的末尾會(huì)被調(diào)用,如果子類(lèi)有側(cè)輸出(SideOutput)的需求,重寫(xiě)此方法即可,此方法的入?yún)⑹翘幚磉^(guò)的數(shù)據(jù)集,可以從這里取得側(cè)輸出;

      子類(lèi)決定CoProcessFunction的功能

      1. 子類(lèi)CollectEveryOne.java如下所示,邏輯很簡(jiǎn)單,將每個(gè)源的上游數(shù)據(jù)直接輸出到下游算子:

      package com.bolingcavalry.coprocessfunction;
      
      import org.apache.flink.api.java.tuple.Tuple2;
      import org.apache.flink.streaming.api.functions.co.CoProcessFunction;
      import org.apache.flink.util.Collector;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      public class CollectEveryOne extends AbstractCoProcessFunctionExecutor {
      
          private static final Logger logger = LoggerFactory.getLogger(CollectEveryOne.class);
      
          @Override
          protected CoProcessFunction<Tuple2<String, Integer>, Tuple2<String, Integer>, Tuple2<String, Integer>> getCoProcessFunctionInstance() {
              return new CoProcessFunction<Tuple2<String, Integer>, Tuple2<String, Integer>, Tuple2<String, Integer>>() {
      
                  @Override
                  public void processElement1(Tuple2<String, Integer> value, Context ctx, Collector<Tuple2<String, Integer>> out) {
                      logger.info("處理1號(hào)流的元素:{},", value);
                      out.collect(value);
                  }
      
                  @Override
                  public void processElement2(Tuple2<String, Integer> value, Context ctx, Collector<Tuple2<String, Integer>> out) {
                      logger.info("處理2號(hào)流的元素:{}", value);
                      out.collect(value);
                  }
              };
          }
      
          public static void main(String[] args) throws Exception {
              new CollectEveryOne().execute();
          }
      }
      1. 上述代碼中,CoProcessFunction后面的泛型定義很長(zhǎng):<Tuple2<String, Integer>, Tuple2<String, Integer>, Tuple2<String, Integer>> ,一共三個(gè)Tuple2,分別代表一號(hào)數(shù)據(jù)源輸入、二號(hào)數(shù)據(jù)源輸入、下游輸出的類(lèi)型;

      驗(yàn)證

      1. 分別開(kāi)啟本機(jī)的99989999端口,我這里是MacBook,執(zhí)行nc -l 9998nc -l 9999

      2. 啟動(dòng)Flink應(yīng)用,如果您和我一樣是Mac電腦,直接運(yùn)行CollectEveryOne.main方法即可(如果是windows電腦,我這沒(méi)試過(guò),不過(guò)做成jar在線部署也是可以的);

      3. 在監(jiān)聽(tīng)9998和9999端口的控制臺(tái)分別輸入aaa,111bbb,222

      4. 以下是flink控制臺(tái)輸出的內(nèi)容,可見(jiàn)processElement1和processElement1方法的日志代碼已經(jīng)執(zhí)行,并且print方法作為最下游,將兩個(gè)數(shù)據(jù)源的數(shù)據(jù)都打印出來(lái)了,符合預(yù)期:

      12:45:38,774 INFO CollectEveryOne - 處理1號(hào)流的元素:(aaa,111),
      (aaa,111)
      12:45:43,816 INFO CollectEveryOne - 處理2號(hào)流的元素:(bbb,222)
      (bbb,222)

      更多

      • 以上就是最基本的CoProcessFunction用法,其實(shí)CoProcessFunction的使用遠(yuǎn)不及此,結(jié)合狀態(tài),可以processElement1獲得更多二號(hào)流的元素信息,另外還可以結(jié)合定時(shí)器來(lái)約束兩個(gè)流協(xié)同處理的等待時(shí)間,您可以參考前面文章中的狀態(tài)和定時(shí)器來(lái)自行嘗試;

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類(lèi)似文章 更多