大数据学习之Flink基础

news2024/11/12 7:04:30

Flink基础

1、系统时间与时间时间

系统时间(处理时间)

在Sparksreaming的任务计算时,使用的是系统时间。

假设所用窗口为滚动窗口,大小为5分钟。那么每五分钟,都会对接收的数据进行提交任务.

但是,这里有个要注意的点,有个概念叫时间轴对齐。若我们在12:12开始接收数据,按道理我们会在12:17进行提交任务。事实上我们会在12:20进行提交任务,因为会进行时间轴对齐,将一天按照五分钟进行划分,会对应到12:20。在此时提交任务,后面每个五分钟提交任务,都会对应到我们所划分的时间轴。

事件时间

flink支持带有事件时间的窗口(Window)操作

事件时间区别于系统时间,如下举例:

flink处理实时数据,对数据进行逐条处理。设定事件时间为5分钟,12:00开始接收数据,接收的第一条数据时间为12:01,接收的第二条数据为12:02。假设从此时起没有收到数据,那么将不会进行提交任务。**到了12:06,接收到了第三条数据。第三条数据的接收时间自12:00起,已经超过了五分钟,**那么此时便会进行任务提交。

2、wordcount简单案例的实现
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;

public class Demo01StreamWordCount {
    public static void main(String[] args) throws Exception {
        // 1、构建Flink环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment
                .getExecutionEnvironment();

        // 2、通过Socket模拟无界流环境,方便FLink处理
        // 虚拟机启动:nc -lk 8888
        // 从Source构建第一个DataStream
        // TODO C:\Windows\System32\drivers\etc\hosts文件中配置了master与IP地址的映射,所以这里可以使用master
        DataStream<String> lineDS = env.socketTextStream("master", 8888);

        // 统计每个单词的数量
        // 第一步:将每行数据的每个单词切出来并进行扁平化处理
        DataStream<String> wordsDS = lineDS.flatMap(new FlatMapFunction<String, String>() {
            /**
             *FlatMapFunction<String, String>: 表示输入、输出数据的类型
             * @param line DS中的一条数据
             * @param out 通过collect方法将数据发送到下游
             * @throws Exception
             */
            @Override
            public void flatMap(String line, Collector<String> out) throws Exception {
                for (String word : line.split(",")) {
                    // 将每个单词发送到下游
                    out.collect(word);
                }
            }
        });

        // 第二步:将每个单词变成 KV格式,V置为1;返回的数据是一个二元组Tuple2
        DataStream<Tuple2<String, Integer>> wordKVDS = wordsDS.map(new MapFunction<String, Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> map(String word) throws Exception {
                return Tuple2.of(word, 1);
            }
        });

        /**
         * 第三步:按每一个单词进行分组; 无法再使用其父类DataStream进行定义(无法向上转型)
         * KeyedStream<T, K> 是 DataStream<T> 的一个特殊化版本,它添加了与键控操作相关的特定方法(如 reduce、aggregate、window 等)。
         * 由于 KeyedStream 提供了额外的功能和方法,它不能简单地被视为 DataStream 的一个简单实例,
         * 因为它实现了额外的接口(如 KeyedOperations<T, K>)并可能覆盖了某些方法的行为以支持键控操作。
         */
        KeyedStream<Tuple2<String, Integer>, String> keyedDS = wordKVDS.keyBy(new KeySelector<Tuple2<String, Integer>, String>() {
            @Override
            public String getKey(Tuple2<String, Integer> tuple2) throws Exception {
                // 对Key进行分组
                return tuple2.f0;
            }
        });
        // 第四步:对1进行聚合sum,下标是从0开始的
        DataStream<Tuple2<String, Integer>> wordCntDS = keyedDS.sum(1);

        // 3、打印结果:将DS中的内容Sink到控制台
        wordCntDS.print();

        // 执行任务
        env.execute();
    }
}
3、设置任务执行的并行度

本机为8核,可并行16的线程

