log4j.properties

log4j.rootLogger=warn, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.atguigu</groupId>
        <artifactId>bigdata230201</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>Flink</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <flink.version>1.17.0</flink.version>
    </properties>

    <!--
      依赖范围:
        1. compile(默认的) :  主程序和测试程序都可以用。  打包时会包含在内。
        2. test           :  测试程序可用。打包时会排除掉。
        3. provided       :  主程序和测试程序都可以用。 打包时会排除掉
                             只在编译期生效, 运行时不可用。

    -->


    <dependencies>
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-streaming-java</artifactId>
            <version>${flink.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-clients</artifactId>
            <version>${flink.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
            <scope>provided</scope>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>

        <!-- WEB UI -->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-runtime-web</artifactId>
            <version>${flink.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- DataGen connector-->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-datagen</artifactId>
            <version>${flink.version}</version>
        </dependency>

        <!-- file connector -->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-files</artifactId>
            <version>${flink.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- hadoop client -->
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>3.3.4</version>
            <scope>provided</scope>
        </dependency>

        <!-- kafka connector -->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-kafka</artifactId>
            <version>${flink.version}</version>
            <scope>provided</scope>
        </dependency>

        <!-- fastJson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>

        <!-- jdbc connector -->
        <dependency>
            <groupId>org.apache.flink</groupId>
            <artifactId>flink-connector-jdbc</artifactId>
            <version>3.1.0-1.17</version>
            <scope>provided</scope>
        </dependency>

        <!-- mysql connector -->
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <version>8.0.32</version>
            <scope>provided</scope>
        </dependency>


    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.4</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <artifactSet>
                                <excludes>
                                    <exclude>com.google.code.findbugs:jsr305</exclude>
                                    <exclude>org.slf4j:*</exclude>
                                    <exclude>log4j:*</exclude>
                                </excludes>
                            </artifactSet>
                            <filters>
                                <filter>
                                    <!-- Do not copy the signatures in the META-INF folder.
                                    Otherwise, this might cause SecurityExceptions when using the JAR. -->
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                            <transformers combine.children="append">
                                <transformer
                                        implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer">
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>


</project>
package com.atguigu.flink.func;

import com.atguigu.flink.pojo.Event;
import org.apache.flink.streaming.api.functions.source.SourceFunction;

import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * @author WEIYUNHUI
 * @date 2023/6/13 10:39
 * <p>
 * 自定义Source , 需要实现SourceFunction
 */
public class ClickSource implements SourceFunction<Event> {

    private static Boolean isRunning = true;

    /**
     * 每秒生成一条Event数据
     */
    @Override
    public void run(SourceContext<Event> ctx) throws Exception {
        String[] users = {"Zhangs", "Lisi", "Tom", "Jerry", "Peiqi"};
        String[] urls = {"/home", "/cart", "detail", "pay"};
        Random random = new Random();
        while (isRunning) {
            Event event =
                    new Event(users[random.nextInt(users.length)], urls[random.nextInt(urls.length)], System.currentTimeMillis());//System.currentTimeMillis()
            ctx.collect(event);
            //休眠1秒钟
            TimeUnit.SECONDS.sleep(1);
        }
    }

    @Override
    public void cancel() {
        isRunning = false;
    }
}
package com.atguigu.flink.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author WEIYUNHUI
 * @date 2023/6/13 10:40
 *
 * 封装用户点击事件(点击数据)
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Event {
    private String user ; // 用户
    private String url ; //点击的url
    private Long ts ; // 点击事件发生的时间
}
package com.atguigu.flink.timeAndwindow;

import com.atguigu.flink.func.ClickSource;
import com.atguigu.flink.pojo.Event;
import com.google.common.collect.Lists;
import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction;
import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.api.windowing.windows.TimeWindow;
import org.apache.flink.util.Collector;

import java.time.Duration;

/**
 * Created by  on 2023/6/18 0018 15:03
 *
 * @author 
 * 永远相信美好的事情总会发生.
 * <p>
 * 全窗口函数: 收集齐所有的数据后,统一计算一次输出结果。 可以获取到一些窗口相关的信息(窗口的起始和结束时间)
 * *   1. WindowFunction(过时)
 * *   2. ProcessWindowFunction
 */
public class Flink09_ProcessWindowFunction {

    public static void main(String[] args) throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        SingleOutputStreamOperator<Event> ds = env.addSource(new ClickSource())
                .assignTimestampsAndWatermarks(
                        WatermarkStrategy.<Event>forBoundedOutOfOrderness(Duration.ZERO)
                                .withTimestampAssigner(
                                        (event, ts) -> event.getTs()
                                )
                );
        ds.print("input");

        //需求: 每10秒统计每个user的点击次数 需要包含窗口信息
        //需求: 统计10秒内每个user的点击次数, 5秒输出一次结果。
        ds.map(
                event -> Tuple2.of(event.getUser(), 1)
        ).returns(
                Types.TUPLE(Types.STRING, Types.INT)
        ).keyBy(
                t -> t.f0
        ).window(
//                TumblingEventTimeWindows.of(Time.seconds(10))
                SlidingEventTimeWindows.of(Time.seconds(10),Time.seconds(5))
        ).process(
                new ProcessWindowFunction<Tuple2<String, Integer>, String, String, TimeWindow>() {


                    @Override
                    public void process(String key, ProcessWindowFunction<Tuple2<String, Integer>, String, String, TimeWindow>.Context context, Iterable<Tuple2<String, Integer>> elements, Collector<String> out) throws Exception {

                        //汇总每个user的点击次数
                        int count = Lists.newArrayList(elements).size();

                        //获取窗口的信息
                        long start = context.window().getStart();
                        long end = context.window().getEnd();

                        //输出
                        out.collect("窗口[ " + start + " ~ " + end + " ) , 用户 " + key + " 的点击次数为: " + count);

                    }
                }
        ).print();

        env.execute();

    }

}
input> Event(user=Zhangs, url=detail, ts=1687073571212)
input> Event(user=Jerry, url=/home, ts=1687073572217)
input> Event(user=Tom, url=detail, ts=1687073573218)
input> Event(user=Lisi, url=/cart, ts=1687073574218)
input> Event(user=Lisi, url=/home, ts=1687073575218)
窗口[ 1687073565000 ~ 1687073575000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073565000 ~ 1687073575000 ) , 用户 Jerry 的点击次数为: 1
窗口[ 1687073565000 ~ 1687073575000 ) , 用户 Lisi 的点击次数为: 1
窗口[ 1687073565000 ~ 1687073575000 ) , 用户 Tom 的点击次数为: 1
input> Event(user=Zhangs, url=pay, ts=1687073576219)
input> Event(user=Tom, url=/home, ts=1687073577219)
input> Event(user=Peiqi, url=pay, ts=1687073578220)
input> Event(user=Zhangs, url=/cart, ts=1687073579220)
input> Event(user=Lisi, url=/cart, ts=1687073580220)
窗口[ 1687073570000 ~ 1687073580000 ) , 用户 Jerry 的点击次数为: 1
窗口[ 1687073570000 ~ 1687073580000 ) , 用户 Zhangs 的点击次数为: 3
窗口[ 1687073570000 ~ 1687073580000 ) , 用户 Peiqi 的点击次数为: 1
窗口[ 1687073570000 ~ 1687073580000 ) , 用户 Tom 的点击次数为: 2
窗口[ 1687073570000 ~ 1687073580000 ) , 用户 Lisi 的点击次数为: 2
input> Event(user=Jerry, url=pay, ts=1687073581220)
input> Event(user=Peiqi, url=/home, ts=1687073582220)
input> Event(user=Tom, url=pay, ts=1687073583220)
input> Event(user=Peiqi, url=detail, ts=1687073584221)
input> Event(user=Jerry, url=pay, ts=1687073585221)
窗口[ 1687073575000 ~ 1687073585000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073575000 ~ 1687073585000 ) , 用户 Peiqi 的点击次数为: 3
窗口[ 1687073575000 ~ 1687073585000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073575000 ~ 1687073585000 ) , 用户 Tom 的点击次数为: 2
窗口[ 1687073575000 ~ 1687073585000 ) , 用户 Jerry 的点击次数为: 1
input> Event(user=Lisi, url=pay, ts=1687073586221)
input> Event(user=Tom, url=/cart, ts=1687073587222)
input> Event(user=Jerry, url=/home, ts=1687073588222)
input> Event(user=Jerry, url=/cart, ts=1687073589223)
input> Event(user=Peiqi, url=pay, ts=1687073590223)
窗口[ 1687073580000 ~ 1687073590000 ) , 用户 Jerry 的点击次数为: 4
窗口[ 1687073580000 ~ 1687073590000 ) , 用户 Tom 的点击次数为: 2
窗口[ 1687073580000 ~ 1687073590000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073580000 ~ 1687073590000 ) , 用户 Peiqi 的点击次数为: 2
input> Event(user=Zhangs, url=detail, ts=1687073591223)
input> Event(user=Peiqi, url=/cart, ts=1687073592224)
input> Event(user=Peiqi, url=detail, ts=1687073593225)
input> Event(user=Peiqi, url=/home, ts=1687073594226)
input> Event(user=Peiqi, url=/home, ts=1687073595226)
窗口[ 1687073585000 ~ 1687073595000 ) , 用户 Lisi 的点击次数为: 1
窗口[ 1687073585000 ~ 1687073595000 ) , 用户 Peiqi 的点击次数为: 4
窗口[ 1687073585000 ~ 1687073595000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073585000 ~ 1687073595000 ) , 用户 Jerry 的点击次数为: 3
窗口[ 1687073585000 ~ 1687073595000 ) , 用户 Tom 的点击次数为: 1
input> Event(user=Jerry, url=/cart, ts=1687073596227)
input> Event(user=Tom, url=pay, ts=1687073597227)
input> Event(user=Jerry, url=pay, ts=1687073598227)
input> Event(user=Lisi, url=/cart, ts=1687073599227)
input> Event(user=Lisi, url=detail, ts=1687073600228)
窗口[ 1687073590000 ~ 1687073600000 ) , 用户 Peiqi 的点击次数为: 5
窗口[ 1687073590000 ~ 1687073600000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073590000 ~ 1687073600000 ) , 用户 Lisi 的点击次数为: 1
窗口[ 1687073590000 ~ 1687073600000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073590000 ~ 1687073600000 ) , 用户 Tom 的点击次数为: 1
input> Event(user=Lisi, url=pay, ts=1687073601229)
input> Event(user=Zhangs, url=detail, ts=1687073602229)
input> Event(user=Tom, url=pay, ts=1687073603230)
input> Event(user=Lisi, url=/cart, ts=1687073604231)
input> Event(user=Zhangs, url=/cart, ts=1687073605232)
窗口[ 1687073595000 ~ 1687073605000 ) , 用户 Tom 的点击次数为: 2
窗口[ 1687073595000 ~ 1687073605000 ) , 用户 Lisi 的点击次数为: 4
窗口[ 1687073595000 ~ 1687073605000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073595000 ~ 1687073605000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073595000 ~ 1687073605000 ) , 用户 Peiqi 的点击次数为: 1
input> Event(user=Jerry, url=/home, ts=1687073606232)
input> Event(user=Jerry, url=/cart, ts=1687073607232)
input> Event(user=Peiqi, url=detail, ts=1687073608232)
input> Event(user=Zhangs, url=/home, ts=1687073609232)
input> Event(user=Jerry, url=detail, ts=1687073610234)
窗口[ 1687073600000 ~ 1687073610000 ) , 用户 Tom 的点击次数为: 1
窗口[ 1687073600000 ~ 1687073610000 ) , 用户 Lisi 的点击次数为: 3
窗口[ 1687073600000 ~ 1687073610000 ) , 用户 Peiqi 的点击次数为: 1
窗口[ 1687073600000 ~ 1687073610000 ) , 用户 Zhangs 的点击次数为: 3
窗口[ 1687073600000 ~ 1687073610000 ) , 用户 Jerry 的点击次数为: 2
input> Event(user=Peiqi, url=/cart, ts=1687073611234)
input> Event(user=Peiqi, url=pay, ts=1687073612235)
input> Event(user=Peiqi, url=detail, ts=1687073613235)
input> Event(user=Tom, url=/home, ts=1687073614236)
input> Event(user=Zhangs, url=/cart, ts=1687073615237)
窗口[ 1687073605000 ~ 1687073615000 ) , 用户 Jerry 的点击次数为: 3
窗口[ 1687073605000 ~ 1687073615000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073605000 ~ 1687073615000 ) , 用户 Peiqi 的点击次数为: 4
窗口[ 1687073605000 ~ 1687073615000 ) , 用户 Tom 的点击次数为: 1
input> Event(user=Jerry, url=detail, ts=1687073616237)
input> Event(user=Peiqi, url=detail, ts=1687073617238)
input> Event(user=Zhangs, url=/home, ts=1687073618238)
input> Event(user=Zhangs, url=detail, ts=1687073619239)
input> Event(user=Lisi, url=/home, ts=1687073620239)
窗口[ 1687073610000 ~ 1687073620000 ) , 用户 Zhangs 的点击次数为: 3
窗口[ 1687073610000 ~ 1687073620000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073610000 ~ 1687073620000 ) , 用户 Peiqi 的点击次数为: 4
窗口[ 1687073610000 ~ 1687073620000 ) , 用户 Tom 的点击次数为: 1
input> Event(user=Tom, url=/cart, ts=1687073621239)
input> Event(user=Peiqi, url=/home, ts=1687073622239)
input> Event(user=Tom, url=/cart, ts=1687073623240)
input> Event(user=Jerry, url=pay, ts=1687073624240)
input> Event(user=Jerry, url=detail, ts=1687073625240)
窗口[ 1687073615000 ~ 1687073625000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073615000 ~ 1687073625000 ) , 用户 Zhangs 的点击次数为: 3
窗口[ 1687073615000 ~ 1687073625000 ) , 用户 Lisi 的点击次数为: 1
窗口[ 1687073615000 ~ 1687073625000 ) , 用户 Peiqi 的点击次数为: 2
窗口[ 1687073615000 ~ 1687073625000 ) , 用户 Tom 的点击次数为: 2
input> Event(user=Lisi, url=detail, ts=1687073626240)
input> Event(user=Zhangs, url=/home, ts=1687073627241)
input> Event(user=Zhangs, url=/cart, ts=1687073628241)
input> Event(user=Lisi, url=/home, ts=1687073629241)
input> Event(user=Zhangs, url=/cart, ts=1687073630241)
窗口[ 1687073620000 ~ 1687073630000 ) , 用户 Tom 的点击次数为: 2
窗口[ 1687073620000 ~ 1687073630000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073620000 ~ 1687073630000 ) , 用户 Lisi 的点击次数为: 3
窗口[ 1687073620000 ~ 1687073630000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073620000 ~ 1687073630000 ) , 用户 Peiqi 的点击次数为: 1
input> Event(user=Jerry, url=detail, ts=1687073631242)
input> Event(user=Tom, url=/home, ts=1687073632242)
input> Event(user=Tom, url=/home, ts=1687073633243)
input> Event(user=Peiqi, url=/home, ts=1687073634243)
input> Event(user=Lisi, url=detail, ts=1687073635243)
窗口[ 1687073625000 ~ 1687073635000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073625000 ~ 1687073635000 ) , 用户 Zhangs 的点击次数为: 3
窗口[ 1687073625000 ~ 1687073635000 ) , 用户 Peiqi 的点击次数为: 1
窗口[ 1687073625000 ~ 1687073635000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073625000 ~ 1687073635000 ) , 用户 Tom 的点击次数为: 2
input> Event(user=Peiqi, url=/cart, ts=1687073636243)
input> Event(user=Jerry, url=detail, ts=1687073637244)
input> Event(user=Jerry, url=pay, ts=1687073638244)
input> Event(user=Lisi, url=/cart, ts=1687073639245)
input> Event(user=Tom, url=/cart, ts=1687073640246)
窗口[ 1687073630000 ~ 1687073640000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073630000 ~ 1687073640000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073630000 ~ 1687073640000 ) , 用户 Peiqi 的点击次数为: 2
窗口[ 1687073630000 ~ 1687073640000 ) , 用户 Jerry 的点击次数为: 3
窗口[ 1687073630000 ~ 1687073640000 ) , 用户 Tom 的点击次数为: 2
input> Event(user=Zhangs, url=/home, ts=1687073641246)
input> Event(user=Tom, url=pay, ts=1687073642246)
input> Event(user=Tom, url=pay, ts=1687073643247)
input> Event(user=Peiqi, url=detail, ts=1687073644247)
input> Event(user=Peiqi, url=/cart, ts=1687073645247)
窗口[ 1687073635000 ~ 1687073645000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073635000 ~ 1687073645000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073635000 ~ 1687073645000 ) , 用户 Tom 的点击次数为: 3
窗口[ 1687073635000 ~ 1687073645000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073635000 ~ 1687073645000 ) , 用户 Peiqi 的点击次数为: 2
input> Event(user=Lisi, url=/cart, ts=1687073646247)
input> Event(user=Jerry, url=pay, ts=1687073647247)
input> Event(user=Tom, url=pay, ts=1687073648247)
input> Event(user=Jerry, url=pay, ts=1687073649247)
input> Event(user=Peiqi, url=detail, ts=1687073650248)
窗口[ 1687073640000 ~ 1687073650000 ) , 用户 Tom 的点击次数为: 4
窗口[ 1687073640000 ~ 1687073650000 ) , 用户 Peiqi 的点击次数为: 2
窗口[ 1687073640000 ~ 1687073650000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073640000 ~ 1687073650000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073640000 ~ 1687073650000 ) , 用户 Lisi 的点击次数为: 1
input> Event(user=Peiqi, url=/home, ts=1687073651248)
input> Event(user=Zhangs, url=/cart, ts=1687073652249)
input> Event(user=Tom, url=pay, ts=1687073653249)
input> Event(user=Lisi, url=detail, ts=1687073654250)
input> Event(user=Lisi, url=/cart, ts=1687073655250)
窗口[ 1687073645000 ~ 1687073655000 ) , 用户 Tom 的点击次数为: 2
窗口[ 1687073645000 ~ 1687073655000 ) , 用户 Peiqi 的点击次数为: 3
窗口[ 1687073645000 ~ 1687073655000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073645000 ~ 1687073655000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073645000 ~ 1687073655000 ) , 用户 Zhangs 的点击次数为: 1
input> Event(user=Jerry, url=pay, ts=1687073656250)
input> Event(user=Zhangs, url=/home, ts=1687073657250)
input> Event(user=Zhangs, url=/cart, ts=1687073658250)
input> Event(user=Lisi, url=pay, ts=1687073659251)
input> Event(user=Jerry, url=/home, ts=1687073660251)
窗口[ 1687073650000 ~ 1687073660000 ) , 用户 Zhangs 的点击次数为: 3
窗口[ 1687073650000 ~ 1687073660000 ) , 用户 Lisi 的点击次数为: 3
窗口[ 1687073650000 ~ 1687073660000 ) , 用户 Peiqi 的点击次数为: 2
窗口[ 1687073650000 ~ 1687073660000 ) , 用户 Jerry 的点击次数为: 1
窗口[ 1687073650000 ~ 1687073660000 ) , 用户 Tom 的点击次数为: 1
input> Event(user=Tom, url=pay, ts=1687073661252)
input> Event(user=Peiqi, url=/cart, ts=1687073662252)
input> Event(user=Jerry, url=pay, ts=1687073663252)
input> Event(user=Jerry, url=/cart, ts=1687073664252)
input> Event(user=Zhangs, url=/home, ts=1687073665252)
窗口[ 1687073655000 ~ 1687073665000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073655000 ~ 1687073665000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073655000 ~ 1687073665000 ) , 用户 Peiqi 的点击次数为: 1
窗口[ 1687073655000 ~ 1687073665000 ) , 用户 Jerry 的点击次数为: 4
窗口[ 1687073655000 ~ 1687073665000 ) , 用户 Tom 的点击次数为: 1
input> Event(user=Peiqi, url=detail, ts=1687073666253)
input> Event(user=Jerry, url=/home, ts=1687073667253)
input> Event(user=Zhangs, url=/home, ts=1687073668253)
input> Event(user=Jerry, url=/cart, ts=1687073669253)
input> Event(user=Tom, url=/home, ts=1687073670253)
窗口[ 1687073660000 ~ 1687073670000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073660000 ~ 1687073670000 ) , 用户 Jerry 的点击次数为: 5
窗口[ 1687073660000 ~ 1687073670000 ) , 用户 Tom 的点击次数为: 1
窗口[ 1687073660000 ~ 1687073670000 ) , 用户 Peiqi 的点击次数为: 2
input> Event(user=Tom, url=/cart, ts=1687073671253)
input> Event(user=Lisi, url=/cart, ts=1687073672254)
input> Event(user=Jerry, url=/cart, ts=1687073673254)
input> Event(user=Tom, url=detail, ts=1687073674254)
input> Event(user=Peiqi, url=detail, ts=1687073675255)
窗口[ 1687073665000 ~ 1687073675000 ) , 用户 Peiqi 的点击次数为: 1
窗口[ 1687073665000 ~ 1687073675000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073665000 ~ 1687073675000 ) , 用户 Tom 的点击次数为: 3
窗口[ 1687073665000 ~ 1687073675000 ) , 用户 Jerry 的点击次数为: 3
窗口[ 1687073665000 ~ 1687073675000 ) , 用户 Lisi 的点击次数为: 1
input> Event(user=Peiqi, url=pay, ts=1687073676255)
input> Event(user=Jerry, url=detail, ts=1687073677255)
input> Event(user=Tom, url=/cart, ts=1687073678256)
input> Event(user=Peiqi, url=detail, ts=1687073679257)
input> Event(user=Lisi, url=detail, ts=1687073680257)
窗口[ 1687073670000 ~ 1687073680000 ) , 用户 Tom 的点击次数为: 4
窗口[ 1687073670000 ~ 1687073680000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073670000 ~ 1687073680000 ) , 用户 Peiqi 的点击次数为: 3
窗口[ 1687073670000 ~ 1687073680000 ) , 用户 Lisi 的点击次数为: 1
input> Event(user=Jerry, url=/home, ts=1687073681257)
input> Event(user=Jerry, url=detail, ts=1687073682258)
input> Event(user=Jerry, url=pay, ts=1687073683258)
input> Event(user=Zhangs, url=detail, ts=1687073684259)
input> Event(user=Zhangs, url=detail, ts=1687073685259)
窗口[ 1687073675000 ~ 1687073685000 ) , 用户 Jerry 的点击次数为: 4
窗口[ 1687073675000 ~ 1687073685000 ) , 用户 Peiqi 的点击次数为: 3
窗口[ 1687073675000 ~ 1687073685000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073675000 ~ 1687073685000 ) , 用户 Lisi 的点击次数为: 1
窗口[ 1687073675000 ~ 1687073685000 ) , 用户 Tom 的点击次数为: 1
input> Event(user=Zhangs, url=/home, ts=1687073686259)
input> Event(user=Peiqi, url=/cart, ts=1687073687259)
input> Event(user=Zhangs, url=pay, ts=1687073688259)
input> Event(user=Zhangs, url=/home, ts=1687073689260)
input> Event(user=Lisi, url=/home, ts=1687073690260)
窗口[ 1687073680000 ~ 1687073690000 ) , 用户 Zhangs 的点击次数为: 5
窗口[ 1687073680000 ~ 1687073690000 ) , 用户 Lisi 的点击次数为: 1
窗口[ 1687073680000 ~ 1687073690000 ) , 用户 Jerry 的点击次数为: 3
窗口[ 1687073680000 ~ 1687073690000 ) , 用户 Peiqi 的点击次数为: 1
input> Event(user=Zhangs, url=pay, ts=1687073691261)
input> Event(user=Jerry, url=/home, ts=1687073692262)
input> Event(user=Lisi, url=detail, ts=1687073693263)
input> Event(user=Zhangs, url=/cart, ts=1687073694263)
input> Event(user=Lisi, url=detail, ts=1687073695263)
窗口[ 1687073685000 ~ 1687073695000 ) , 用户 Peiqi 的点击次数为: 1
窗口[ 1687073685000 ~ 1687073695000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073685000 ~ 1687073695000 ) , 用户 Zhangs 的点击次数为: 6
窗口[ 1687073685000 ~ 1687073695000 ) , 用户 Jerry 的点击次数为: 1
input> Event(user=Jerry, url=detail, ts=1687073696263)
input> Event(user=Peiqi, url=/home, ts=1687073697263)
input> Event(user=Lisi, url=/cart, ts=1687073698264)
input> Event(user=Peiqi, url=pay, ts=1687073699264)
input> Event(user=Jerry, url=/home, ts=1687073700265)
窗口[ 1687073690000 ~ 1687073700000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073690000 ~ 1687073700000 ) , 用户 Lisi 的点击次数为: 4
窗口[ 1687073690000 ~ 1687073700000 ) , 用户 Peiqi 的点击次数为: 2
窗口[ 1687073690000 ~ 1687073700000 ) , 用户 Jerry 的点击次数为: 2
input> Event(user=Tom, url=detail, ts=1687073701265)
input> Event(user=Jerry, url=/cart, ts=1687073702265)
input> Event(user=Jerry, url=pay, ts=1687073703266)
input> Event(user=Zhangs, url=/home, ts=1687073704266)
input> Event(user=Tom, url=/cart, ts=1687073705267)
窗口[ 1687073695000 ~ 1687073705000 ) , 用户 Jerry 的点击次数为: 4
窗口[ 1687073695000 ~ 1687073705000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073695000 ~ 1687073705000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073695000 ~ 1687073705000 ) , 用户 Peiqi 的点击次数为: 2
窗口[ 1687073695000 ~ 1687073705000 ) , 用户 Tom 的点击次数为: 1
input> Event(user=Jerry, url=pay, ts=1687073706267)
input> Event(user=Lisi, url=detail, ts=1687073707267)
input> Event(user=Tom, url=/home, ts=1687073708268)
input> Event(user=Zhangs, url=/home, ts=1687073709268)
input> Event(user=Jerry, url=pay, ts=1687073710269)
窗口[ 1687073700000 ~ 1687073710000 ) , 用户 Tom 的点击次数为: 3
窗口[ 1687073700000 ~ 1687073710000 ) , 用户 Jerry 的点击次数为: 4
窗口[ 1687073700000 ~ 1687073710000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073700000 ~ 1687073710000 ) , 用户 Lisi 的点击次数为: 1
input> Event(user=Lisi, url=/home, ts=1687073711269)
input> Event(user=Zhangs, url=/home, ts=1687073712270)
input> Event(user=Tom, url=/home, ts=1687073713271)
input> Event(user=Peiqi, url=/home, ts=1687073714272)
input> Event(user=Jerry, url=/home, ts=1687073715272)
窗口[ 1687073705000 ~ 1687073715000 ) , 用户 Tom 的点击次数为: 3
窗口[ 1687073705000 ~ 1687073715000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073705000 ~ 1687073715000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073705000 ~ 1687073715000 ) , 用户 Peiqi 的点击次数为: 1
窗口[ 1687073705000 ~ 1687073715000 ) , 用户 Lisi 的点击次数为: 2
input> Event(user=Lisi, url=detail, ts=1687073716273)
input> Event(user=Zhangs, url=/home, ts=1687073717273)
input> Event(user=Peiqi, url=pay, ts=1687073718273)
input> Event(user=Tom, url=/home, ts=1687073719274)
input> Event(user=Tom, url=/home, ts=1687073720274)
窗口[ 1687073710000 ~ 1687073720000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073710000 ~ 1687073720000 ) , 用户 Peiqi 的点击次数为: 2
窗口[ 1687073710000 ~ 1687073720000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073710000 ~ 1687073720000 ) , 用户 Tom 的点击次数为: 2
窗口[ 1687073710000 ~ 1687073720000 ) , 用户 Lisi 的点击次数为: 2
input> Event(user=Peiqi, url=pay, ts=1687073721275)
input> Event(user=Jerry, url=detail, ts=1687073722276)
input> Event(user=Tom, url=/home, ts=1687073723276)
input> Event(user=Lisi, url=/home, ts=1687073724276)
input> Event(user=Zhangs, url=/cart, ts=1687073725277)
窗口[ 1687073715000 ~ 1687073725000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073715000 ~ 1687073725000 ) , 用户 Tom 的点击次数为: 3
窗口[ 1687073715000 ~ 1687073725000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073715000 ~ 1687073725000 ) , 用户 Jerry 的点击次数为: 2
窗口[ 1687073715000 ~ 1687073725000 ) , 用户 Peiqi 的点击次数为: 2
input> Event(user=Peiqi, url=detail, ts=1687073726278)
input> Event(user=Peiqi, url=pay, ts=1687073727278)
input> Event(user=Lisi, url=/home, ts=1687073728278)
input> Event(user=Tom, url=detail, ts=1687073729278)
input> Event(user=Lisi, url=detail, ts=1687073730280)
窗口[ 1687073720000 ~ 1687073730000 ) , 用户 Peiqi 的点击次数为: 3
窗口[ 1687073720000 ~ 1687073730000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073720000 ~ 1687073730000 ) , 用户 Zhangs 的点击次数为: 1
窗口[ 1687073720000 ~ 1687073730000 ) , 用户 Jerry 的点击次数为: 1
窗口[ 1687073720000 ~ 1687073730000 ) , 用户 Tom 的点击次数为: 3
input> Event(user=Zhangs, url=/cart, ts=1687073731280)
input> Event(user=Peiqi, url=/home, ts=1687073732280)
input> Event(user=Zhangs, url=pay, ts=1687073733281)
input> Event(user=Zhangs, url=/cart, ts=1687073734281)
input> Event(user=Tom, url=detail, ts=1687073735281)
窗口[ 1687073725000 ~ 1687073735000 ) , 用户 Tom 的点击次数为: 1
窗口[ 1687073725000 ~ 1687073735000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073725000 ~ 1687073735000 ) , 用户 Zhangs 的点击次数为: 4
窗口[ 1687073725000 ~ 1687073735000 ) , 用户 Peiqi 的点击次数为: 3
input> Event(user=Zhangs, url=detail, ts=1687073736282)
input> Event(user=Zhangs, url=/home, ts=1687073737283)
input> Event(user=Lisi, url=pay, ts=1687073738283)
input> Event(user=Jerry, url=pay, ts=1687073739283)
input> Event(user=Peiqi, url=pay, ts=1687073740284)
窗口[ 1687073730000 ~ 1687073740000 ) , 用户 Zhangs 的点击次数为: 5
窗口[ 1687073730000 ~ 1687073740000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073730000 ~ 1687073740000 ) , 用户 Jerry 的点击次数为: 1
窗口[ 1687073730000 ~ 1687073740000 ) , 用户 Tom 的点击次数为: 1
窗口[ 1687073730000 ~ 1687073740000 ) , 用户 Peiqi 的点击次数为: 1
input> Event(user=Peiqi, url=detail, ts=1687073741284)
input> Event(user=Jerry, url=pay, ts=1687073742284)
input> Event(user=Lisi, url=/cart, ts=1687073743284)
input> Event(user=Jerry, url=detail, ts=1687073744284)
input> Event(user=Peiqi, url=detail, ts=1687073745285)
窗口[ 1687073735000 ~ 1687073745000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073735000 ~ 1687073745000 ) , 用户 Tom 的点击次数为: 1
窗口[ 1687073735000 ~ 1687073745000 ) , 用户 Peiqi 的点击次数为: 2
窗口[ 1687073735000 ~ 1687073745000 ) , 用户 Jerry 的点击次数为: 3
窗口[ 1687073735000 ~ 1687073745000 ) , 用户 Zhangs 的点击次数为: 2
input> Event(user=Zhangs, url=/cart, ts=1687073746285)
input> Event(user=Jerry, url=detail, ts=1687073747286)
input> Event(user=Peiqi, url=detail, ts=1687073748286)
input> Event(user=Tom, url=pay, ts=1687073749287)
input> Event(user=Zhangs, url=detail, ts=1687073750287)
窗口[ 1687073740000 ~ 1687073750000 ) , 用户 Peiqi 的点击次数为: 4
窗口[ 1687073740000 ~ 1687073750000 ) , 用户 Lisi 的点击次数为: 1
窗口[ 1687073740000 ~ 1687073750000 ) , 用户 Tom 的点击次数为: 1
窗口[ 1687073740000 ~ 1687073750000 ) , 用户 Jerry 的点击次数为: 3
窗口[ 1687073740000 ~ 1687073750000 ) , 用户 Zhangs 的点击次数为: 1
input> Event(user=Lisi, url=detail, ts=1687073751287)
input> Event(user=Peiqi, url=/home, ts=1687073752288)
input> Event(user=Tom, url=/home, ts=1687073753288)
input> Event(user=Tom, url=/home, ts=1687073754288)
input> Event(user=Zhangs, url=detail, ts=1687073755289)
窗口[ 1687073745000 ~ 1687073755000 ) , 用户 Peiqi 的点击次数为: 3
窗口[ 1687073745000 ~ 1687073755000 ) , 用户 Tom 的点击次数为: 3
窗口[ 1687073745000 ~ 1687073755000 ) , 用户 Zhangs 的点击次数为: 2
窗口[ 1687073745000 ~ 1687073755000 ) , 用户 Jerry 的点击次数为: 1
窗口[ 1687073745000 ~ 1687073755000 ) , 用户 Lisi 的点击次数为: 1
input> Event(user=Zhangs, url=/home, ts=1687073756290)
input> Event(user=Tom, url=pay, ts=1687073757290)
input> Event(user=Zhangs, url=/cart, ts=1687073758290)
input> Event(user=Lisi, url=detail, ts=1687073759290)
input> Event(user=Tom, url=detail, ts=1687073760290)
窗口[ 1687073750000 ~ 1687073760000 ) , 用户 Lisi 的点击次数为: 2
窗口[ 1687073750000 ~ 1687073760000 ) , 用户 Tom 的点击次数为: 3
窗口[ 1687073750000 ~ 1687073760000 ) , 用户 Zhangs 的点击次数为: 4
窗口[ 1687073750000 ~ 1687073760000 ) , 用户 Peiqi 的点击次数为: 1

数据第一次来,5秒滑动一次,底层源码经过计算,571+5=576,取整得575,所以第一次的窗口为565-575,当事件时间到575的时候,触发计算,计算565-575窗口的数据;

5秒滑动一次,下一个窗口是570-580,当事件时间到580的时候,触发计算,计算570-580窗口的数据;

依次类推。。。

可以看到,第一个窗口计算的时候,565到570是没有数据的,所以第一个窗口只计算了571到575的数据;

第二个窗口虽然是570-580,但是只计算了571到580的数据;

之后的窗口就可以计算完整的数据了

Flink-滑动窗口-时间

flink 滑动窗口应用场景_算法


Flink-滑动窗口-计数

flink 滑动窗口应用场景_flink_02

事实上“触发计算”和“窗口关闭”两个行为也可以分开

flink 滑动窗口应用场景_flink 滑动窗口应用场景_03