【黑马头条】-day06自媒体文章上下架-Kafka

news2024/11/26 4:20:46

文章目录

  • 今日内容
  • 1 Kafka
    • 1.1 消息中间件对比
    • 1.2 kafka介绍
    • 1.3 kafka安装及配置
    • 1.4 kafka案例
      • 1.4.1 导入kafka客户端
      • 1.4.2 编写生产者消费者
      • 1.4.3 启动测试
      • 1.4.4 多消费者启动
    • 1.5 kafka分区机制
      • 1.5.1 topic剖析
    • 1.6 kafka高可用设计
    • 1.7 kafka生产者详解
      • 1.7.1 同步发送
      • 1.7.2 异步发送
      • 1.7.3 参数详解
        • 1.7.3.1 ack
        • 1.7.3.2 retries
        • 1.7.3.3 消息压缩
    • 1.8 kafka消费者详解
      • 1.8.1 消费者组
      • 1.8.2 消息有序性
      • 1.8.3 提交和偏移量
        • 1.8.3.1 同步提交
        • 1.8.3.2 异步提交
        • 1.8.3.3 同步异步混合提交
    • 1.9 Spring集成kafka
      • 1.9.1 导入依赖
      • 1.9.2 创建配置文件
      • 1.9.3 创建生产者
      • 1.9.4 创建消费者
      • 1.9.5 启动类
      • 1.9.6 测试
    • 1.10 kafka传递对象
      • 1.10.1 创建User
      • 1.10.2 添加User的发送和接收
  • 2 自媒体文章上下架
    • 2.1 接口定义
    • 2.2 Controller
    • 2.3 Service
    • 2.4 通知Article修改文章配置
      • 2.4.1 导入kafka依赖
      • 2.4.2 在Nacos中配置kafka的生产者
      • 2.4.3 自媒体通知Article
      • 2.4.4 在Nacos中配置kafka的消费者
      • 2.4.5 配置ap_article_config表
      • 2.4.6 article端监听
      • 2.4.7 测试


今日内容

在这里插入图片描述

1 Kafka

1.1 消息中间件对比

在这里插入图片描述

在这里插入图片描述

1.2 kafka介绍

在这里插入图片描述

在这里插入图片描述

1.3 kafka安装及配置

在这里插入图片描述

  • Docker安装zookeeper

拉取镜像

docker pull zookeeper:3.4.14

创建容器

docker run -d --name zookeeper -p 2181:2181 zookeeper:3.4.14
  • Docker安装kafka

下载镜像

docker pull wurstmeister/kafka:2.12-2.3.1

创建容器

docker run -d --name kafka \
--env KAFKA_ADVERTISED_HOST_NAME=192.168.204.129 \
--env KAFKA_ZOOKEEPER_CONNECT=192.168.204.129:2181 \
--env KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://192.168.204.129:9092 \
--env KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 \
--env KAFKA_HEAP_OPTS="-Xmx256M -Xms256M" \
--net=host wurstmeister/kafka:2.12-2.3.1

在这里插入图片描述

docker run -d --name kafka \
--env KAFKA_ADVERTISED_HOST_NAME=192.168.204.129 \
--env KAFKA_ZOOKEEPER_CONNECT=192.168.204.129:2181 \
--env KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://192.168.204.129:9092 \
--env KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092 \
--env KAFKA_HEAP_OPTS="-Xmx256M -Xms256M" \
-p 9092:9092 wurstmeister/kafka:2.12-2.3.1

-p 9092:9092做端口映射

1.4 kafka案例

在这里插入图片描述

1.4.1 导入kafka客户端

在heima-leadnews-test模块中创建kafka-demo的模块

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
</dependency>

1.4.2 编写生产者消费者

创建com.heima.kafka.sample包

下面两个类ConsumerQuickStart和ProducerQuickStart类

生产者:

package com.heima.kafka.sample;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;

import java.util.Properties;
 
/**
 * 生产者
 */
public class ProducerQuickStart {
 
    public static void main(String[] args) {
        //1.kafka的配置信息
        Properties properties = new Properties();
        //kafka的连接地址
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"192.168.204.129:9092");
        //发送失败,失败的重试次数
        properties.put(ProducerConfig.RETRIES_CONFIG,5);
        //消息key的序列化器
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
        //消息value的序列化器
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
 