手动改变任务的并行度,若不设置则会显示1-16,设置后只会显示1-2
env.setParallelism(2);
setBufferTimeout():设置输出缓冲区刷新的最大时间频率(毫秒)。
env.setBufferTimeout(200);

import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;

public class Demo01StreamWordCount {
    public static void main(String[] args) throws Exception {
        // 1、构建Flink环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment
                .getExecutionEnvironment();
        // 手动改变任务的并行度,默认并行度为最大,
        env.setParallelism(2);
        // setBufferTimeout():设置输出缓冲区刷新的最大时间频率(毫秒)。
        env.setBufferTimeout(200);

        // 2、通过Socket模拟无界流环境,方便FLink处理
        // 虚拟机启动:nc -lk 8888
        // 从Source构建第一个DataStream
        DataStream<String> lineDS = env.socketTextStream("master", 8888);
        System.out.println("lineDS并行度:" + lineDS.getParallelism());

        // 统计每个单词的数量
        // 第一步:将每行数据的每个单词切出来并进行扁平化处理
        DataStream<String> wordsDS = lineDS.flatMap(new FlatMapFunction<String, String>() {
            /**
             *
             * @param line DS中的一条数据
             * @param out 通过collect方法将数据发送到下游
             * @throws Exception
             */
            @Override
            public void flatMap(String line, Collector<String> out) throws Exception {
                for (String word : line.split(",")) {
                    // 将每个单词发送到下游
                    out.collect(word);
                }
            }
        });
        System.out.println("wordsDS并行度:" + wordsDS.getParallelism());

        // 第二步:将每个单词变成 KV格式,V置为1
        DataStream<Tuple2<String, Integer>> wordKVDS = wordsDS.map(new MapFunction<String, Tuple2<String, Integer>>() {
            @Override
            public Tuple2<String, Integer> map(String word) throws Exception {
                return Tuple2.of(word, 1);
            }
        });
        System.out.println("wordKVDS并行度:" + wordKVDS.getParallelism());

        // 第三步:按每一个单词进行分组
        // keyBy之后数据流会进行分组,相同的key会进入同一个线程中被处理
        // 传递数据的规则:hash取余(线程总数,默认CPU的总线程数)原理
        KeyedStream<Tuple2<String, Integer>, String> keyedDS = wordKVDS.keyBy(new KeySelector<Tuple2<String, Integer>, String>() {
            @Override
            public String getKey(Tuple2<String, Integer> tuple2) throws Exception {
                return tuple2.f0;
            }
        });
        System.out.println("keyedDS并行度:" + keyedDS.getParallelism());

        // 第四步:对1进行聚合sum
        DataStream<Tuple2<String, Integer>> wordCntDS = keyedDS.sum(1);
        System.out.println("wordCntDS并行度:" + wordCntDS.getParallelism());
        // 3、打印结果:将DS中的内容Sink到控制台
        keyedDS.print();

        env.execute();

    }
}

在这里插入图片描述

4、设置批/流处理方式,使用Lambda表达式,使用自定类实现接口中抽象的方法
package com.shujia.flink.core;

import org.apache.flink.api.common.RuntimeExecutionMode;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
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.util.Collector;

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

        // 1、构建环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 设置Flink程序的处理方式:默认是流处理
        /**
         * BATCH:批处理,只能处理有界流,底层是MR模型,可以进行预聚合
         * STREAMING:流处理,可以处理无界流,也可以处理有界流,底层是持续流模型,数据一条一条处理
         * AUTOMATIC:自动判断,当所有的Source都是有界流则使用BATCH模式,当Source中有一个是无界流则会使用STREAMING模式
         */
        env.setRuntimeMode(RuntimeExecutionMode.BATCH);

        // 2、获得第一个DS
        // 通过readTextFile可以基于文件构建有界流
        DataStream<String> wordsFileDS = env.readTextFile("flink/data/words.txt");

        // 3、DS之间的转换
        // 统计每个单词的数量
        // 第一步:将每行数据的每个单词切出来并进行扁平化处理

        // Flink处理逻辑传入的方式
        // new XXXFunction 使用匿名内部类
