Apache flink ApacheFlink-使用数据流中的值动态创建流数据源

Apache flink ApacheFlink-使用数据流中的值动态创建流数据源,apache-flink,Apache Flink,我正在尝试使用Apache Flink构建一个示例应用程序,该应用程序执行以下操作: 从卡夫卡队列中读取股票符号流(例如“CSCO”、“FB”) 对于每个符号,执行当前价格的实时查找,并将值流化以供下游处理 *更新到原始帖子* 我将map函数移动到一个单独的类中,并且没有得到运行时错误消息“MapFunction的实现不再是可序列化的。对象可能包含或引用不可序列化的字段” 我现在面临的问题是,卡夫卡主题“股票价格”,我试图写的价格,是没有收到他们。我正在尝试排除故障,并将发布任何更新 publi

我正在尝试使用Apache Flink构建一个示例应用程序,该应用程序执行以下操作:

  • 从卡夫卡队列中读取股票符号流(例如“CSCO”、“FB”)
  • 对于每个符号,执行当前价格的实时查找,并将值流化以供下游处理
  • *更新到原始帖子*

    我将map函数移动到一个单独的类中,并且没有得到运行时错误消息“MapFunction的实现不再是可序列化的。对象可能包含或引用不可序列化的字段”

    我现在面临的问题是,卡夫卡主题“股票价格”,我试图写的价格,是没有收到他们。我正在尝试排除故障,并将发布任何更新

    public class RetrieveStockPrices { 
        @SuppressWarnings("serial") 
        public static void main(String[] args) throws Exception { 
            final StreamExecutionEnvironment streamExecEnv = StreamExecutionEnvironment.getExecutionEnvironment();
            streamExecEnv.setStreamTimeCharacteristic(TimeCharacteristic.IngestionTime); 
    
            Properties properties = new Properties(); 
            properties.setProperty("bootstrap.servers", "localhost:9092"); 
            properties.setProperty("zookeeper.connect", "localhost:2181"); 
            properties.setProperty("group.id", "stocks"); 
    
            DataStream<String> streamOfStockSymbols = streamExecEnv.addSource(new FlinkKafkaConsumer08<String>("stocksymbol", new SimpleStringSchema(), properties)); 
    
            DataStream<String> stockPrice = 
                streamOfStockSymbols 
                //get unique keys 
                .keyBy(new KeySelector<String, String>() { 
                    @Override 
                    public String getKey(String trend) throws Exception {
                        return trend; 
                    }
                    }) 
                //collect events over a window 
                .window(TumblingEventTimeWindows.of(Time.seconds(60))) 
                //return the last event from the window...all elements are the same "Symbol" 
                .apply(new WindowFunction<String, String, String, TimeWindow>() {
                    @Override 
                    public void apply(String key, TimeWindow window, Iterable<String> input, Collector<String> out) throws Exception { 
                        out.collect(input.iterator().next().toString()); 
                    }
                })
                .map(new StockSymbolToPriceMapFunction());
    
            streamExecEnv.execute("Retrieve Stock Prices"); 
        }
    }
    
    public class StockSymbolToPriceMapFunction extends RichMapFunction<String, String> {
        @Override
        public String map(String stockSymbol) throws Exception {
            final StreamExecutionEnvironment streamExecEnv = StreamExecutionEnvironment.getExecutionEnvironment();
            streamExecEnv.setStreamTimeCharacteristic(TimeCharacteristic.IngestionTime);
            System.out.println("StockSymbolToPriceMapFunction: stockSymbol: " + stockSymbol);
    
            DataStream<String> stockPrices = streamExecEnv.addSource(new LookupStockPrice(stockSymbol));
            stockPrices.keyBy(new CustomKeySelector()).addSink(new FlinkKafkaProducer08<String>("localhost:9092", "stockprices", new SimpleStringSchema()));
    
            return "100000";
        }
    
        private static class CustomKeySelector implements KeySelector<String, String> {
            @Override
            public String getKey(String arg0) throws Exception {
                return arg0.trim();
            }
        }
    }
    
    
    public class LookupStockPrice extends RichSourceFunction<String> { 
        public String stockSymbol = null; 
        public boolean isRunning = true; 
    
        public LookupStockPrice(String inSymbol) { 
                stockSymbol = inSymbol; 
        } 
    
        @Override 
        public void open(Configuration parameters) throws Exception { 
                isRunning = true; 
        } 
    
    
        @Override 
        public void cancel() { 
                isRunning = false; 
        } 
    
        @Override 
        public void run(SourceFunction.SourceContext<String> ctx) 
                        throws Exception { 
                String stockPrice = "0";
                while (isRunning) { 
                    //TODO: query Google Finance API 
                    stockPrice = Integer.toString((new Random()).nextInt(100)+1);
                    ctx.collect(stockPrice);
                    Thread.sleep(10000);
                } 
        } 
    }
    
    公共类RetrieveStockPrices{
    @抑制警告(“串行”)
    公共静态void main(字符串[]args)引发异常{
    最终StreamExecutionEnvironment streamExecEnv=StreamExecutionEnvironment.getExecutionEnvironment();
    StreamXecenv.setStreamTimeCharacteristic(时间特征.摄取时间);
    属性=新属性();
    setProperty(“bootstrap.servers”,“localhost:9092”);
    setProperty(“zookeeper.connect”,“localhost:2181”);
    属性。setProperty(“group.id”、“股票”);
    DataStream streamOfStockSymbols=streamXecenv.addSource(新的FlinkKafkaConsumer08(“stocksymbol”,新的SimpleStringSchema(),属性));
    数据流股价=
    股票符号流
    //获取唯一密钥
    .keyBy(新的KeySelector(){
    @凌驾
    公共字符串getKey(字符串趋势)引发异常{
    回归趋势;
    }
    }) 
    //通过窗口收集事件
    .window(TumblingEventTimeWindows.of(时间秒(60)))
    //从窗口返回最后一个事件…所有元素都是相同的“符号”
    .apply(新的WindowFunction(){
    @凌驾
    public void apply(字符串键、时间窗口、Iterable输入、收集器输出)引发异常{
    out.collect(input.iterator().next().toString());
    }
    })
    .map(新的StockSymbolToPriceMapFunction());
    执行(“检索股票价格”);
    }
    }
    公共类StockSymbolToPriceMapFunction扩展了RichMapFunction{
    @凌驾
    公共字符串映射(字符串stockSymbol)引发异常{
    最终StreamExecutionEnvironment streamExecEnv=StreamExecutionEnvironment.getExecutionEnvironment();
    StreamXecenv.setStreamTimeCharacteristic(时间特征.摄取时间);
    System.out.println(“StockSymbolOpriceMapfunction:stockSymbol:”+stockSymbol);
    DataStream stockPrices=streamExecEnv.addSource(新lookupstockprices(stockSymbol));
    stockPrices.keyBy(新的CustomKeySelector()).addSink(新的flinkkapkaproducer08(“localhost:9092”,“stockPrices”,新的SimpleStringSchema());
    返回“100000”;
    }
    私有静态类CustomKeySelector实现KeySelector{
    @凌驾
    公共字符串getKey(字符串arg0)引发异常{
    返回arg0.trim();
    }
    }
    }
    公共类LookupStockPrice扩展了RichSourceFunction{
    公共字符串stockSymbol=null;
    公共布尔值isRunning=true;
    公共LookupStockPrice(字符串inSymbol){
    stockSymbol=inSymbol;
    } 
    @凌驾
    public void open(配置参数)引发异常{
    isRunning=true;
    } 
    @凌驾
    public void cancel(){
    isRunning=false;
    } 
    @凌驾
    公共无效运行(SourceFunction.SourceContext ctx)
    抛出异常{
    字符串stockPrice=“0”;
    当(正在运行时){
    //TODO:查询谷歌金融API
    股票价格=整数.toString((new Random()).nextInt(100)+1);
    ctx.托收(股票价格);
    睡眠(10000);
    } 
    } 
    }
    
    StreamExecutionEnvironment
    不缩进以在流媒体应用程序的操作员内部使用。非预期意味着,这不受测试和鼓励。它可能会工作并做一些事情,但很可能表现不好,可能会杀死您的应用程序

    程序中的
    stocksymboltopricemap函数
    为每个传入记录指定一个全新的独立流媒体应用程序。但是,由于不调用
    streamxecenv.execute()
    程序不会启动,
    map
    方法将返回,而不执行任何操作


    如果调用
    streamExecEnv.execute()
    ,该函数将在workers JVM中启动一个新的本地Flink群集,并在此本地Flink群集上启动应用程序。本地Flink实例将占用大量堆空间,在启动几个集群之后,工人可能会因为
    OutOfMemoryError
    而死亡,这不是您希望发生的。

    是否可以动态创建流以响应传入数据?您可以实现一个
    FlatMapFunction
    ,该函数根据到达的记录动态读取和发送数据。例如,如果您有一个具有文件名的流,则可以使用
    FlatMapFunction
    打开这些文件并发出它们的数据。但是,所有记录的输出类型必须相同。另外,正确处理事件时间语义可能是一个挑战,但这更像是动态添加源的一般问题。@FabianHueske我正在解决一个类似的用例。因此,如果我必须使用FlatMapFunction,那么我们必须使用scala/Java中的普通文件API读取文件,而不是使用Flink的readTextFile。原因是我们不能使用S