        //2.生产者对象
        KafkaProducer<String,String> producer = new KafkaProducer<String, String>(properties);

        /**
         * 第一个参数:topic 第二个参数:key 第三个参数:value
         */
        //封装发送的消息
        ProducerRecord<String,String> record = new ProducerRecord<String, String>("topic-first","key-001","hello kafka");
 
        //3.发送消息
        producer.send(record);
 
        //4.关闭消息通道,必须关闭,否则消息发送不成功
        producer.close();
    }
 
}

消费者:

public class ConsumerQuickStart {
 
    public static void main(String[] args) {
        //1.添加kafka的配置信息
        Properties properties = new Properties();
        //kafka的连接地址
        properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "192.168.204.129:9092");
        //消费者组
        properties.put(ConsumerConfig.GROUP_ID_CONFIG, "group1");
        //消息的反序列化器
        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("topic-first"));
 
        //当前线程一直处于监听状态
        while (true) {
            //4.获取消息
            ConsumerRecords<String, String> consumerRecords = consumer.poll(Duration.ofMillis(1000));
            for (ConsumerRecord<String, String> consumerRecord : consumerRecords) {
                System.out.println(consumerRecord.key());
                System.out.println(consumerRecord.value());
            }
        }
 
    }
 
}

1.4.3 启动测试

消费者成功收到消息

在这里插入图片描述

1.4.4 多消费者启动

同一个组下只能有一个消费者的收到消息

在这里插入图片描述

如果想一对多,则需要将消费者放在不同组中

在这里插入图片描述

1.5 kafka分区机制

在这里插入图片描述

1.5.1 topic剖析

在这里插入图片描述

在这里插入图片描述

ProducerRecord<String,String> record = new ProducerRecord<String, String>("topic-first","key-001",0,"hello kafka");

在发送消息时可以指定分区partition

1.6 kafka高可用设计

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.7 kafka生产者详解

1.7.1 同步发送

在这里插入图片描述

/**
 * 第一个参数:topic 第二个参数:key 第三个参数:value
 */
//封装发送的消息
ProducerRecord<String,String> record = new ProducerRecord<String, String>("topic-first","key-001","hello kafka");

//3.发送消息
//producer.send(record);

//3.1 同步发送消息
RecordMetadata recordMetadata = producer.send(record).get();
System.out.println("同步发送消息结果:topic="+recordMetadata.topic()+",partition="+recordMetadata.partition()+",offset="+recordMetadata.offset());

发送结果:

同步发送消息结果:topic=topic-first,partition=0,offset=1

1.7.2 异步发送

在这里插入图片描述

//3.2 异步发送消息
producer.send(record, new Callback() {
    @Override
    public void onCompletion(RecordMetadata recordMetadata, Exception e) {
        if(e!=null){
            e.printStackTrace();
        }else{
            System.out.println("异步发送消息结果:topic="+recordMetadata.topic()+",partition="+recordMetadata.partition()+",offset="+recordMetadata.offset());
        }
    }
});

发送结果:

异步发送消息结果:topic=topic-first,partition=0,offset=2

1.7.3 参数详解

1.7.3.1 ack

在这里插入图片描述

1.7.3.2 retries

在这里插入图片描述

1.7.3.3 消息压缩

在这里插入图片描述

1.8 kafka消费者详解

1.8.1 消费者组

在这里插入图片描述

1.8.2 消息有序性

在这里插入图片描述

在这里插入图片描述

1.8.3 提交和偏移量

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

手动提交

//手动提交偏移量
properties.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");
1.8.3.1 同步提交

把enable.auto.commit设置为false,让应用程序决定何时提交偏移量。使用commitSync()提交偏移量,commitSync()将会提交poll返回的最新的偏移量,所以在处理完所有记录后要确保调用了commitSync()方法。否则还是会有消息丢失的风险。

只要没有发生不可恢复的错误,commitSync()方法会一直尝试直至提交成功,如果提交失败也可以记录到错误日志里。

在这里插入图片描述