//        DataStream<String> wordsDS = wordsFileDS.flatMap(new FlatMapFunction<String, String>() {
//            /**
//             * @param line DS中的一条数据
//             * @param out 通过collect方法将数据发送到下游
//             * @throws Exception
//             * Type parameters:
//             * FlatMapFunction<T, O>
//             * <T> – Type of the input elements. <O> – Type of the returned elements.
//             */
//            @Override
//            public void flatMap(String line, Collector<String> out) throws Exception {
//                for (String word : line.split(",")) {
//                    // 将每个单词发送到下游
//                    out.collect(word);
//                }
//            }
//        });

        /**
         * 使用Lambda表达式
         * 使用时得清楚FlatMapFunction中所要实现的抽象方法flatMap的两个参数的含义
         * ()->{}
         *  通过 -> 分隔,左边是函数的参数,右边是函数实现的具体逻辑
         *  并且需要给出 flatMap函数的输出类型,Types.STRING
         *  line: 输入数据类型, out: 输出数据类型
         */
        DataStream<String> wordsDS = wordsFileDS.flatMap((line, out) -> {
            for (String word : line.split(",")) {
                out.collect(word);
            }
        }, Types.STRING);


        //TODO 使用自定类实现接口中抽象的方法,一般不使用这种方法
        wordsFileDS.flatMap(new MyFunction()).print();

        // 第二步:将每个单词变成 KV格式,V置为1
//        DataStream<Tuple2<String, Integer>> wordKVDS = wordsDS.map(new MapFunction<String, Tuple2<String, Integer>>() {
//            @Override
//            public Tuple2<String, Integer> map(String word) throws Exception {
//                return Tuple2.of(word, 1);
//            }
//        });

        // TODO 此处需要给出 map函数的输出类型,Types.TUPLE(Types.STRING, Types.INT),是一个二元组
        DataStream<Tuple2<String, Integer>> wordKVDS = wordsDS.map(word -> Tuple2.of(word, 1), Types.TUPLE(Types.STRING, Types.INT));


        /**
         * 第三步:按每一个单词进行分组
         *    keyBy之后数据流会进行分组,相同的key会进入同一个线程中被处理
         *    传递数据的规则:hash取余(线程总数,默认CPU的总线程数,本机为16)原理
         */
//        KeyedStream<Tuple2<String, Integer>, String> keyedDS = wordKVDS.keyBy(new KeySelector<Tuple2<String, Integer>, String>() {
//            @Override
//            public String getKey(Tuple2<String, Integer> tuple2) throws Exception {
//                return tuple2.f0;
//            }
//        });


        // TODO 此处的Types.STRING 并不是直接表示某个方法的输出类型,而是用来指定 keyBy 方法中键(key)的类型。这里可以省略!
        KeyedStream<Tuple2<String, Integer>, String> keyedDS = wordKVDS.keyBy(kv -> kv.f0, Types.STRING);
        // 第四步:对1进行聚合sum,无需指定返回值类型
        DataStream<Tuple2<String, Integer>> wordCntDS = keyedDS.sum(1);

        // 4、最终结果的处理(保存/输出打印)
        wordCntDS.print();

        env.execute();

    }
}

class MyFunction implements FlatMapFunction<String,String>{

    @Override
    public void flatMap(String line, Collector<String> out) throws Exception {
        for (String word : line.split(",")) {
                    // 将每个单词发送到下游
                    out.collect(word);
                }
    }
}
5、source
1、从本地集合source中读取数据
package com.shujia.flink.source;

import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import java.util.ArrayList;

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

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // 本地集合Source
        ArrayList<String> arrList = new ArrayList<>();
        arrList.add("flink");
        arrList.add("flink");
        arrList.add("flink");
        arrList.add("flink");

        //TODO 有界流,fromCollection
        DataStream<String> listDS = env.fromCollection(arrList);
        listDS.print();

        env.execute();
    }
}
2、新版本从本地文件中读取数据,有界流和无界流两种方式
package com.shujia.flink.source;

