Flink的常用算子以及实例

1.map

特性:接收一个数据,经过处理之后,就返回一个数据
在这里插入图片描述

1.1. 源码分析

  • 我们来看看map的源码
    在这里插入图片描述
    map需要接收一个MapFunction<T,R>的对象,其中泛型T表示传入的数据类型,R表示经过处理之后输出的数据类型
  • 我们继续往下点,看看MapFunction<T,R>的源码
    在这里插入图片描述
    这是一个接口,那么在代码中,我们就需要实现这个接口

1.2. 案例

那么我们现在要实现一个功能,就是从给一个文件中读取数据,返回每一行的字符串长度。

我们要读取的文件内容如下
在这里插入图片描述

代码贴在这里(为了让打击不看迷糊,导包什么的我就省略了)

public class TransformTest1_Base {
    public static void main(String[] args) throws Exception {
        // 1. 获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 2. 将并行度设为1
        env.setParallelism(1);
        // 3. 读取文件夹
        DataStreamSource<String> inputDataStream = env.readTextFile("C:\\Users\\Administrator\\IdeaProjects\\FlinkTutorial\\src\\main\\resources\\sensor");
        // 4. 将文件夹每一行的数据都返回它的长度
        // 在这里我们用匿名内部类的方式创建了一个MapFunction对象
        SingleOutputStreamOperator<Integer> dataStream = inputDataStream.map(new MapFunction<String, Integer>() {

            // 5. 重写map方法,参数s是接收到的一个数据,我们只需要返回它的长度就行了。
            @Override
            public Integer map(String s) throws Exception {
                return s.length();
            }
        });
        // 6. 打印输出
        dataStream.print();
        // 7. 启动执行环境
        env.execute();
    }
}

显示
在这里插入图片描述

1.3. 总结

map的使用范围就是需要对的那个数据进行处理,并且每次返回一个数据的时候,map就比较方便了。

2. flatMap

  • 接收一个数据,可以返回多条数据

2.1. 源码分析

在这里插入图片描述
我们发现,它需要传入一个FlatMapFunction的一个对象
在这里插入图片描述

我们继续点进去,看看FlatMapFunction的源码,可以发现,FlatMapFunction<T,R>也是一个接口,并且接口里面的方法的返回值是一个Collector,也就是多个值的集合。

2.2. 案例

我们还是读取那个文件,这次我们要做的处理是,将文件的每一行数据按照逗号隔开,给出代码:

public class TransformTest2_Base {
    public static void main(String[] args) throws Exception {
        // 1. 获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 2. 设置并行度
        env.setParallelism(1);
        // 3. 读取文件夹
        DataStreamSource<String> dataStream = env.readTextFile("C:\\Users\\Administrator\\IdeaProjects\\FlinkTutorial\\src\\main\\resources\\sensor");
        // 4. 用匿名内部类的方式重写FlatMapFuncction,将每行字符按","隔开
        SingleOutputStreamOperator<String> flatMapStream = dataStream.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public void flatMap(String s, Collector<String> collector) throws Exception {
                // 5. 分割一行字符,获得对应的字符串数组
                String[] split = s.split(",");
                for (String slt : split) {
                    // 6. 将这些数据返回
                    collector.collect(slt);
                }
            }
        });
        // 7. 打印输出处理后的数据
        flatMapStream.print();
        // 8. 启动执行环境
        env.execute();
    }
}

可以看到执行的结果
在这里插入图片描述

3. filter

听这个名字就知道是个过滤器,用来过滤数据。
在这里插入图片描述

3.1. 源码分析

我们看看filer的源码,继承子FilterFunction,可以看到,这次泛型就只有一个值了,因为filter只允许返回的数据<=原来的数据,所以只做过滤,并不能改变数据蕾西,没必要设置返回的类型
在这里插入图片描述
我们继续点进去,看看FilterFunction的源码
在这里插入图片描述
果不其然,也是一个接口,而里面的filter方法只有一个参数,并且返回的是一个boolean类型,若返回true则var1原样返回,若返回false,则var1会被过滤掉。

3.2. 案例

我们还是读取以上文件,这一次我们返回以"sensor_1"开头的字符串,其余的一律不返回,给出代码