while (true){
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
    for (ConsumerRecord<String, String> record : records) {
        System.out.println(record.value());
        System.out.println(record.key());
        try {
            consumer.commitSync();//同步提交当前最新的偏移量
        }catch (CommitFailedException e){
            System.out.println("记录提交失败的异常:"+e);
        }
    }
}
1.8.3.2 异步提交

手动提交有一个缺点,那就是当发起提交调用时应用会阻塞。当然我们可以减少手动提交的频率,但这个会增加消息重复的概率(和自动提交一样)。另外一个解决办法是,使用异步提交的API :commitAsync()

在这里插入图片描述

 while (true){
    ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
    for (ConsumerRecord<String, String> record : records) {
        System.out.println(record.value());
        System.out.println(record.key());
    }
    consumer.commitAsync(new OffsetCommitCallback() {
        @Override
        public void onComplete(Map<TopicPartition, OffsetAndMetadata> map, Exception e) {
            if(e!=null){
                System.out.println("记录错误的提交偏移量:"+ map+",异常信息"+e);
            }
        }
    });
}
1.8.3.3 同步异步混合提交

异步提交也有个缺点,那就是如果服务器返回提交失败,异步提交不会进行重试

相比较起来,同步提交会进行重试直到成功或者最后抛出异常给应用。异步提交没有实现重试是因为,如果同时存在多个异步提交,进行重试可能会导致位移覆盖

举个例子,假如我们发起了一个异步提交commitA,此时的提交位移为2000,随后又发起了一个异步提交commitB且位移为3000;commitA提交失败但commitB提交成功,此时commitA进行重试并成功的话,会将实际上将已经提交的位移从3000回滚到2000,导致消息重复消费。

在这里插入图片描述

 try {
    while (true){
        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(1000));
        for (ConsumerRecord<String, String> record : records) {
            System.out.println(record.value());
            System.out.println(record.key());
        }
        consumer.commitAsync();
    }
}catch (Exception e){+
    e.printStackTrace();
    System.out.println("记录错误信息:"+e);
}finally {
    try {
        consumer.commitSync();
    }finally {
        consumer.close();
    }
}

1.9 Spring集成kafka

1.9.1 导入依赖

在kafka-demo中导入依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- kafkfa -->
    <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>
</dependencies>

1.9.2 创建配置文件

在resources下创建文件application.yml

server:
  port: 9991
spring:
  application:
    name: kafka-demo
  kafka:
    bootstrap-servers: 192.168.204.129:9092
    producer:
      retries: 10
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer
    consumer:
      group-id: ${spring.application.name}-test
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

1.9.3 创建生产者

创建com.heima.kafka.controller.HelloController类,负责发送消息

@RestController
public class HelloController {
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;

    @GetMapping("/hello")
    public String hello() {
        kafkaTemplate.send("itcast-topic", "hello kafka");
        return "success";
    }
}

1.9.4 创建消费者

建com.heima.kafka.listener.HelloListener类,负责监听消息

@Component
public class HelloListener {
    @KafkaListener(topics = "itcast-topic")
    public void listen(String message) {
        if(!StringUtils.isEmpty(message)) {
            System.out.println("message = " + message);
        }
    }
}

1.9.5 启动类

@SpringBootApplication
public class KafkaAppication {
    public static void main(String[] args) {
        SpringApplication.run(KafkaAppication.class, args);
    }
}

1.9.6 测试

打开localhost:9991/hello

在这里插入图片描述

已经接收到消息

1.10 kafka传递对象

在这里插入图片描述

1.10.1 创建User

创建com.heima.kafka.pojo.User

@Data
public class User {
    private String username;
    private Integer age;
}

1.10.2 添加User的发送和接收

使用fastjson进行转换

Controller:

@GetMapping("/user")
public String user() {
    User user = new User();
    user.setUsername("zhangsan");
    user.setAge(20);
    kafkaTemplate.send("user-topic", JSON.toJSONString(user));
    return "success";
}

Listener:

@KafkaListener(topics = "user-topic")
public void listenUser(String message) {
    if(!StringUtils.isEmpty(message)) {
        User user = JSON.parseObject(message, User.class);
        System.out.println(user);
    }
}

在这里插入图片描述

2 自媒体文章上下架