import org.apache.flink.api.common.eventtime.WatermarkStrategy;
import org.apache.flink.connector.file.src.FileSource;
import org.apache.flink.connector.file.src.reader.TextLineInputFormat;
import org.apache.flink.core.fs.Path;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;

import java.io.File;
import java.time.Duration;

public class Demo02FileSource {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        //TODO 历史版本读文件的方式,有界流
        DataStream<String> oldFileDS = env.readTextFile("flink/data/words.txt");
//        oldFileDS.print();

        //TODO 读取案例一: 新版本加载文件的方式:FileSource,默认是有界流
        FileSource<String> fileSource = FileSource
                .forRecordStreamFormat(
                        new TextLineInputFormat()
                        , new Path("flink/data/words.txt")
                )
                .build();
        
        //TODO 从Source加载数据构建DS,使用自带source类,使用 fromSource
        DataStream<String> fileSourceDS = env.fromSource(fileSource, WatermarkStrategy.noWatermarks(), "fileSource");
        fileSourceDS.print();

        //TODO 读取案例二: 将读取文件变成无界流
        FileSource<String> fileSource2 = FileSource
                .forRecordStreamFormat(
                        new TextLineInputFormat()
                        , new Path("flink/data/words")
                )
                //TODO 使成为无界流读取一个文件夹中的数据,类似Flume中的spool dir,可以监控一个目录下文件的变化
                // Duration.ofSeconds(5) 以5秒为间隔持续监控
                .monitorContinuously(Duration.ofSeconds(5))
                .build();

        DataStream<String> fileSourceDS2 = env.fromSource(fileSource2,WatermarkStrategy.noWatermarks(),"fileSource2");
        fileSourceDS2.print();
        env.execute();

    }
}
3、自定义source类,区分有界流与无界流
  • 只有在Source启动时会执行一次
  • run方法如果会结束,则Source会得到一个有界流
    
  • run方法如果不会结束,则Source会得到一个无界流
    
package com.shujia.flink.source;

import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;

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

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        // TODO 使用自定义source类,通过addSource对其进行添加
        DataStream<String> mySourceDS = env.addSource(new MySource());
        mySourceDS.print();

        env.execute();
        
    }
}


class MySource implements SourceFunction<String>{

    /**
     * 只有在Source启动时会执行一次
     *     run方法如果会结束,则Source会得到一个有界流
     *     run方法如果不会结束,则Source会得到一个无界流
     *  下面的例子Source会得到一个无界流
     */
    @Override
    public void run(SourceContext<String> ctx) throws Exception {
        System.out.println("run方法启动了");
        // ctx 可以通过collect方法向下游发送数据
        long cnt = 0L;
        while(true){
            ctx.collect(cnt+"");
            cnt ++;
            // 休眠一会
            Thread.sleep(1000);
        }


    }

    // Source结束时会执行
    @Override
    public void cancel() {
        System.out.println("Source结束了");

    }
}
4、自定义source类,读取MySQL中的数据,并进行处理
package com.shujia.flink.source;

import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Demo04MyMySQLSource {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStream<Students> studentDS = env.addSource(new MyMySQLSource());

        // 统计班级人数
        DataStream<Tuple2<String, Integer>> clazzCntDS = studentDS
                .map(stu -> Tuple2.of(stu.clazz, 1), Types.TUPLE(Types.STRING, Types.INT))
                .keyBy(t2 -> t2.f0)
                .sum(1);
        clazzCntDS.print();

        // 统计性别人数
        DataStream<Tuple2<String, Integer>> genderCntDS = studentDS
                .map(stu -> Tuple2.of(stu.gender, 1), Types.TUPLE(Types.STRING, Types.INT))
                .keyBy(t2 -> t2.f0)
                .sum(1);
        genderCntDS.print();

        env.execute();

    }
}

// TODO 自定义source类从MySQL中读取数据
class MyMySQLSource implements SourceFunction<Students> {