public class TransformTest3_Base {
    public static void main(String[] args) throws Exception {
        // 1. 获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 2. 设置并行度
        env.setParallelism(1);
        // 3. 读取文件
        DataStreamSource<String> dataStream = env.readTextFile("C:\\Users\\Administrator\\IdeaProjects\\FlinkTutorial\\src\\main\\resources\\sensor");
        // 4. 用匿名内部类的方式重写FilterFunction
        SingleOutputStreamOperator<String> filterDataStream = dataStream.filter(new FilterFunction<String>() {
            @Override
            public boolean filter(String s) throws Exception {
                // 5. 若s以"sensor_1"开头,则返回true
                return s.startsWith("\"sensor_1\"");
            }
        });
        // 6. 打印处理后的数据
        filterDataStream.print();
        // 7. 启动执行环境
        env.execute();
    }
}

4. 分组聚合

  • 注意:任何的聚合操作都有默认的分组,聚合是在分组的基础上进行的。比如,对整体进行求和,那么分组就是整体。所以,在做聚合操作之前,一定要明确是在哪个分组上进行聚合操作
  • 注意:聚合操作,本质上是一个多对一(一对一是多对一的特殊情况)的操作。特别注意的是这个’一‘,可以是一个值(mean, sum等),同样也可以是一个对象(list, set等对象)

4.1. 分组(keyBy)

在这里插入图片描述
DataStream → KeyedStream:逻辑地将一个流拆分成不相交的分区,每个分区包含具有相同 key 的元素,在内部以 hash 的形式实现的。

  • 分组就是为了聚合操作做准备的,keyBy方法会将数据流按照hash实现,分别放在不同的分区,每个分区都可以进行聚合操作。
  • 我们可以用这个性质,计算每一个sensor温度的最大值,我们为此将文件修改:
    在这里插入图片描述
    分组之后的图就是所有sensor_1在一个分区里,sensor_6,sensor_7,sensor_10在不同的三个分区,也就是有四个分区,而后三个分区中只有一条数据,所以最大值和最小值都只有一个
  • 在flink中,分组操作是由keyBy方法来完成的,我们来看看keyBy的源码
    在这里插入图片描述
    可以发现,keyBy可以对对象和元组进行聚合。

4.2. 聚合

这些算子可以针对 KeyedStream 的每一个支流做聚合。
⚫ sum():对每个支流求和
⚫ min():对每个支流求最小值
⚫ max():对每个支流求最大值
⚫ minBy()
⚫ maxBy()
我们来看看max()的源码
在这里插入图片描述
这也是传一个属性名,也就是求对应的属性名的最大值。

4.3. 实例演示

public class TransformTest1_RollingAggreation {
    public static void main(String[] args) throws Exception {
        // 1. 获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 2. 设置并行度
        env.setParallelism(1);
        // 3. 读取文件
        DataStreamSource<String> stringDataStreamSource = env.readTextFile("C:\\Users\\Administrator\\IdeaProjects\\FlinkTutorial\\src\\main\\resources\\sensor");
        // 4. 用map将每行数据变成一个对象
        SingleOutputStreamOperator<SensorReading> map = stringDataStreamSource.map(new MapFunction<String, SensorReading>() {
            @Override
            public SensorReading map(String s) throws Exception {
                String[] split = s.split(",");
                return new SensorReading(split[0], new Long(split[1]), new Double(split[2]));
            }
        });
        // 5. 分组操作,以id属性分组
        KeyedStream<SensorReading, Tuple> keyedstream = map.keyBy("id");
        // 6. 聚合操作,求每个分组的温度最大值
        SingleOutputStreamOperator<SensorReading> resultStream = keyedstream.max("temperature");
        // 7. 打印输出
        resultStream.print();
        // 8. 启动执行环境
        env.execute();
    }
}

运行结果
在这里插入图片描述
诶,这有人就要问了,不是求每一个分组的温度最大值么?为什么sensor_1的这个分组所有的数据都有?
答:flink是一个流处理分布式框架,这是一条数据流,每来一个数据就得处理一次,所以输出的都是当前状态下的最大值。

4.4. reduce自定义聚合