在这里插入图片描述

2.1 接口定义

在这里插入图片描述

2.2 Controller

@PostMapping("/down_or_up")
public ResponseResult downOrUp(@RequestBody WmNewsDto wmNewsDto){
    return wmNewsService.downOrUp(wmNewsDto);
}

2.3 Service

接口

ResponseResult downOrUp(WmNewsDto wmNewsDto);

实现

@Override
public ResponseResult downOrUp(WmNewsDto wmNewsDto) {
    // 1.参数检查
    if(wmNewsDto.getId()==null){
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"文章id不能为空");
    }
    // 2.查询文章
    WmNews wmNews = getById(wmNewsDto.getId());
    if(wmNews == null){
        return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"文章不存在");
    }
    // 3.修改文章状态
    if(!wmNews.getStatus().equals(WmNews.Status.PUBLISHED.getCode())){
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"只有已发布的文章才能上下架");
    }
    if(wmNewsDto.getEnable()==null){
        return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"enable不能为空");
    }
    wmNews.setEnable(wmNewsDto.getEnable());
    updateById(wmNews);
    // 4.返回结果
    return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

2.4 通知Article修改文章配置

2.4.1 导入kafka依赖

在heima-leadnews-common模块下导入kafka依赖

<!-- kafkfa -->
<dependency>
    <groupId>org.springframework.kafka</groupId>
    <artifactId>spring-kafka</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
</dependency>

2.4.2 在Nacos中配置kafka的生产者

在自媒体端的nacos配置中心配置kafka的生产者,在heima-leadnews-wemedia下的配置文件中配置kafka

spring:
  kafka:
    bootstrap-servers: 192.168.204.129:9092
    producer:
      retries: 10
      key-serializer: org.apache.kafka.common.serialization.StringSerializer
      value-serializer: org.apache.kafka.common.serialization.StringSerializer

在这里插入图片描述

2.4.3 自媒体通知Article

创建com.heima.common.constants.mNewsMessageConstants常量类,保存kafka的topic.

public class WmNewsMessageConstants {
 
    public static final String WM_NEWS_UP_OR_DOWN_TOPIC="wm.news.up.or.down.topic";
}

注入kafka

@Autowired
private KafkaTemplate<String,String> kafkaTemplate;

发送消息,通知article端修改文章配置

//发送消息,通知article端修改文章配置
if(wmNews.getArticleId() != null){
    Map<String,Object> map = new HashMap<>();
    map.put("articleId",wmNews.getArticleId());
    map.put("enable",dto.getEnable());
    kafkaTemplate.send(WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC,JSON.toJSONString(map));
}

2.4.4 在Nacos中配置kafka的消费者

在article端的nacos配置中心配置kafka的消费者

spring:
  kafka:
    bootstrap-servers: 192.168.204.129:9092
    consumer:
      group-id: ${spring.application.name}
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

在这里插入图片描述

2.4.5 配置ap_article_config表

因为需要修改ap_article_config,所以需要创建对应service和mapper

在这里插入图片描述

创捷Service,com.heima.article.service.ApArticleConfigService接口

public interface ApArticleConfigService extends IService<ApArticleConfig> {
 
    /**
     * 修改文章配置
     * @param map
     */
    public void updateByMap(Map map);
}

实现

@Service
@Slf4j
@Transactional
public class ApArticleConfigServiceImpl extends ServiceImpl<ApArticleConfigMapper, ApArticleConfig> implements ApArticleConfigService {
    /**
     * 修改文章配置
     * @param map
     */
    @Override
    public void updateByMap(Map map) {
        //0 下架 1 上架
        Object enable = map.get("enable");
        boolean isDown = true;
        if(enable.equals(1)){
            isDown = false;
        }
        //修改文章配置
        update(Wrappers.<ApArticleConfig>lambdaUpdate().eq(ApArticleConfig::getArticleId,map.get("articleId")).set(ApArticleConfig::getIsDown,isDown));
    }
}

2.4.6 article端监听

在article端编写监听,接收数据

