当前位置: 首页 > news >正文

【Kafka】Kafka Stream简单使用

一、实时流式计算

1. 概念

一般流式计算会与批量计算相比较。在流式计算模型中,输入是持续的,可以认为在时间上是无界的,也就意味着,永远拿不到全量数据去做计算。同时,计算结果是持续输出的,也即计算结果在时间上也是无界的。流式计算一般对实时性要求较高,同时一般是先定义目标计算,然后数据到来之后将计算逻辑应用于数据。同时为了提高计算效率,往往尽可能采用增量计算代替全量计算
在这里插入图片描述
流式计算就相当于上图的右侧扶梯,是可以源源不断的产生数据,源源不断的接收数据,没有边界。

2. 应用场景

  • 日志分析: 网站的用户访问日志进行实时的分析,计算访问量,用户画像,留存率等等,实时的进行数据分析,帮助企业进行决策
  • 大屏看板统计: 可以实时的查看网站注册数量,订单数量,购买数量,金额等。
  • 公交实时数据: 可以随时更新公交车方位,计算多久到达站牌等
  • 实时文章分值计算

比如应用较广的 头条类文章的分值计算,通过用户的行为实时文章的分值,分值越高就越被推荐

3. Kafka Stream

近些年来,开源流处理领域涌现出了很多优秀框架。光是在 Apache 基金会孵化的项目,关于流处理的大数据框架就有十几个之多,比如早期的 Apache SamzaApache Storm,以及这些年火爆的 Spark 以及 Flink 等。