在实际生产中,不可能让我们完成这么简单的操作就行了,所以我们需要更复杂的操作,而reduce就是满足这个条件,它可以让我们自定义聚合的方式。

  • 我们来看看reduce的源码
    在这里插入图片描述
    reduce需要传入的是一个ReduceFunction的对象,我们再来看看ReduceFunction是个什么东西
    在这里插入图片描述
    var1是当前这个分组的状态,var2是新加入的值,而reduce函数体就是我们要进行的操作,返回一个新的状态。
    到这我就明白了,要是我们向实时获取最大温度的话,var1是之前的最大温度,通过var1和var2的比较就能实现。

4.5. reduce实例

我们这一次要实现一个实时的温度最大值,也就是返回的数据中的时间戳是当前的。

public class TransformTest1_Reduce {
    public static void main(String[] args) throws Exception {
        // 1. 获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 2. 设置并行度
        env.setParallelism(1);
        // 3. 读取文件
        DataStreamSource<String> dataStream = env.readTextFile("C:\\Users\\Administrator\\IdeaProjects\\FlinkTutorial\\src\\main\\resources\\sensor");
        // 4. 通过map将每行数据转换为一个对象
        SingleOutputStreamOperator<SensorReading> map = dataStream.map(new MapFunction<String, SensorReading>() {
            @Override
            public SensorReading map(String s) throws Exception {
                String[] split = s.split(",");
                return new SensorReading(split[0], new Long(split[1]), new Double(split[2]));
            }
        });
        // 5. 按对象的id分组
        KeyedStream<SensorReading, Tuple> keyStream = map.keyBy("id");
        // 6. reduce自定义聚合
        SingleOutputStreamOperator<SensorReading> reduce = keyStream.reduce(new ReduceFunction<SensorReading>() {
            @Override
            public SensorReading reduce(SensorReading sensorReading, SensorReading t1) throws Exception {
                // 7. 获取当前时间为止接收到的最大温度
                return new SensorReading(sensorReading.getId(), System.currentTimeMillis(), Math.max(sensorReading.getTemperature(),t1.getTemperature()));
            }
        });
        // 8. 打印输出
        reduce.print();
        // 9. 启动运行环境
        env.execute();
    }
}

这一次的输出我们就得你好好研究一下了。
在这里插入图片描述
从这块可以发现,我们获取的都是当前的时间戳,而且时间戳也在改变,这一点很好理解,但是下面这个数据就很诡异了。
在这里插入图片描述

  • 这两块的时间戳为什么没有改变呢?这需要我们再来看看reduce方法了,reduce方法是传入两个参数,第一个是当前的状态,第二个是新读取的值,通过方法体的操作返回一个最新的状态。
  • 仔细理解一下这句话,若我刚开始没有数据的时候,那么哪来的状态呢?所以reduce把接收到的第一个参数作为状态,其中sensor_6,7,8这三个分区只有一个数据,所以直接拿来当作状态。

5. 多流转换算子

5.1. 分流操作(Split 和 Select)

  • Split能将流中的数据按条件贴上标签,比如我把温度大于30度的对象贴上一个high标签,把温度低于30度的贴上一个low标签,标签可以贴多个。那么就把流中的数据,按照标签分类了(这里并没有分流)
    在这里插入图片描述
  • Select是按照标签来分流
    在这里插入图片描述
  1. split源码
    在这里插入图片描述
    可以发现,返回的是一个SplitStream,需要传入一个选择器,我们看看OutputSeclector的源码
    在这里插入图片描述
    传入value,返回这个value对应的标签,实现对这个value进行类似"分类"的操作。
  2. select源码
    在这里插入图片描述
    只需要接收一个或者多个标签就能返回包含那个标签对象的数据流。

5.2. 实例演示

  • 我们这一次要把读取到的数据分成三条流,一条是high(高于30度),一条是low(低于30度),一条是all(所有的数据)。代码:
public class TransformTest4_MultipleStreams {
    public static void main(String[] args) throws Exception {
        // 1. 获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        // 2. 设置并行度
        env.setParallelism(1);
        // 3. 读取文件
        DataStreamSource<String> dataStream = env.readTextFile("C:\\Users\\Administrator\\IdeaProjects\\FlinkTutorial\\src\\main\\resources\\sensor");
        // 4. 通过map将每行数据转换为一个对象
        SingleOutputStreamOperator<SensorReading> map = dataStream.map(new MapFunction<String, SensorReading>() {
            @Override
            public SensorReading map(String s) throws Exception {
                String[] split = s.split(",");
                return new SensorReading(split[0], new Long(split[1]), new Double(split[2]));
            }
        });
        // 5. 按条件贴标签
        SplitStream<SensorReading> split = map.split(new OutputSelector<SensorReading>() {
            @Override
            public Iterable<String> select(SensorReading value) {
                return value.getTemperature() > 30 ? Collections.singletonList("high") : Collections.singletonList("low");
            }
        });
        // 6. 按标签选择,生成不同的数据流
        DataStream<SensorReading> high = split.select("high");
        DataStream<SensorReading> low = split.select("low");
        DataStream<SensorReading> all = split.select("high", "low");
        high.print("high");
        low.print("low");
        all.print("all");
        env.execute();
    }
}

5.3. 合流操作Connect 和 CoMap

在这里插入图片描述
DataStream,DataStream → ConnectedStreams:连接两个保持他们类型的数
据流,两个数据流被 Connect 之后,只是被放在了一个同一个流中,内部依然保持各自的数据和形式不发生任何变化,两个流相互独立。
在这里插入图片描述
ConnectedStreams → DataStream:作用于 ConnectedStreams 上,功能与 map和 flatMap 一样,对 ConnectedStreams 中的每一个 Stream 分别进行 map 和 flatMap处理。
类似于一国两制,看似两条流合并在了一起,其实内部依旧是按照自己的约定运行,类型并没有改变。

  1. connect源码
    在这里插入图片描述
    将当前调用者的流和参数中的流合并,返回一个ConnectedStreams<T,R>类型
    在这里插入图片描述
    我们再来看看ConnectionStreams<T,R>中的map方法,其中要传的是一个CoMapFunction<IN1,IN2,R>的对象,最重要的就是这个类,我们来看看这个类
    在这里插入图片描述
    这个CoMapFunction<IN1,IN2,R>和之前的MapFunction不太一样,这里要重写的方法有两个,map1和map2,一个是针对IN1的,一个是针对IN2的,R就是返回类型。
    这下全明白了,在这个方法内部,对这两条流分别操作,合成一条流。

5.4. 实例演示

public class TransformTest5_MultipleStreams {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);
        // 1. 读取文件
        DataStreamSource<String> dataStreamSource = env.readTextFile("C:\\Users\\Administrator\\IdeaProjects\\FlinkTutorial\\src\\main\\resources\\sensor");
        // 2. 将每行数据变成一个对象
        SingleOutputStreamOperator<SensorReading> map = dataStreamSource.map(new MapFunction<String, SensorReading>() {
            @Override
            public SensorReading map(String s) throws Exception {
                String[] split = s.split(",");
                return new SensorReading(split[0], new Long(split[1]), new Double(split[2]));
            }
        });
        // 3. 将数据打上标签
        SplitStream<SensorReading> split = map.split(new OutputSelector<SensorReading>() {
            @Override
            public Iterable<String> select(SensorReading value) {
                return value.getTemperature() > 30 ? Collections.singletonList("high") : Collections.singletonList("low");
            }
        });
        // 4. 按照高温和低温的标签分成两条流
        DataStream<SensorReading> high = split.select("high");
        DataStream<SensorReading> low = split.select("low");
        // 5. 将high流的数据转换为二元组
        SingleOutputStreamOperator<Tuple2<String, Double>> tuple2SingleOutputStreamOperator = high.map(new MapFunction<SensorReading, Tuple2<String, Double>>() {
            @Override
            public Tuple2<String, Double> map(SensorReading sensorReading) throws Exception {
                return new Tuple2<>(sensorReading.getId(), sensorReading.getTemperature());
            }
        });
        // 6. 将tuple2SingleOutputStreamOperator和low连接
        ConnectedStreams<Tuple2<String, Double>, SensorReading> connect = tuple2SingleOutputStreamOperator.connect(low);
        // 7. 调用map传参CoMapFunction将两条流合并成一条流objectSingleOutputStreamOperator
        SingleOutputStreamOperator<Object> objectSingleOutputStreamOperator = connect.map(new CoMapFunction<Tuple2<String, Double>, SensorReading, Object>() {
            // 这是处理high流的方法
            @Override
            public Object map1(Tuple2<String, Double> value) throws Exception {
                return new Tuple3<>(value.getField(0), value.getField(1), "temp is too high");
            }
            // 这是处理low流的方法
            @Override
            public Object map2(SensorReading value) throws Exception {
                return new Tuple2<>(value.getTemperature(), "normal");
            }
        });
        objectSingleOutputStreamOperator.print();
        env.execute();
    }
}