@Component
@Slf4j
public class ArtilceIsDownListener {
    @Autowired
    private ApArticleConfigService apArticleConfigService;
    @KafkaListener(topics = WmNewsMessageConstants.WM_NEWS_UP_OR_DOWN_TOPIC)
    public void onMessage(String message){
        if(StringUtils.isNotBlank(message)){
            Map map = JSON.parseObject(message, Map.class);
            apArticleConfigService.updateByMap(map);
            log.info("article端文章配置修改,articleId={}",map.get("articleId"));
        }
    }
}

2.4.7 测试

启动相应启动类

在这里插入图片描述

打开自媒体管理界面,准备下架这个新闻

在这里插入图片描述

下架该文件,发现两张表都已经修改,完美进行下架

在这里插入图片描述

说明我们kafka的消息传递已经成功。

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

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

相关文章

吴恩达机器学习笔记:第 7 周-12支持向量机(Support Vector Machines)12.1-12.3

目录 第 7 周 12、 支持向量机(Support Vector Machines)12.1 优化目标12.2 大边界的直观理解 第 7 周 12、 支持向量机(Support Vector Machines) 12.1 优化目标 到目前为止,你已经见过一系列不同的学习算法。在监督学习中&#xff0c;许多学习算法的性能都非常类似&#xf…

【Python】python学生体能考核成绩管理系统(数据库) (源码+报告)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

新版chrome 解决在http协议下无法调用摄像头和麦克风的问题(不安全)

解决办法&#xff1a;亲测可行 chrome浏览器地址栏中输入chrome://flags/#unsafely-treat-insecure-origin-as-secure&#xff0c;回车&#xff0c;如下图&#xff0c;将该选项置为Enabled&#xff0c; edge浏览器打开&#xff1a;edge://flags/#unsafely-treat-insecure-orig…

linux文件访问权限理解

目录 一&#xff0c;涉及指令: 二&#xff0c;权限的表示 三&#xff0c;权限命令使用 一&#xff0c;涉及指令: umask chmod chown/chgrp 二&#xff0c;权限的表示 rwx rwx r-x含义: 访问方式: r-可读;w-可写&#xff1b;x-可执行&#xff1b; 访问用户:u-所有者;…

最新Android Studio导入aar包的方法

以前的方式&#xff0c;目前看网上也大多数都是这种方式&#xff0c;导致我本地加的时候一直有问题 但是这样都无法sync以及编译通过&#xff0c;因为方式已经变了 1&#xff1a;将aar文件复制到MyApplication\app\libs下 2&#xff1a;在MyApplication\app\build.gradle下添加…

LLM大语言模型助力DataEase小助手,新增气泡地图,DataEase开源数据可视化分析平台v2.5.0发布

2024年4月8日&#xff0c;DataEase开源数据可视化分析平台正式发布v2.5.0版本。 这一版本的功能升级包括&#xff1a;新增DataEase小助手支持&#xff0c;通过结合智能算法和LLM&#xff08;即Large Language Model&#xff0c;大语言模型&#xff09;能力&#xff0c;DataEas…

Python(9):一文学懂进程,线程和协程

文章目录 一、进程1.创建多进程2.查看进程id3.进程池4.进程间的互相通信 二、线程1.threading线程模块2.创建多线程3.互斥锁4.死锁5.线程间的互相通信 三、协程1.认识协程2.gevent模块在爬虫中的应用 四、多线程、多进程、协程的区别 分类定义程序一个应用可以当做一个程序&…

广佛站点导航助手小程序产品使用说明书

一、产品简介 广佛站点导航助手小程序是一款专为广佛地区用户设计的地铁导航工具。通过获取用户的实时位置信息&#xff0c;小程序能够迅速定位并展示离用户最近的三个地铁站点。用户可以通过本小程序轻松查找地铁站点&#xff0c;规划出行路线&#xff0c;提高出行效率。 二、…

STM32 串口接收定长,不定长数据

本文为大家介绍如何使用 串口 接收定长 和 不定长 的数据。 文章目录 前言一、串口接收定长数据1. 函数介绍2.代码实现 二、串口接收不定长数据1.函数介绍2. 代码实现 三&#xff0c;两者回调函数的区别比较四&#xff0c;空闲中断的介绍总结 前言 一、串口接收定长数据 1. 函…

计算机网络——网络地址转换(NAT)技术