    @Override
    public void run(SourceContext<Students> ctx) throws Exception {
        //TODO run方法只会执行一次创建下列对象的操作
        // 建立连接
        Connection conn = DriverManager.getConnection("jdbc:mysql://master:3306/bigdata_30", "root", "123456");
        // 创建Statement
        Statement st = conn.createStatement();
        // 执行查询
        ResultSet rs = st.executeQuery("select * from students2");
        // 遍历rs提取每一条数据
        while (rs.next()) {
            long id = rs.getLong("id");
            String name = rs.getString("name");
            int age = rs.getInt("age");
            String gender = rs.getString("gender");
            String clazz = rs.getString("clazz");

            Students stu = new Students(id, name, age, gender, clazz);
            ctx.collect(stu);

            /**
             * 16> (文科四班,1)
             * 15> (女,1)
             * 15> (女,2)
             * 2> (男,1)
             * 7> (文科六班,1)
             * 15> (女,3)
             * 2> (男,2)
             * 17> (理科六班,1)
             * 17> (理科六班,2)
             * 13> (理科五班,1)
             * 20> (理科二班,1)
             * 13> (理科四班,1)
             */
        }

        rs.close();
        st.close();
        conn.close();
    }

    @Override
    public void cancel() {

    }
}

// TODO 创建一个类,用于存储从MySQL中取出的数据
class Students {
    Long id;
    String name;
    Integer age;
    String gender;
    String clazz;

    public Students(Long id, String name, Integer age, String gender, String clazz) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.gender = gender;
        this.clazz = clazz;
    }
}
6、sink
1、构建FileSink,监控一个端口中的数据并将其写入到本地文件夹中
package com.shujia.flink.sink;

import org.apache.flink.api.common.serialization.SimpleStringEncoder;
import org.apache.flink.configuration.MemorySize;
import org.apache.flink.connector.file.sink.FileSink;
import org.apache.flink.core.fs.Path;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.sink.filesystem.rollingpolicies.DefaultRollingPolicy;

import java.time.Duration;
public class Demo01FileSink {
    public static void main(String[] args) throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStreamSource<String> lineDS = env.socketTextStream("master", 8888);

        // 构建FileSink
        FileSink<String> fileSink = FileSink
                .<String>forRowFormat(new Path("flink/data/fileSink"), new SimpleStringEncoder<String>("UTF-8"))
                .withRollingPolicy(
                        DefaultRollingPolicy.builder()
                                // 这个设置定义了滚动的时间间隔。
                                .withRolloverInterval(Duration.ofSeconds(10))
                                // 这个设置定义了一个不活动间隔。
                                .withInactivityInterval(Duration.ofSeconds(10))
                                // 这个设置定义了单个日志文件可以增长到的最大大小。在这个例子中,每个日志文件在被滚动之前可以增长到最多1MB。
                                .withMaxPartSize(MemorySize.ofMebiBytes(1))
                                .build())
                .build();


        lineDS.sinkTo(fileSink);
        env.execute();

    }
}
2、自定义sink类
package com.shujia.flink.sink;

import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.sink.SinkFunction;

import java.util.ArrayList;

public class Demo02MySink {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        ArrayList<String> arrList = new ArrayList<>();
        arrList.add("flink");
        arrList.add("flink");
        arrList.add("flink");
        arrList.add("flink");
        DataStreamSource<String> ds = env.fromCollection(arrList);

        ds.addSink(new MySinkFunction());

        env.execute();

        /**
         * 进入了invoke方法
         * flink
         * 进入了invoke方法
         * flink
         * 进入了invoke方法
         * flink
         * 进入了invoke方法
         * flink
         */

    }
}

class MySinkFunction implements SinkFunction<String>{