5.5. 多条流合并(union)

之前我们只能合并两条流,那我们要合并多条流呢?这里我们就需要用到union方法。
在这里插入图片描述

  • Connect 与 Union 区别:
  1. Union 之前两个流的类型必须是一样,Connect 可以不一样,在之后的 coMap中再去调整成为一样的。
  2. Connect 只能操作两个流,Union 可以操作多个。

若我们给出以下代码:

high.union(low,all);

那么high,low,all三条流都会合并在一起。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在ARM服务器上一键安装Proxmox VE(以在Oracle Cloud VPS上为例)(甲骨文)

前言 如题&#xff0c;具体用到的说明文档如下 virt.spiritlhl.net 具体流程 首先是按照说明&#xff0c;先得看看自己的服务器符不符合安装 Proxmox VE的条件 https://virt.spiritlhl.net/guide/pve_precheck.html#%E5%90%84%E7%A7%8D%E8%A6%81%E6%B1%82 有提到硬件和软…

Redis缓存问题(穿透, 击穿, 雪崩, 污染, 一致性)

目录 1.什么是Redis缓存问题&#xff1f; 2.缓存穿透 3.缓存击穿 4.缓存雪崩 5.缓存污染&#xff08;或满了&#xff09; 5.1 最大缓存设置多大 5.2 缓存淘汰策略 6.数据库和缓存一致性 6.1 4种相关模式 6.2 方案&#xff1a;队列重试机制 6.3 方案&#xff1a;异步更新缓…

基于YOLOV8模型的西红柿目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOV8模型的西红柿目标检测系统可用于日常生活中检测与定位西红柿目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算法训练数…

day20 飞机大战射击游戏

有飞行物类 飞行 爆炸 的连环画&#xff0c; 飞行的背景图 &#xff0c; 子弹图&#xff0c; 还有游戏开始 暂停 结束 的画面图。 设计一个飞机大战的小游戏&#xff0c; 玩家用鼠标操作hero飞行机&#xff0c; 射出子弹杀死敌机&#xff0c;小蜜蜂。 敌机可以获得分数&…

浅谈java自定义中类两个对象的比较

目录 实现比较两个对象是否相同 1.前置代码 1.学生类 2.示例 3.输出 4.原因 2.那么我们要怎么做呢? 1.对Student类中重新实现quals方法(即对equals方法重写) 2.完整代码如下: 3.具体操作 4.演示 1.示例 2.输出 3.原因 实现比较两个对象的大小 第一种: 用…

Android 9.0 Vold挂载流程解析(下)

Android 9.0 Vold挂载流程解析&#xff08;上&#xff09; 前言 上一篇介绍了Android 文件系统中Vold挂载机制的总体框架&#xff0c;我们分析了vod进程的main.cpp.接下来我们分析下存储卡挂载和卸载的流程。 存储卡挂载 在上篇文章文章提到&#xff0c;监听驱动层挂载和卸…

【是C++,不是C艹】 手把手带你实现Date类(附源码)

&#x1f49e;&#x1f49e;欢迎来到 Claffic 的博客&#x1f49e;&#x1f49e; &#x1f449; 专栏&#xff1a;《是C&#xff0c;不是C艹》&#x1f448; 前言&#xff1a; 恍惚间&#xff0c;已经两个月没更新了 &#xff08;&#xff1b;д&#xff40;&#xff09;ゞ 我忏…

听GPT 讲Alertmanager源代码--dispatch/silence/inhibit等

目前Alertmanager项目共计53M大小&#xff0c;其中.git占了46M&#xff0c;总的go代码行数不足6万行(包括.pb.go等文件)&#xff0c;不算是一个大项目。 但实现了告警的分发&#xff0c;静默等功能&#xff0c;值的研究&#xff0c;尤其是dispatch中的route部分。 在Prometheus…