目录 前言 前篇 引言 SNAT&#xff08;Source Network Address Translation&#xff09;源网络地址转换 SNAT流程 确定性标记 DNAT&#xff08;Destination Network Address Translation&#xff0c;目标网络地址转换&#xff09; NAT技术重要性 前言 本博客是博主用于…

Docker学习笔记(二):在Linux中部署Docker(Centos7下安装docker、环境配置,以及镜像简单使用)

一、前言 记录时间 [2024-4-6] 前置文章&#xff1a;Docker学习笔记&#xff08;一&#xff09;&#xff1a;入门篇&#xff0c;Docker概述、基本组成等&#xff0c;对Docker有一个初步的认识 在上文中&#xff0c;笔者进行了Docker概述&#xff0c;介绍其历史、优势、作用&am…

Linux:软件包管理器 - yum

Linux&#xff1a;软件包管理器 - yum Linux的软件安装方式源代码安装rpm包安装yum安装 yum三板斧yum listyum installyum remove yum生态yum源 Linux的软件安装方式 源代码安装 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序 源代码安…

python+Flask+django企业仓库进销存管理信息系统35wiz

Flask提供了更大的灵活性和简单性&#xff0c;适合小型项目和微服务。Django则提供了更多的内置功能&#xff0c;适合大型项目。Flask让开发者更多的控制其组件&#xff0c;而Django则遵循开箱即用的原则 本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&am…

五大背景图光线手法,附大量案例,可下载原图。

2023-10-01 23:05贝格前端工场 在背景图设计中&#xff0c;使用光线效果可以帮助营造科技感。以下是一些使用光线来表现科技感的设计技巧&#xff1a; 线性光源&#xff1a;使用线性光源可以在背景图中创建出明亮的光线效果。可以在设计中添加一条或多条线性光源&#xff0c;然…

Docker Nginx 部署Vue项目

先弄个ngix镜像&#xff0c;还原到linux里面 发布包放的位置 nginx配置文件 server {listen 8049;server_name localhost;#charset koi8-r;access_log /var/log/nginx/host.access.log main;error_log /var/log/nginx/error.log error;location / {# root 根目录&a…

全速前进:2024年MAD(机器学习,人工智能和数据)前景(20000字长文)

THE 2024 MAD (MACHINE LEARNING, ARTIFICIAL INTELLIGENCE & DATA) LANDSCAPE 是FirstMark对数据、分析、机器学习和人工智能生态系统的第十次年度展望和「现状」描述 。 在这个领域的10多年里&#xff0c;事情从来没有像今天这样令人兴奋和充满希望。我们多年来描述的所…

[STM32+HAL]DengFOC移植之闭环位置控制

一、源码来源 DengFOC官方文档 二、HAL库配置 1、开启硬件IIC低速模式 低速更稳定 2、PWM波开启 三、keil填写代码 1、AS5600读取编码器数值 #include "AS5600.h" #include "math.h"float angle_prev0; int full_rotations0; // full rotation trac…

Day37|贪心算法part06:738.单调递增的数字、968. 监控二叉树、贪心总结

738. 单调递增的数字 总体思想就是从后往前遍历&#xff0c;比较第i位和第i1位的大小&#xff0c;不符合顺序char[i]减1&#xff0c;i1位填9&#xff0c;找到需要填9的最先位置&#xff0c;然后填9。 class Solution {public int monotoneIncreasingDigits(int n) {String s …

负荷预测 | Matlab基于TCN-BiGRU-Attention单输入单输出时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于TCN-BiGRU-Attention单输入单输出时间序列多步预测&#xff1b; 2.单变量时间序列数据集&#xff0c;采用前12个时刻预测未来96个时刻的数据&#xff1b; 3.excel数据方便替换&#xff0c;运行环境matlab…

领域驱动设计(DDD)学习心得

领域驱动设计&#xff08;DDD&#xff09; 领域驱动设计是一种用于复杂软件系统的软件开发方法论。它强调与软件所服务的业务领域的专家紧密合作&#xff0c;通过深入理解业务领域的复杂性&#xff0c;来构建能够反映业务逻辑的领域模型。DDD的核心思想包括以下几点&#xff1…