    @Override
    public void invoke(String value, Context context) throws Exception {
        System.out.println("进入了invoke方法");
        // invoke 每一条数据会执行一次
        // 最终数据需要sink到哪里,就对value进行处理即可
        System.out.println(value);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1952253.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习的前沿主题:GANs、自监督学习和Transformer模型

&#x1f48e; 欢迎大家互三&#xff1a;2的n次方_ &#x1f48e;1. 介绍 深度学习在人工智能领域中占据了重要地位&#xff0c;特别是生成对抗网络&#xff08;GANs&#xff09;、自监督学习和Transformer模型的出现&#xff0c;推动了图像生成、自然语言处理等多个领域的创…

AI跟踪报道第49期-新加坡内哥谈技术-本周AI新闻: 开源AI王者归来的一周

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

杭州社保卡办理-农业银行版本

step 1、杭州滨江高新支行 被告知只能工作日办理&#xff08;由于工作时间冲突&#xff0c;办理不了&#xff09; 询问哪个支行可以办&#xff0c;回答说不知道&#xff0c;让我自己去问。银行服务态度较差。 step 2、杭州滨江江南支行 市民卡显示这家&#xff0c;周六可以…

QT开发(QT的基本概述和环境的安装)

QT的概述 一.QT的介绍背景1.1 什么是QT1.2QT的发展史1.3 Qt支持的平台1.4QT版本1.5QT的优点1.6QT的应用场景 二.搭建QT开发环境2.1 QT的开发工具的下载2.2 QT环境变量配置 三.QT的三种基类四.QT Hello World程序4.1使用按钮实现4.1.1 代码方式实现4.1.2 可视化操作实现 一.QT的…

Java_如何在IDEA中使用Git

注意&#xff1a;进行操作前首先要确保已经下载git&#xff0c;在IDEA中可以下载git&#xff0c;但是速度很慢&#xff0c;可以挂梯子下载。 导入git仓库代码 第一次导入&#xff1a; 首先得到要加载的git仓库的url&#xff1a; 在git仓库中点击 “克隆/下载” 按钮&#xf…

【马斯洛需求层次理论】

马斯洛层次需求理论指导人生 作者 π 作者前言&#xff1a; 我认为人生是要一些原则和理论支撑指导的&#xff0c;不然人就很容易失去方向&#xff0c;动力。活得也会非常的累。 有时候不仅不自知&#xff0c;很多情况下不能理解他人的行为和感受。这就是让自己的社交变得很不…

推荐系统三十六式学习笔记:工程篇.常见架构25|Netflix个性化推荐架构

目录 架构的重要性经典架构1.数据流2.在线层3.离线层4.近线层 简化架构总结 你是否曾经觉得算法就是推荐系统的全部&#xff0c;即便不是全部&#xff0c;至少也是嫡长子&#xff0c;然而实际上&#xff0c;工程实现才是推荐系统的骨架。如果没有好的软件实现&#xff0c;算法不…

LoRaWAN网络中的chirpstack

目录 一、chirpstack介绍 二、网关与chirpstack之间的通信 三、NS与AS之间的通信 1、Protobuf 2、gRPC 一、chirpstack介绍 ChirpStack 是一个开源的 LoRaWAN 网络服务器&#xff0c;可用于 设置私有或公共 LoRaWAN 网络。ChirpStack 提供了一个 Web 界面 用于管理网关、设…

【计算机网络】OSPF单区域实验

一&#xff1a;实验目的 1&#xff1a;掌握在路由器上配置OSPF单区域。 2&#xff1a;学习OSPF协议的原理&#xff0c;及其网络拓扑结构改变后的变化。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS交换机、网线、内网网卡接口、Windows 2019操作系统的计算机等。…

OpenSSL学习笔记及在项目中的使用

OpenSSL官方命令手册&#xff1a;OpenSSL commands - OpenSSL Documentation 参考教程&#xff1a; 操作&#xff1a;OpenSSL的基本使用教程(一&#xff09;_openssl.exe使用教程-CSDN博客 操作&#xff1a;Linux和Shell回炉复习系列文章总目录 - 骏马金龙 - 博客园 (cnblog…

微服务安全——OAuth2.1详解、授权码模式、SpringAuthorizationServer实战、SSO单点登录、Gateway整合OAuth2

文章目录 Spring Authorization Server介绍OAuth2.0协议介绍角色OAuth2.0协议的运行流程应用场景授权模式详解客户端模式密码模式授权码模式简化模式token刷新模式 OAuth 2.1 协议介绍授权码模式PKCE扩展设备授权码模式拓展授权模式 OpenID Connect 1.0协议Spring Authorizatio…

揭秘!西藏首个基础教育信创示范基地,有何特殊之处?

学生可以通过玩游戏的方式来学习汉字&#xff0c;可以通过编程课件控制小汽车的行动轨迹&#xff0c;老师可以根据学生作业大数据&#xff0c;现场作精准解析与辅导……一个鼠标、一个键盘、一块屏幕&#xff0c;这是西藏首个基础教育信创示范基地的教学场景。 值得注意的是&am…

linux多线程概述和基本管理

线程概念 什么是线程&#xff1f; 线程是参与系统调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运行单位。一个线程指的是进程中一个单一顺序的控制流&#xff08;或者说是执行路线、执行流&#xff09;&#xff0c;一个进程中可以创建多个线程&#xff0c;…

流量卡流量与实际不符,这种是套路吗?

购买的流量卡与宣传不符&#xff0c;是不是套餐呢&#xff0c;这种并不是全部都是套路&#xff0c;目前常见的流量与实际不符的原因有&#xff1a;到账延迟、首月扣费模式、流量限制、虚假宣传等等&#xff0c;具体我们一块来看一下。 ​ 流量卡与实际不符的原因&#xff1a; …

git等常用工具以及cmake

一、将git中的代码克隆进电脑以及常用工具介绍 1.安装git 首先需要安装git sudo apt install git 注意一定要加--recursive&#xff0c;因为文件中有很多“引用文件“&#xff0c;即第三方文件&#xff08;库&#xff09;&#xff0c;加入该选项会将文件中包含的子模…

怎样确保eBay自养号测评的真实性?高效运作与实操技巧

在eBay平台上&#xff0c;销量是衡量一个店铺成功与否的重要指标。然而&#xff0c;对于一些新开的店铺或者想要快速提升销量的卖家来说&#xff0c;仅仅依靠自然流量是不够的。这时候&#xff0c;自养号测评就成为了一种有效的手段。本文将从注册到提高销量的全过程&#xff0…

HTTP ESP8266 获取天气请求 单片机,嵌入式 2024/7/26 日志

通过http请求获取天气信息: 这里借鉴一下 中国气象局网站举例 首先根据网址 分析: http://weather.cma.cn/ 通过vscode插件:REST Client 发送请求我们会得到内容 首先我们的打开浏览器调试工具查看请求格式 筛选以下几个关键的格式,试着用插件发送请求 GET /web/weather…

昇思25天学习打卡营第23天|基于MobileNetV2的垃圾分类

文章目录 昇思MindSpore应用实践1、MobileNetv2模型原理介绍2、数据准备数据预处理操作 3、基于MindSpore的MobileNetV2模型搭建ReLU6激活函数深度可分离卷积MobileNetV2网络结构 4、模型训练与测试5、模型推理 Reference 昇思MindSpore应用实践 本系列文章主要用于记录昇思25…

mysql面试(七)

前言 本章节列出了mysql在增删改查的时候&#xff0c;分别会涉及到哪些锁类型&#xff0c;又是如何交互的。 这个章节也是mysql面试基础系列的最后一章&#xff0c;后面准备更新redis数据类型和分布式锁相关问题。如果各位看官有什么问题的话&#xff0c;可以留言。 锁 之前…

【动态规划】不同路径

不同路径&#xff08;难度&#xff1a;中等&#xff09; AC代码 有点水 class Solution { public:int uniquePaths(int m, int n) {//以m为行&#xff0c;n为列&#xff0c;创建二维数组vector <vector<int>> dp(m1,vector<int>(n1));dp[0][1]1;dp[1][0]1;…