3.1 Kafka Streams的特点

  • Kafka Stream提供了一个非常简单而轻量的Library,它可以非常方便地嵌入任意Java应用中,也可以任意方式打包和部署
  • 除了Kafka外,无任何外部依赖
  • 充分利用Kafka分区机制实现水平扩展顺序性保证
  • 通过可容错的state store实现高效的状态操作(如windowed joinaggregation
  • 支持正好一次处理语义
  • 提供记录级的处理能力,从而实现毫秒级的低延迟
  • 支持基于事件时间的窗口操作,并且可处理晚到的数据(late arrival of records)
  • 同时提供底层的处理原语Processor(类似于Storm的spout和bolt),以及高层抽象的DSL(类似于Spark的map/group/reduce)

在这里插入图片描述

3.2 关键概念

一个最简单的Streaming的结构如下图所示:
在这里插入图片描述

从一个Topic中读取到数据,经过一些处理操作之后,写入到另一个Topic中,这就是一个最简单的Streaming流式计算。其中,Source Topic中的数据会源源不断的产生新数据。
那么,我们再在上面的结构之上扩展一下,假设定义了多个Source TopicDestination Topic,那就构成如下图所示的较为复杂的拓扑结构:
在这里插入图片描述

  • 源处理器(Source Processor):源处理器是一个没有任何上游处理器的特殊类型的流处理器。它从一个或多个kafka主题生成输入流。通过消费这些主题的消息并将它们转发到下游处理器
  • Sink处理器:sink处理器是一个没有下游流处理器的特殊类型的流处理器。它接收上游流处理器的消息发送到一个指定的Kafka主题
    在这里插入图片描述
    Kafka Streams被认为是开发实时应用程序的最简单方法。它是一个Kafka的客户端API库,编写简单的java就可以实现流式处理。

3.3 KStream

KStream:数据结构类似于map,如下图,key-value键值对

在这里插入图片描述

KStream数据流(data stream),是一段顺序的,可以无限长,不断更新的数据集。
数据流中比较常记录的是事件,这些事件可以是一次鼠标点击(click),一次交易,或是传感器记录的位置数据。

KStream负责抽象的,就是数据流。与Kafka自身topic中的数据一样,类似日志,每一次操作都是向其中插入(insert)新数据。

二、测试kafkaStream

先看下简单的kafkaStreamKStream测试

需求分析:求单词个数(word count)
在这里插入图片描述

1. pom.xml引入依赖:

       <!-- kafka --><dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactId><exclusions><exclusion><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-streams</artifactId><exclusions><exclusion><artifactId>connect-json</artifactId><groupId>org.apache.kafka</groupId></exclusion><exclusion><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId></exclusion></exclusions></dependency>

2. 配置文件

server:port: 9991
spring:application:name: kafka-demokafka:bootstrap-servers: 192.168.200.130:9092producer:retries: 10key-serializer: org.apache.kafka.common.serialization.StringSerializervalue-serializer: org.apache.kafka.common.serialization.StringSerializercompression-type: lz4consumer:group-id: ${spring.application.name}-testkey-deserializer: org.apache.kafka.common.serialization.StringDeserializervalue-deserializer: org.apache.kafka.common.serialization.StringDeserializer

3. 编写生产者

ProducerQuickStart.java

package com.kafka.sample;import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.clients.producer.*;import java.util.Properties;@Slf4j
public class ProducerQuickStart {public static void main(String[] args) {//1. kafka的配置信息Properties prop = new Properties();//kafka的链接信息prop.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.200.130:9092");//配置重试次数prop.put(ProducerConfig.RETRIES_CONFIG, 5);//数据压缩prop.put(ProducerConfig.COMPRESSION_TYPE_CONFIG,"lz4");//ack配置  消息确认机制   默认ack=1,即只要集群首领节点收到消息,生产者就会收到一个来自服务器的成功响应
//        prop.put(ProducerConfig.ACKS_CONFIG,"all");消息key的序列化器prop.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");//消息value的序列化器prop.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringSerializer");//2. 生产者对象KafkaProducer<String, String> producer = new KafkaProducer<String, String>(prop);//封装发送的消息ProducerRecord<String, String> producerRecord = new ProducerRecord<String, String>("itcast-topic-input", "key_001", "hello kafka");//3. 发送消息for (int i = 0; i < 5; i++) {producer.send(producerRecord);}//4. 关闭消息通道  必须关闭,否则消息发不出去producer.close();}
}

4 编写kafkaStream流式处理

KafkaStreamQuickStart.java

package com.kafka.sample;import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.KeyValue;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.kstream.TimeWindows;
import org.apache.kafka.streams.kstream.ValueMapper;import java.time.Duration;
import java.util.Arrays;
import java.util.Properties;/*** 流式处理*/
public class KafkaStreamQuickStart {public static void main(String[] args) {//kafka的配置信心Properties prop = new Properties();prop.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.200.130:9092");prop.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());prop.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());prop.put(StreamsConfig.APPLICATION_ID_CONFIG,"streams-quickstart");//stream 构建器StreamsBuilder streamsBuilder = new StreamsBuilder();//流式计算streamProcessor(streamsBuilder);//创建kafkaStream对象KafkaStreams kafkaStreams = new KafkaStreams(streamsBuilder.build(),prop);//开启流式计算kafkaStreams.start();}/*** 流式计算* 消息的内容:hello kafka  hello itcast* @param streamsBuilder*/private static void streamProcessor(StreamsBuilder streamsBuilder) {//创建kstream对象,同时指定从那个topic中接收消息KStream<String, String> stream = streamsBuilder.stream("itcast-topic-input");/*** 处理消息的value*/stream.flatMapValues(new ValueMapper<String, Iterable<String>>() {@Overridepublic Iterable<String> apply(String value) {return Arrays.asList(value.split(" "));}})//按照value进行聚合处理.groupBy((key,value)->value)//时间窗口.windowedBy(TimeWindows.of(Duration.ofSeconds(10)))//统计单词的个数.count()//转换为kStream.toStream().map((key,value)->{System.out.println("key:"+key+",vlaue:"+value);return new KeyValue<>(key.key().toString(),value.toString());})//发送消息.to("itcast-topic-out");}
}

5. 编写消费者

ConsumerQuickStart.java

package com.kafka.sample;import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;import java.time.Duration;
import java.util.Collections;
import java.util.Properties;public class ConsumerQuickStart {public static void main(String[] args) {//1. 添加kafka的配置信息Properties properties = new Properties();// 配置链接信息properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.200.130:9092");//配置消费者组properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group-2");//配置消息的反序列化器properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.StringDeserializer");//2. 消费者对象KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);//3. 订阅主题consumer.subscribe(Collections.singletonList("itcast-topic-out"));//当前线程一直监听消息while(true){//4. 消费者拉取消息: 每秒拉取一次ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));for (ConsumerRecord<String, String> record : records) {System.out.println(record.key());System.out.println(record.value());}}}
}

启动项目:

  1. 在远端(192.168.200.130:9092)启动docker中的kafka容器
  2. 启动消费者ConsumerQuickStartmain函数
  3. 启动kafkastreammian函数
  4. 启动生产者ProducerQuickStartmain函数

5. 控制台打印结果:

在这里插入图片描述
在这里插入图片描述

整个过程:
生产者向kafka中发送了5条“hello kafka”消息,topic均为itcast-topic-input。kafkastream监听这个topic,每10秒进行一次流式处理,将“hello kakfa”字符串分割,并统计每个单词出现的次数。然后转为kstream,发送消息到kafka中的topic=itcast-topic-out”。消费者监听“itcast-topic-out”的topic,消费消息。

三、Springboot整合kafkaStream

1. 配置文件新增

application.yml

server:port: 9991
spring:application:name: kafka-demokafka:bootstrap-servers: 192.168.200.130:9092producer:retries: 10key-serializer: org.apache.kafka.common.serialization.StringSerializervalue-serializer: org.apache.kafka.common.serialization.StringSerializercompression-type: lz4consumer:group-id: ${spring.application.name}-testkey-deserializer: org.apache.kafka.common.serialization.StringDeserializervalue-deserializer: org.apache.kafka.common.serialization.StringDeserializer
# kafkaStream新增以下配置
kafka:hosts: 192.168.200.130:9092group: ${spring.application.name}

2. 在微服务中新增配置类

KafkaStreamConfig.java

package com.kafka.config;import lombok.Getter;
import lombok.Setter;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.StreamsConfig;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafkaStreams;
import org.springframework.kafka.annotation.KafkaStreamsDefaultConfiguration;
import org.springframework.kafka.config.KafkaStreamsConfiguration;import java.util.HashMap;
import java.util.Map;/*** 通过重新注册KafkaStreamsConfiguration对象,设置自定配置参数*/@Setter
@Getter
@Configuration
@EnableKafkaStreams
@ConfigurationProperties(prefix="kafka")
public class KafkaStreamConfig {private static final int MAX_MESSAGE_SIZE = 16* 1024 * 1024;private String hosts;private String group;@Bean(name = KafkaStreamsDefaultConfiguration.DEFAULT_STREAMS_CONFIG_BEAN_NAME)public KafkaStreamsConfiguration defaultKafkaStreamsConfig() {Map<String, Object> props = new HashMap<>();props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, hosts);props.put(StreamsConfig.APPLICATION_ID_CONFIG, this.getGroup()+"_stream_aid");props.put(StreamsConfig.CLIENT_ID_CONFIG, this.getGroup()+"_stream_cid");props.put(StreamsConfig.RETRIES_CONFIG, 10);props.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass());props.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass());return new KafkaStreamsConfiguration(props);}
}

3. 使用kafkaStream监听消息

KafkaStreamHelloListener.java

package com.kafka.stream;import lombok.extern.slf4j.Slf4j;
import org.apache.kafka.streams.KeyValue;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.kstream.TimeWindows;
import org.apache.kafka.streams.kstream.ValueMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.time.Duration;
import java.util.Arrays;@Configuration
@Slf4j
public class KafkaStreamHelloListener {@Beanpublic KStream<String,String> kStream(StreamsBuilder streamsBuilder){//创建kstream对象,同时指定从那个topic中接收消息KStream<String, String> stream = streamsBuilder.stream("itcast-topic-input");stream.flatMapValues(new ValueMapper<String, Iterable<String>>() {@Overridepublic Iterable<String> apply(String value) {return Arrays.asList(value.split(" "));}})//根据value进行聚合分组.groupBy((key,value)->value)//聚合计算时间间隔.windowedBy(TimeWindows.of(Duration.ofSeconds(10)))//求单词的个数.count().toStream()//处理后的结果转换为string字符串.map((key,value)->{System.out.println("key:"+key+",value:"+value);return new KeyValue<>(key.key().toString(),value.toString());})//发送消息.to("itcast-topic-out");return stream;}
}

测试:

启动springboot应用程序,运行之前的ProducerQuickStart来生产消息,约10秒后,看到kafkaStream消息的处理结果
在这里插入图片描述

说明kafkaStream接收到消息并将多条消息进行了统一处理。

参考(推荐阅读):

  1. https://cloud.tencent.com/developer/article/2100664
  2. https://www.cnblogs.com/tree1123/p/11457851.html

相关文章:

【Kafka】Kafka Stream简单使用

一、实时流式计算 1. 概念 一般流式计算会与批量计算相比较。在流式计算模型中&#xff0c;输入是持续的&#xff0c;可以认为在时间上是无界的&#xff0c;也就意味着&#xff0c;永远拿不到全量数据去做计算。同时&#xff0c;计算结果是持续输出的&#xff0c;也即计算结果…...

在Linux服务器上,查看系统最近的重启记录

在Linux服务器上&#xff0c;您可以查看系统的重启记录以了解系统何时进行了重启。系统的重启记录通常被记录在系统日志文件中。以下是在不同Linux发行版上查看系统重启记录的方法&#xff1a; 1. 使用 last 命令&#xff1a; 打开终端&#xff0c;并输入以下命令来查看系统的…...

Vue2023 面试归纳及复习

1. Vue 3中的Composition API&#xff08;Hooks&#xff09;是什么&#xff1f;它与Options API有何不同&#xff1f; 答&#xff1a;Composition API是Vue 3中引入的一种新的API风格&#xff0c; 用于组织和重用组件逻辑。它与Options API相比&#xff0c; 提供了更灵活和可…...

Android动态可编辑长度列表

概述 在界面实现一个列表&#xff0c;用户可以随意给列表新增或者删除项目&#xff0c;在开发中比较常用&#xff0c;但是真正做起来又有点花时间&#xff0c;今天花时间做一个&#xff0c;以便在以后的开发中用到。 详细 运行效果&#xff1a; 二、实现思路&#xff1a; 1…...

合并对象在 Typescript 中的实现与应用

合并对象在 Typescript 中的实现与应用 文章目录 合并对象在 Typescript 中的实现与应用一、简介二、实现1、函数实现2、参数说明3、返回值 三、使用示例四、实际应用场景五、拓展&#xff1a;使用 lodash-es 的 assign 函数进行对象合并1、简介2、安装与导入3、基础用法4、注意…...

antd upload组件beforeUpload返回promise之后,获取的文件不是file类型导致上传失败

之前的beforeUpload直接返回一个false值 &#xff0c;文件是可以正常与服务端进行传输的 beforeUpload: (file) > {return false},但是这样并不能阻止文件上传&#xff0c;看了官方文档后&#xff0c;改用返回promise对象上传 beforeUpload: (file) > {console.log(-befo…...

创建ffmpeg vs2019工程

0 写在前面 本文主要参考链接&#xff1a;https://www.cnblogs.com/suiyek/p/15669562.html 感谢作者的付出&#xff1b; 1 目录结构 2 下载yasm和nasm 如果自己在安装VS2019等IDE的时候已经安装了它们&#xff0c;则不用再单独进行安装&#xff0c;比如我这边已经安装了&a…...

无涯教程-机器学习 - Jupyter Notebook函数

Jupyter笔记本基本上为开发基于Python的数据科学应用程序提供了一个交互式计算环境。它们以前称为ipython笔记本。以下是Jupyter笔记本的一些功能,使其成为Python ML生态系统的最佳组件之一- Jupyter笔记本可以逐步排列代码,图像,文本,输出等内容,从而逐步说明分析过程。 它有…...

ubuntu安装单机的Consul

文章目录 场景解决启动方式 场景 公司使用Consul做注册发现中心以及管理配置&#xff0c;之前没有用过consul, 现在记录下ubuntu部署的过程 解决 apt 安装 wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-…...

聊聊mybatis-plus的sql加载顺序

序 本文主要研究一下如果mybatis mapper定义了多个同名方法会不会有问题 MybatisConfiguration com/baomidou/mybatisplus/core/MybatisConfiguration.java /*** MybatisPlus 加载 SQL 顺序&#xff1a;* <p> 1、加载 XML中的 SQL </p>* <p> 2、加载 SqlP…...

基于jeecg-boot的flowable流程审批时增加下一个审批人设置

更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbacheng/nbcio-boot 前端代码&#xff1a;https://gitee.com/nbacheng/nbcio-vue.git 在线演示&#xff08;包括H5&#xff09; &#xff1a; http://122.227.135.243:9888 因为有时…...

HTML 与 CSS 有什么区别?

HTML&#xff08;超文本标记语言&#xff09;和 CSS&#xff08;层叠样式表&#xff09;是构建网页的两个核心技术。HTML负责定义网页的结构和内容&#xff0c;而CSS则用于控制网页的样式和布局。虽然它们在构建网页时密切相关&#xff0c;但它们在功能和用途上有明显的区别。 …...

服务器数据恢复-vmware ESXI虚拟机数据恢复案例

服务器数据恢复环境&#xff1a; 从物理机迁移一台虚拟机到ESXI&#xff0c;迁移后做了一个快照。该虚拟机上部署了一个SQLServer数据库&#xff0c;存放了5年左右的数据。ESXI上有数十台虚拟机&#xff0c;EXSI连接了一台EVA存储&#xff0c;所有的虚拟机都在EVA存储上。 服务…...

Rabbitmq的Shovel

Federation 具备的数据转发功能类似&#xff0c; Shovel 够可靠、持续地从一个 Broker 中的队列 ( 作为源端&#xff0c;即source)拉取数据并转发至另一个 Broker 中的交换器 ( 作为目的端&#xff0c;即 destination) 。作为源端的队列和作为目的端的交换器可以同时位于…...

华为手机实用功能介绍

一、内置app介绍 分四块介绍&#xff0c;包括出门款、规划款、工作款和生活款。 出门款&#xff1a;红色框框部分&#xff0c;照镜子化妆/看天气 规划款&#xff1a;黄色框框部分&#xff0c;日程表/计划表/番茄时间/计时 工作款&#xff1a;蓝色框框部分&#xff0c;便笺/录…...

算法题打卡day50-动态规划 | 123.买卖股票的最佳时机III、188.买卖股票的最佳时机IV

123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; 状态&#xff1a;查看索引含义和初始化思路后AC。 增加了两次的限制&#xff0c;相应的就是需要考虑的状态改变&#xff0c;具体的索引含义在代码中&#xff1a; class Solution { public:int maxProfit(…...

jvm与锁

今天是《面霸的自我修养》的第二弹&#xff0c;内容是Java并发编程中关于Java内存模型&#xff08;Java Memory Model&#xff09;和锁的基础理论相关的问题。这两块内容的八股文倒是不多&#xff0c;但是难度较大&#xff0c;接下来我们就一起一探究竟吧。 数据来源&#xff…...

零基础安装pycuda

零基础安装pycuda 前言安装Visual Studio安装C/C环境添加环境变量 安装pycuda查看系统位数查看python版本下载whl文件 前言 最近开始学习基于python的cuda编程&#xff0c;记录一下pycuda的安装。 在安装pycuda之前&#xff0c;首先需要有NVIDIA的独立显卡并且要安装CUDA和CUD…...

Streamlit 讲解专栏(十一):数据可视化-图表绘制详解(中)

文章目录 1 前言2 绘制交互式散点图3 定制图表主题4 增强数据可视化的交互性与注释步骤1步骤二 5 结语 1 前言 在上一篇博文《 Streamlit 讲解专栏&#xff08;十&#xff09;&#xff1a;数据可视化-图表绘制详解&#xff08;上&#xff09;》中&#xff0c;我们学习了一些关…...

d3dx9_35.dll丢失怎么解决

今天&#xff0c;我将为大家介绍关于电脑d3dx9_35.dll丢失的4种详细修复方法。希望通过这次分享&#xff0c;能够帮助大家解决在日常工作和生活中遇到的一些问题。 首先&#xff0c;让我们来了解一下d3dx9_35.dll是什么&#xff1f; d3dx9_35.dll是一个非常重要的动态链接库文…...

Java 大厂面试 200 题完整版含答案解析

前言本文整理了近两年从阿里、腾讯、字节、美团、京东、拼多多等大厂面试中高频出现的 200 道 Java 面试题&#xff0c;覆盖 Java 基础、集合、并发、JVM、Spring、MySQL、Redis、消息队列、分布式、场景设计 等核心模块&#xff0c;每题都附有简明扼要的答案解析&#xff0c;助…...

Thorium浏览器深度解析:5个核心优势与进阶配置实战

Thorium浏览器深度解析&#xff1a;5个核心优势与进阶配置实战 【免费下载链接】thorium Chromium fork named after radioactive element No. 90. Source code and Linux releases. Windows/MacOS/ARM builds served in different repos, links are towards the top of the RE…...

Windows Cleaner终极指南:3分钟彻底解决C盘爆红问题!

Windows Cleaner终极指南&#xff1a;3分钟彻底解决C盘爆红问题&#xff01; 【免费下载链接】WindowsCleaner Windows Cleaner——专治C盘爆红及各种不服&#xff01; 项目地址: https://gitcode.com/gh_mirrors/wi/WindowsCleaner 还在为Windows系统越用越慢而烦恼吗&…...

平衡车PID积分饱和问题

你发现了PID最致命的坑&#xff01; 你说的完全正确&#xff1a;积分&#xff08;Ki&#xff09;是累加的&#xff0c;会无限叠加&#xff0c;直接让PWM爆掉、车猛冲、失控&#xff01; 这就是积分饱和 —— 99%初学者死在这里。 我现在彻底讲透积分为什么炸、怎么修复、平衡车…...

Cursor IDE事件日志分析工具:Python实现开发者行为可视化与效率洞察

1. 项目概述&#xff1a;一个为开发者“把脉”的智能分析工具如果你是一名开发者&#xff0c;尤其是深度使用Cursor这类AI编程助手的开发者&#xff0c;你肯定有过这样的体验&#xff1a;面对一个复杂的项目&#xff0c;你向AI助手提了无数个问题&#xff0c;生成了大量代码片段…...

Shell脚本加固实战:用shellguard提升脚本健壮性与安全性

1. 项目概述&#xff1a;一个为Shell脚本穿上“防弹衣”的守护者 在运维开发、自动化部署乃至日常的系统管理工作中&#xff0c;Shell脚本是我们最忠实、最高效的伙伴。从简单的日志清理到复杂的CI/CD流水线&#xff0c;Shell脚本无处不在。然而&#xff0c;脚本的安全性、健壮…...

从图片到摄像头:用YOLOv8n.pt模型在Win10上实现实时目标检测(代码+命令详解)

从图片到摄像头&#xff1a;用YOLOv8n.pt模型在Win10上实现实时目标检测&#xff08;代码命令详解&#xff09; 当计算机视觉遇上边缘计算&#xff0c;目标检测技术正在重塑人机交互的边界。YOLOv8作为当前最先进的实时检测框架之一&#xff0c;其轻量级版本yolov8n.pt在普通消…...

Mantic.sh:AI驱动的智能命令行工具,让自然语言生成终端命令

1. 项目概述&#xff1a;一个为开发者打造的智能终端伴侣 如果你和我一样&#xff0c;每天有超过一半的工作时间是在终端&#xff08;Terminal&#xff09;里度过的&#xff0c;那你一定对效率有着近乎偏执的追求。敲命令、查日志、管理进程、部署服务……这些重复且琐碎的操作…...

【最新 v2.7.1 版本安装包】OpenClaw 零基础无痛部署,无需命令零代码保姆级快速上手

OpenClaw&#xff08;小龙虾&#xff09;Windows 一键部署保姆级教程 | 10 分钟搭建专属数字员工【点击下载最新OpenClaw安装包】 前言 2026 年开源圈热门 AI 智能体 OpenClaw&#xff08;昵称小龙虾&#xff09;&#xff0c;GitHub 星标突破 28 万&#xff0c;凭借本地运行 …...

树莓派5驱动128x128 LED矩阵:打造复古PICO-8游戏艺术墙

1. 项目概述与核心思路我一直对复古游戏和像素艺术情有独钟&#xff0c;也一直想在家里弄一个既有科技感又能玩的装饰品。最近&#xff0c;我把树莓派5、四块64x64的RGB LED矩阵面板和PICO-8幻想游戏机捣鼓到了一起&#xff0c;成功在墙上挂起了一个128x128像素的“游戏艺术墙”…...