2022年03月 C/C++(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;和数 给定一个正整数序列&#xff0c;判断其中有多少个数&#xff0c;等于数列中其他两个数的和。 比如&#xff0c;对于数列1 2 3 4, 这个问题的答案就是2, 因为3 2 1, 4 1 3。 时间限制&#xff1a;10000 内存限制&#xff1a;65536 输入 共两行&#x…

图数据库_Neo4j学习cypher语言_使用CQL_构建明星关系图谱_导入明星数据_导入明星关系数据_创建明星关系---Neo4j图数据库工作笔记0009

首先找到明星数据 可以看到有一个sheet1,是,记录了所有的关系的数据 然后比如我们搜索一个撒贝宁,可以看到撒贝宁的数据 然后这个是构建的CQL语句 首先我们先去启动服务 neo4j console 然后我们再来看一下以前导入的,可以看到导入很简单, 就是上面有CQL 看一下节点的属性

验证二叉搜索树

给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。 所有左子树和右子树自身必须也是二叉搜索树。 示例 1&#xff1a; 输…

关于lattice planner

使用编程创建驾驶场景。 1.使用Driving scenario Designer 交互方式创建驾驶场景 2.导出matalb function 3.修正这个函数&#xff0c;创建原始场景的变体。 4.调用这个函数&#xff0c;生成drivingScenario object。 5.在simulink中仿真&#xff0c;导入这个objcet &…

探索线程池的威力:优化多线程任务管理与性能提升

比喻举例&#xff08;可以比作工人队伍&#xff09; 想象一下&#xff0c;如果我们需要完成很多工作&#xff0c;我们可以招募一群工人来协助。然而&#xff0c;如果每个工人都是临时招募的&#xff0c;工作完成后就解雇他们&#xff0c;那么每次都要花时间和精力来招募和解雇工…

蓝桥杯上岸每日N题 (闯关)

大家好 我是寸铁 希望这篇题解对你有用&#xff0c;麻烦动动手指点个赞或关注&#xff0c;感谢您的关注 不清楚蓝桥杯考什么的点点下方&#x1f447; 考点秘籍 想背纯享模版的伙伴们点点下方&#x1f447; 蓝桥杯省一你一定不能错过的模板大全(第一期) 蓝桥杯省一你一定不…

使用VisualStudio制作上位机(一)

文章目录 使用VisualStudio制作上位机(一)写在前面第一部分:创建应用程序第二部分:GUI主界面设计使用VisualStudio制作上位机(一) Author:YAL 写在前面 1.达到什么目的呢 本文主要讲怎么通过Visual Studio 制作上位机,全文会以制作过程来介绍怎么做,不会去讲解具体…

【Java】常见面试题:HTTP/HTTPS、Servlet、Cookie、Linux和JVM

文章目录 1. 抓包工具&#xff08;了解&#xff09;2. 【经典面试题】GET和POST的区别&#xff1a;3. URL中不是也有这个服务器主机的IP和端口吗&#xff0c;为啥还要搞个Host&#xff1f;4. 补充5. HTTP响应状态码6. 总结HTTPS工作过程&#xff08;经典面试题&#xff09;7. H…

最长回文子序列——力扣516

动态规划 int longestPalindromeSubseq(string s){int n=s.length();vector<vector<int>>

11. Docker Swarm(二)

1、前言 上一篇中我们利用Docker Swarm搭建了基础的集群环境。那么今天我们就来验证以下该集群的可用性。上一篇的示例中&#xff0c;我创建了3个实例副本&#xff0c;并且通过访问http://192.168.74.132:8080得到我们的页面。 2、验证高可用 1&#xff09;我们可以通过以下命…

一文读懂视频号下载

工具&#xff1a; 移动端抓包工具&#xff08;以Stream为例&#xff09;电脑端浏览器电脑端析包工具&#xff08;以Charles为例&#xff09;【可选项】 一、手机抓包 1 开启Stream 2 抓包 手机进入视频号&#xff0c;通过“搜索“的方式发送get请求&#xff0c;达到抓包的效…

在jupyter notebook中使用海龟绘图

首先&#xff0c;安装ipyturtle3 ref:ipyturtle3 PyPI pip install ipyturtle3然后&#xff0c;安装ipycanvas ipycanvas是一个需要安装在与JupyterLab实例相同环境的包。此外&#xff0c;您需要安装nodejs&#xff0c;并启用JupyterLab ipycanvas小部件。 所有这些都在ipy…