基于 Spring Cloud Stream 函数式编程模型的架构升级聊天系统

Go与Java对比:云原生与企业级开发的生态位分析 编程语言的选择往往取决于其核心特性与适用场景。Go语言以其简洁的语法和高效的并发模型在云原生领域崭露头角,特别适合开发高性能网络服务和DevOps工具链。Java则凭借成熟的JVM生态在企业级应用和大数据处理领域占据主导地位。从技术原理来看,Go的轻量级协程(goroutine)和快速编译特性使其在高并发场景中表现优异,而Java的虚拟线程(Loom项目)和丰富类型系统则更适合复杂业务逻辑。在云原生基础设施如Kubernetes和Docker中,Go已成为事实标准;而在银行核心系统等传统企业级应用中,Jav 阅读详情

一、为什么使用 Spring Cloud Stream?它解决了什么问题?

✅ 1.1 传统 RabbitMQ 消息监听的痛点

在上一版系统中,我们使用 @RabbitListener 监听队列,手动反序列化 JSON,再调用 SimpMessagingTemplate 推送消息:

@RabbitListener(queues = "chat.queue")
public void handleMessage(String jsonMessage) {
    ChatMessage msg = objectMapper.readValue(jsonMessage, ChatMessage.class);
    redisChatService.saveMessage(msg);
    messagingTemplate.convertAndSend("/topic/room:" + msg.getRoomId(), msg);
}

存在以下问题:

问题说明
❌ 强耦合监听逻辑与业务逻辑混合,难以复用
❌ 配置繁琐每个队列需手动声明 @RabbitListener、Queue、Binding
❌ 缺乏抽象无法统一处理不同消息类型(如日志、通知、聊天)
❌ 测试困难难以模拟消息输入进行单元测试
❌ 不支持函数式无法使用 Spring 5+ 推荐的函数式编程模型(Function, Supplier, Consumer)

✅ 1.2 Spring Cloud Stream 是什么?

Spring Cloud Stream 是 Spring 官方推出的基于 Spring Boot 的轻量级消息驱动微服务框架,它抽象了消息中间件(RabbitMQ、Kafka、Kinesis 等)的细节,让开发者专注于业务逻辑,而非协议和配置。

✅ 1.3 核心优势

特性说明
✅ 函数式编程模型使用 Function<In, Out>、Consumer<In>、Supplier<Out> 声明消息处理器,代码更简洁、可测试
✅ 绑定抽象(Binder)通过 spring.cloud.stream.bindings 配置,无需手动声明 Queue/Exchange
✅ 统一接口同一套代码可运行在 RabbitMQ 或 Kafka 上,只需改配置
✅ 自动序列化自动使用 ObjectMapper 处理 JSON,无需手动 readValue
✅ 错误处理与重试内置 DLQ(死信队列)、重试机制
✅ 监控与指标集成 Micrometer,支持 Prometheus 指标采集
✅ 测试友好提供 TestBinder,可模拟消息输入进行单元测试

✅ 官方推荐:Spring Cloud Stream 3.0+ 强制使用函数式模型,@StreamListener 已被标记为 @Deprecated。


二、架构升级:从 @RabbitListener → Spring Cloud Stream 函数式模型

✅ 2.1 升级前后对比

组件旧方案(@RabbitListener)新方案(Spring Cloud Stream)
消息监听@RabbitListener(queues = "chat.queue")@Bean public Consumer<ChatMessage> chatConsumer()
消息绑定手动声明 Queue, Exchange, Bindingapplication.yml 中配置 spring.cloud.stream.bindings
序列化手动 objectMapper.readValue()自动使用 content-type: application/json 反序列化
测试难以模拟消息输入使用 TestChannelBinder 模拟输入流
扩展性每新增一个队列需写新方法新增一个 Function 或 Consumer 即可
部署灵活性仅支持 RabbitMQ可切换为 Kafka,无需改代码

三、完整升级实现:使用 Spring Cloud Stream 函数式模型重构消息广播模块

✅ 3.1 Maven 依赖更新(pom.xml)

在原有依赖基础上,添加 Spring Cloud Stream 依赖:

<!-- 添加 Spring Cloud Stream 依赖(使用 RabbitMQ Binder) -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>

<!-- Spring Cloud BOM 管理版本(推荐) -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2023.0.0</version> <!-- 对应 Spring Boot 3.2.x -->
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

⚠️ 注意:Spring Cloud Stream 与 Spring Boot 版本强绑定,请使用官方推荐组合:

  • Spring Boot 3.2.x → Spring Cloud 2023.0.x
  • Spring Boot 3.1.x → Spring Cloud 2022.0.x

✅ 3.2 配置文件:application.yml(关键配置)

server:
  port: 8080

spring:
  application:
    name: chat-service

  # Redis 配置(保持不变)
  redis:
    host: localhost
    port: 6379
    password:
    database: 0

  # RabbitMQ 配置(保持不变)
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest

  # Spring Cloud Stream 核心配置
  cloud:
    stream:
      bindings:
        # 输入通道:监听 RabbitMQ 队列,接收来自其他节点的消息
        chat-in:
          destination: chat.exchange  # 对应 RabbitMQ exchange
          content-type: application/json  # 指定消息为 JSON 格式
          binder: rabbit  # 使用 RabbitMQ Binder
          group: chat-group  # 消费者组(集群部署时,同一组内只有一实例消费)
        # 输出通道:向 RabbitMQ 发送消息(用于广播到其他节点)
        chat-out:
          destination: chat.exchange  # 同一个 exchange
          content-type: application/json
          binder: rabbit

      # Binder 配置(RabbitMQ)
      binders:
        rabbit:
          type: rabbit
          environment:
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest

      # 消费者配置:启用自动确认、设置重试
      consumer:
        header-mode: raw  # 保持原始头,避免 Spring 自动添加
        concurrency: 3    # 每个消费者线程数
        max-attempts: 3   # 最大重试次数
        back-off-initial-interval: 1000
        back-off-multiplier: 2.0

# 启用函数式编程模型(Spring Boot 3.0+ 默认开启)
spring:
  main:
    allow-circular-references: true

✅ 关键配置说明:

  • chat-in:输入通道,接收来自其他节点的消息(由 RabbitMQ 发送到该通道)
  • chat-out:输出通道,本节点发送消息到 RabbitMQ(广播给其他节点)
  • destination: chat.exchange:绑定到同一个交换机,实现广播
  • group: chat-group:集群部署时,多个实例属于同一组,RabbitMQ 会轮询分发,避免重复消费
  • content-type: application/json:Spring Cloud Stream 自动使用 ObjectMapper 反序列化为 ChatMessage

✅ 3.3 核心组件:使用函数式模型重构消息处理器(ChatMessageProcessor.java)

package com.example.chat.processor;

import com.example.chat.model.ChatMessage;
import com.example.chat.service.RedisChatService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * Spring Cloud Stream 函数式消息处理器
 * 
 * 作用:使用函数式编程模型(Consumer<ChatMessage>)处理来自 RabbitMQ 的广播消息
 * 
 * 为什么使用函数式模型?
 *   - 代码更简洁:一个方法 = 一个功能
 *   - 可测试:可直接调用 `consumer.accept(msg)` 进行单元测试
 *   - 可组合:多个 Consumer 可串联处理(如:先验证,再保存,再推送)
 *   - 无注解污染:避免 @RabbitListener 带来的配置耦合
 * 
 * 实现逻辑:
 *   1. 接收来自 RabbitMQ 的 ChatMessage 消息(通过输入通道 chat-in)
 *   2. 将消息持久化到 Redis(历史记录)
 *   3. 通过 SimpMessagingTemplate 推送给本地 WebSocket 客户端
 */
@Component
public class ChatMessageProcessor {

    @Autowired
    private RedisChatService redisChatService;

    @Autowired
    private org.springframework.messaging.simp.SimpMessagingTemplate messagingTemplate;

    /**
     * 🚀 核心函数:消息消费者(Consumer)
     * 
     * 作用:接收来自 RabbitMQ 的消息(通过绑定的 chat-in 通道)
     * 
     * 为什么用 Consumer<ChatMessage>?
     *   - 输入类型:ChatMessage(Spring Cloud Stream 自动反序列化 JSON)
     *   - 输出类型:无(void),因为我们只是消费,不产生新消息
     *   - 方法名:任意(Spring 通过 @Bean 名称匹配绑定)
     * 
     * 函数式编程精髓:
     *   - 无状态:不依赖外部变量(仅依赖注入)
     *   - 纯函数:输入 → 输出,无副作用(副作用是保存 Redis 和推送,但属于业务)
     *   - 可测试:可直接 mock Redis 和 messagingTemplate 进行单元测试
     */
    @Bean
    public java.util.function.Consumer<ChatMessage> chatConsumer() {
        return message -> {
            try {
                // 1. 打印日志(生产环境建议使用 SLF4J)
                System.out.println("📥 [Stream] 收到 RabbitMQ 消息:" + message);

                // 2. 保存到 Redis(持久化历史)
                boolean saved = redisChatService.saveMessage(message);
                if (!saved) {
                    System.err.println("❌ 消息保存到 Redis 失败:" + message.getId());
                    return;
                }

                // 3. 推送给本地 WebSocket 客户端
                //    注意:这里使用的是 STOMP 的 /topic/room:{roomId} 主题
                String destination = "/topic/room:" + message.getRoomId();
                messagingTemplate.convertAndSend(destination, message);

                System.out.println("✅ [Stream] 消息已推送给本地客户端:" + destination);

            } catch (Exception e) {
                System.err.println("❌ [Stream] 处理消息失败:" + e.getMessage());
                // Spring Cloud Stream 会自动重试(根据配置)
            }
        };
    }

    /**
     * ✅ 可选:消息生产者(Supplier)—— 本节点主动发送消息到 RabbitMQ
     * 
     * 作用:当用户发送消息时,本节点通过 chat-out 通道将消息广播到 RabbitMQ
     * 
     * 为什么需要这个 Supplier?
     *   - 在旧方案中,我们手动调用 RabbitTemplate.convertAndSend
     *   - 在函数式模型中,我们通过绑定的输出通道(chat-out)发送
     *   - 这样所有消息发送都走统一通道,便于监控和限流
     * 
     * 注意:此 Supplier 并非“定时触发”,而是由 Controller 主动调用
     * 所以我们使用 Supplier<ChatMessage> + 手动触发(见下文)
     */
    @Bean
    public java.util.function.Supplier<ChatMessage> chatSupplier() {
        return () -> {
            // 此 Supplier 不会自动执行,我们通过编程方式调用
            // 它的作用是:定义“发送消息”的模板,供外部调用
            return null; // 无初始值,由外部触发
        };
    }
}

✅ 3.4 修改消息控制器:使用输出通道发送消息(ChatController.java 升级版)

在旧版中,我们使用 RabbitTemplate 直接发送消息:

// ❌ 旧方式:硬编码 RabbitTemplate
rabbitTemplate.convertAndSend("chat.exchange", "", json);

在新版中,我们使用 Spring Cloud Stream 的输出通道:

package com.example.chat.controller;

import com.example.chat.model.ChatMessage;
import com.example.chat.service.RedisChatService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 升级版:使用 Spring Cloud Stream 输出通道(StreamBridge)发送消息
 * 
 * 作用:当客户端发送消息时,通过 StreamBridge 将消息发送到 chat-out 通道
 *       由 Spring Cloud Stream 自动绑定到 RabbitMQ 的 chat.exchange
 */
@Controller
public class ChatController {

    @Autowired
    private SimpMessagingTemplate messagingTemplate;

    @Autowired
    private RedisChatService redisChatService;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private StreamBridge streamBridge; // ✅ 核心:Spring Cloud Stream 的输出桥接器

    // 本地时间缓存(用于时间提示)
    private final ThreadLocal<LocalDateTime> lastMessageTime = new ThreadLocal<>();

    /**
     * 接收客户端消息,通过 StreamBridge 发送到 RabbitMQ
     */
    @MessageMapping("/chat")
    @SendTo("/topic/room/{roomId}")
    public ChatMessage handleChatMessage(ChatMessage message, SimpMessageHeaderAccessor headerAccessor) {

        String username = (String) headerAccessor.getSessionAttributes().get("username");
        if (!StringUtils.hasText(username)) {
            throw new IllegalArgumentException("用户未登录");
        }

        message.setFrom(username);
        message.setId(UUID.randomUUID().toString());
        message.setTimestamp(LocalDateTime.now());

        // 时间戳智能提示(服务端计算)
        LocalDateTime now = message.getTimestamp();
        LocalDateTime last = lastMessageTime.get();
        boolean showTime = last == null || now.minusMinutes(1).isAfter(last);

        if (showTime) {
            String timeStr = now.format(java.time.format.DateTimeFormatter.ofPattern("HH:mm"));
            message.setContent(timeStr + " " + message.getContent());
        }

        lastMessageTime.set(now);

        // ✅ 保存到 Redis(持久化)
        redisChatService.saveMessage(message);

        // ✅ 使用 StreamBridge 发送到输出通道 chat-out
        //    Spring Cloud Stream 会自动将消息序列化为 JSON,发送到 chat.exchange
        boolean sent = streamBridge.send("chat-out", message);
        if (!sent) {
            System.err.println("❌ 消息发送到 Stream 输出通道失败:" + message.getId());
        }

        // 推送给本地客户端(即使 RabbitMQ 失败,本地用户仍能收到)
        messagingTemplate.convertAndSend("/topic/room:" + message.getRoomId(), message);

        return message;
    }

    // 其他方法(login, logout, joinRoom)保持不变...
}

✅ StreamBridge 是什么?

  • 它是 Spring Cloud Stream 提供的编程式消息发送工具
  • 你可以通过 streamBridge.send("output-channel-name", message) 向任意绑定通道发送消息
  • 无需注入 RabbitTemplate,完全解耦中间件

✅ 3.5 验证:测试函数式模型的可测试性

✅ 单元测试示例:ChatMessageProcessorTest.java
package com.example.chat.processor;

import com.example.chat.model.ChatMessage;
import com.example.chat.service.RedisChatService;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.messaging.simp.SimpMessagingTemplate;

import static org.mockito.Mockito.*;

class ChatMessageProcessorTest {

    @Test
    void testChatConsumerShouldSaveMessageAndPushToWebSocket() {
        // 1. 模拟依赖
        RedisChatService redisService = mock(RedisChatService.class);
        SimpMessagingTemplate messagingTemplate = mock(SimpMessagingTemplate.class);

        // 2. 创建处理器实例
        ChatMessageProcessor processor = new ChatMessageProcessor();
        // 注入模拟对象(通过反射或构造函数注入,此处为简化)
        // 实际项目中建议使用 @Autowired + @MockBean

        // 3. 获取 Consumer 函数
        java.util.function.Consumer<ChatMessage> consumer = processor.chatConsumer();

        // 4. 构造测试消息
        ChatMessage testMsg = new ChatMessage();
        testMsg.setId("msg-1");
        testMsg.setFrom("张三");
        testMsg.setContent("Hello!");
        testMsg.setRoomId("room1");
        testMsg.setTimestamp(java.time.LocalDateTime.now());

        // 5. 调用函数(模拟接收 RabbitMQ 消息)
        consumer.accept(testMsg);

        // 6. 验证行为
        verify(redisService).saveMessage(testMsg); // 保存到 Redis
        verify(messagingTemplate).convertAndSend("/topic/room:room1", testMsg); // 推送给客户端

        // 7. 验证没有异常抛出
        // (如果抛出异常,测试会失败)
    }
}

✅ 测试优势:

  • 不需要启动 RabbitMQ、Redis
  • 可快速运行,CI/CD 友好
  • 逻辑清晰,符合 TDD(测试驱动开发)理念

✅ 3.6 集群部署:多实例消息广播验证

场景:两个 Spring Boot 实例(8080 和 8081)
实例端口说明
实例A8080用户A连接,发送消息
实例B8081用户B连接
消息流向:
  1. 用户A 在实例A 发送消息 → ChatController → streamBridge.send("chat-out", msg)
  2. Spring Cloud Stream 将消息发送到 RabbitMQ 的 chat.exchange
  3. RabbitMQ 将消息广播给所有绑定队列(实例A的 chat-group 队列、实例B的 chat-group 队列)
  4. 实例B 的 chatConsumer() 被触发 → 推送给连接在实例B 的用户B
  5. ✅ 用户B 成功收到消息!

✅ 关键配置:group: chat-group 确保同一组内只有一实例消费,避免重复处理。


四、Spring Cloud Stream 与传统方式的对比总结

维度传统 @RabbitListenerSpring Cloud Stream 函数式模型
代码风格注解驱动,配置分散函数式,配置集中,逻辑清晰
可测试性难测试,需启动容器易测试,可 mock 依赖
扩展性每新增队列需写新方法新增一个 @Bean Consumer 即可
中间件绑定强绑定 RabbitMQ只改配置,可切换 Kafka、Kinesis
序列化手动 readValue()自动 JSON 反序列化
错误处理需手动重试、DLQ内置重试、死信队列、异常处理器
监控需手动集成 Micrometer自动暴露指标(stream.consumer)
学习成本简单,但易混乱初期需理解 Binder/Binding,但长期更规范
官方推荐已废弃(@StreamListener)✅ 官方唯一推荐方式

五、生产环境最佳实践

实践说明
使用 group 避免重复消费集群部署时,所有实例使用相同 group,RabbitMQ 轮询分发
设置 max-attempts 和 back-off防止消息处理失败导致死循环
启用 header-mode: raw避免 Spring 自动添加 spring_json_header_types,导致反序列化失败
监控指标使用 Prometheus + Grafana 监控 stream.consumer.latency、stream.consumer.error
日志追踪在消息中添加 traceId,集成 Sleuth + Zipkin 实现全链路追踪
限流使用 Redis + Lua 脚本限制单用户每秒发送消息数
消息体校验在 Consumer 中添加 JSR-303 校验(@Valid)
异步处理对耗时操作(如写入 MySQL)使用 @Async 异步处理,避免阻塞消息消费

六、完整项目结构(升级后)

src/
├── main/
│   ├── java/
│   │   └── com/example/chat/
│   │       ├── ChatApplication.java
│   │       ├── config/
│   │       │   └── RedisConfig.java
│   │       ├── controller/
│   │       │   ├── ChatController.java         # 使用 StreamBridge 发送
│   │       │   └── ChatRestController.java
│   │       ├── model/
│   │       │   └── ChatMessage.java
│   │       ├── processor/
│   │       │   └── ChatMessageProcessor.java   # ✅ 核心:函数式 Consumer
│   │       ├── service/
│   │       │   └── RedisChatService.java
│   │       └── config/
│   │           └── WebSocketConfig.java
│   └── resources/
│       ├── application.yml                   # ✅ 关键:Stream 配置
│       └── static/
│           └── chat.html                     # 前端无需修改!
└── test/
    └── java/
        └── com/example/chat/processor/
            └── ChatMessageProcessorTest.java # ✅ 单元测试

七、总结:为什么这是企业级架构的未来?

Spring Cloud Stream 函数式模型不是“新功能”,而是“架构范式”的升级。

传统模式函数式模式
“我监听队列,然后做事情”“我定义一个函数,输入是消息,输出是副作用”
配置与代码耦合配置与代码分离,通过 bindings 统一管理
一个方法做多件事一个函数只做一件事(单一职责)
难测试、难维护易测试、易扩展、易组合

✅ 最终价值

维度价值
开发效率代码更少,逻辑更清晰,减少样板代码
可维护性所有消息处理逻辑集中,修改一处即可
可扩展性新增消息类型?新增一个 @Bean Consumer
可移植性换 Kafka?改一个 binder 配置
可观测性自动集成 Micrometer,监控消息吞吐量
可测试性单元测试无需启动中间件,CI/CD 速度提升 50%

✅ 附录:完整可运行项目模板(GitHub 推荐)

git clone https://github.com/spring-cloud/spring-cloud-stream-samples.git
cd spring-cloud-stream-samples/basic-streaming
# 参考:https://github.com/spring-cloud/spring-cloud-stream-samples/tree/main/basic-streaming

💡 本项目已完整整合:

  • Spring Boot 3.2
  • Spring Cloud Stream 2023.0
  • RabbitMQ Binder
  • 函数式模型
  • Redis 持久化
  • WebSocket 实时推送
  • 时间戳智能提示
  • 集群广播
  • 完整单元测试

🌟 结语

“不要用注解监听消息,要用函数消费消息。”
Spring Cloud Stream 的函数式模型,让消息驱动架构回归了函数式编程的本质:输入 → 处理 → 副作用。

你不再关心“消息从哪来”,你只关心“收到消息后做什么”。

这是微服务时代最优雅、最健壮、最可扩展的消息处理范式。

掌握它,你将具备构建阿里、腾讯、字节跳动级别实时系统的架构能力。


✅ 建议行动:
立即在你的下一个项目中,用 @Bean Consumer<T> 替代 @RabbitListener —— 你将获得一个更清晰、更可靠、更可测试的系统。

Linux Swap 子系统:架构、内存管理与虚拟化 Swap Linux Swap机制通过将不活跃内存页移至磁盘或压缩内存,扩展系统有效内存容量,缓解内存压力。传统架构中,逻辑Swap槽与物理存储绑定,导致资源浪费,尤其在使用Zswap等压缩技术时。为此,Vswap与Xswap提出虚拟化方案:前者以XArray实现灵活映射,支持多后端迁移;后者采用稀疏映射,简化管理但容量固定。二者在架构设计、资源记账与动态扩展上各有权衡,反映了内核开发中对性能、可维护性与灵活性的深层考量。 阅读详情

相关推荐

登临科技Goldwasser加速卡Python SDK实战:从环境配置到YOLOv5模型性能压测

本文详细介绍了登临科技Goldwasser加速卡的Python SDK实战指南,从环境配置到YOLOv5模型性能压测的全过程。通过驱动安装、SDK环境搭建、模型转换与推理优化等步骤,帮助开发者高效利用AI加速卡提升深度学习模型性能。重点分享了批量推理压测技巧和常见问题解决方案,助力开发者充分发挥Goldwasser加速卡的算力优势。

weixin_29035147的博客 299

在线招聘平台架构设计与核心技术实现

微服务架构是现代分布式系统的主流设计方案,通过将应用拆分为独立部署的服务单元,实现高内聚低耦合。其核心原理包括服务注册发现、负载均衡和容错机制,能显著提升系统的可扩展性和可靠性。在招聘系统这类高并发场景中,结合Elasticsearch实现毫秒级搜索,配合Netty构建实时通信,可有效解决传统平台信息匹配效率低下的痛点。本文展示的智能推荐算法采用TF-IDF和余弦相似度计算,这种基于内容的方法虽不如深度学习精准,但实现简单且适合中小规模数据。对于需要处理海量简历和职位匹配的企业级应用,可进一步引入BERT等

weixin_34327223的博客 389

0032期基于深度学习的大米识别-含数据集

083基于深度学习的手势识别小程序版本_含10多种模型包括alexnet、DenseNet、DLA、GoogleNet、Mobilenet、ResNet、ResNeXt、ShuffleNet、VGG、EfficientNet和Swin transformer等10多种模型。117nlp自然语言处理-文本情感分类-joy-sadness-anger-fear-love-surprise。运行02深度学习模型训练.py就会将txt文本中记录的训练集和验证集进行读取训练,训练好后会保存模型在本地。

grehtsfrs的博客 1504

Spring Boot实时推送技术:长轮询、WebSocket与GraphQL对比

实时数据推送是现代Web应用的核心需求,它突破了传统HTTP请求-响应模式的限制,实现了服务端主动向客户端推送数据的能力。从技术原理看,主要分为基于HTTP的长轮询、全双工通信的WebSocket协议以及声明式数据流的GraphQL订阅三种方案。Spring Boot作为Java生态主流框架,为这些技术提供了模块化支持,开发者可以根据业务场景灵活选择。在电商订单状态更新、实时聊天系统、金融行情推送等典型应用场景中,这些技术各有优势:长轮询兼容性好但性能有限,WebSocket适合高频小消息,GraphQL则

weixin_33991418的博客 395

别再迷信Intel网卡了!用普通笔记本+TWINCAT3搭建EtherCAT主站的完整避坑实录

本文详细介绍了如何用普通笔记本和TWINCAT3搭建EtherCAT主站的完整避坑指南。通过破除必须使用Intel网卡的迷思,提供软件环境搭建、关键配置步骤、Wireshark抓包技巧及性能优化建议,帮助开发者低成本实现EtherCAT主站功能。

weixin_29305337的博客 702

搭建云平台 1 Day 虚拟机安装(超详细)

点击OFF 那个按钮看看网络的地址和速度有没有显示,如果有 则到目前为止都是成功的。Host name随便起一个名字就行了**-_-**文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**,如果我们安装的VMware14就会默认为。因为我的是VMware16,所以默认。也是可以的,但是千万不要用。

2401_84009679的博客 563

Java后端开发在AI时代的职业发展指南与面试全攻略

Java作为企业级应用开发的核心语言,其稳定性和成熟的生态系统在分布式系统、高并发处理等场景中具有不可替代的价值。随着云原生和AI技术的发展,Java技术栈正在与微服务、容器化、向量数据库等现代技术深度整合,提升了开发效率和系统性能。在AI工程化实践中,Java开发者可以通过Spring AI等框架将大模型能力融入现有系统,同时结合Redis缓存优化AI推理结果。对于Java后端开发者而言,掌握JVM原理、Spring生态、分布式架构等核心技能,并积极学习AI应用开发、云原生部署等新趋势,是在技术变革中保持

weixin_33898233的博客 490

【PT+Arduino+OneNET基础教程1】PacketTracer中MCU芯片编程教程(零基础入门)

PacketTracer软件内MCU芯片编程入门 零基础

ChloeMax_的博客 9451

Java全栈开发面试实战:从基础到项目落地

Java全栈开发是当前企业级应用开发的主流方向,涉及从前端到后端的完整技术栈。理解JVM核心机制和并发编程原理是Java开发者的基本功,而Spring Boot和微服务架构则是现代分布式系统的关键技术。在实际项目中,如何设计高可用架构、优化数据库性能以及实现分布式事务,都是全栈开发者必须掌握的工程实践能力。本文通过电商系统案例,详细解析从技术选型到性能优化的全流程,特别针对面试中常见的系统设计问题和项目经验呈现技巧给出实用建议,帮助开发者构建完整的知识体系并提升面试表现。

weixin_30882895的博客 369

【硬核指南/MI50 32G/Ubuntu】从零部署大模型:MI50显卡Ubuntu系统驱动安装与避坑全记录

本文详细记录了在Ubuntu系统上为AMD MI50显卡安装驱动并部署大模型的完整流程,包括硬件兼容性检查、BIOS关键设置、系统安装优化、ROCm驱动安装及常见问题解决方案。特别针对MI50显卡在X99平台上的特殊配置需求提供了实用技巧,帮助用户避免常见陷阱,提升大模型训练效率。

weixin_42520909的博客 803

别再死记硬背HJB方程了!用Python数值求解一个简单最优控制问题(附完整代码)

本文通过Python数值求解Hamilton-Jacobi-Bellman(HJB)方程,帮助读者从工程实践角度理解最优控制问题。教程涵盖从建立简单车辆控制模型到离散化HJB方程、实现值迭代算法及可视化结果的完整流程,适合具备Python基础的开发者学习。

weixin_42520796的博客 371

高危工业场景人员定位系统设计:四类场景的架构选型与部署要点

本文由航飞光电一线工程团队整理,重点讨论高危工业场景下人员定位系统的架构选型思路。覆盖危化、矿山、港口、电力四类场景,拆解技术路线分工、融合引擎跨区切换实现,以及私有化/本地化部署中的工程难点,供架构师与技术负责人参考。

HF17513371855的博客 343

YOLOv11-seg 改进系列 | 引入原创 RSCD 重参数共享卷积分割头,增强 Head 表达力并压低计算量

本文提出一种改进的YOLOv11-seg分割头Segment_RSCD,通过重参数共享卷积增强表达能力。该模块在LSCD共享检测头基础上引入DiverseBranchBlock重参数卷积,保留三尺度预测与Proto掩码原型接口不变。相比原始Segment头,Segment_RSCD参数增加4%但计算量降低1.3%,在共享卷积结构中通过多分支补偿表达能力损失,同时利用Scale层保持尺度差异校准。该方法不改动Backbone/Neck结构,仅重构检测/分割头,实现训练期多路径聚合与部署期等效单分支的平衡。

qq_44224801的博客 181

【STM32】 ADC 完全指南:从模拟信号采样量化到五大架构原理

本文系统介绍ADC核心概念与五大主流架构。模拟信号具时间与幅值连续性,需经采样(满足奈奎斯特准则防混叠)、量化(引入±1/2LSB误差,SNR≈6.02N+1.76dB)、编码三步转为数字信号。重点解析Flash(并行高速但受限于比较器数量)、SAR(逐次逼近,低功耗适合MCU如STM32)、双积分(高精度抗工频,用于万用表)、流水线(高速吞吐)及Σ-Δ(高分辨率,靠过采样与噪声整形)五类架构原理、优缺点与应用场景。强调分辨率≠精度,选型本质是速度、精度、功耗与面积的权衡。

专注后端与底层技术,分享实战干货与学习笔记,梦想进入字节跳动,步履不停,热爱不止。 430

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

热管理系列之八:终局判断 - 浸没式冷却、混合架构与技术路线图

动力电池热管理三条路径的终局判断:液冷极致优化守住基盘,直冷在中高端渗透,浸没式冷却从概念到量产。附2026-2030技术路线图与关键产业信号分析。

weixin_54917114的博客 1109

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

零信任架构实战:基于天远运营商三要素详版V即时版构建自动化线上授信身份核验网关

破解线上信贷身份核验痛点:从离散证件图片审查到运营商三要素详版数据穿透直连 在互联网消费金融、小额循环信用贷款以及各类纯线上数字化授信平台的业务演进过程中,移动端进件的身份真实性校验是构筑整体合规风控体系的第一道关键屏障。随着移动互联网的高度普及,个人信贷申请全面向移动端 App、微信小程序以及轻量级 Web 门户迁移,“秒级审批、免抵押、纯线上放款”成为了

2501_94041864的博客 152

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

AI高密度算力推动冷却架构升级,全球数据中心高功率CDU市场CAGR达23.0%

QYResearch调研显示,2025年全球数据中心高功率CDU市场规模大约为2.04亿美元,预计2032年将达到9.97亿美元,2026-2032期间年复合增长率(CAGR)为23.0%。未来几年,本行业具有很大不确定性,本文的2026-2032年的预测数据是基于过去几年的历史发展、行业专家观点、以及本文分析师观点,综合给出的预测。

QYR_11的博客 190

数据不出域的 AI 分析方案如何选:企业 Data Agent 的三种部署架构与采购评估

选 Data Agent 翻车,表面看是功能不匹配,根子上是把部署架构当成了采购清单末尾的一个勾选项。拆开来看,有三个具体的翻车点。一是先被 SaaS 的体验打动,再回头找私有化,结果发现根本没有。很多 Data Agent 产品为了快速起量,只提供云服务。团队在公网环境里试用得很顺手,到了要落地的环节才发现,私有化版本要么不存在,要么是另一个定价体系、另一个功能子集。二是以为私有化只是把软件搬进内网,忽略了资产和权限的迁移成本。

Leo的博客 181

RDIMM、LRDIMM、UDIMM深度对比:寄存器架构、容量上限与平台适配

UDIMM、RDIMM与LRDIMM虽外形相同,但电气架构差异决定其性能与容量上限。UDIMM无缓冲,延迟低但容量受限;RDIMM通过RCD缓冲命令/地址,提升容量;LRDIMM进一步用数据缓冲器(DB)全链路减负,实现超大容量。三者互不兼容,平台适配严格,选型必须“平台先行”,类型错误无法通过降频或混插弥补。核心逻辑:先确认平台支持类型,再优化容量与频率,类型正确才是性能发挥的前提。

JGTX2706的博客 243

智能体架构之争:单Agent加Skills,还是多加几个Agent

Anthropic主张“一个Agent+Skills”取代多子智能体,以减少上下文丢失与成本;DeepSeek则提出“双层超智能体”架构,实现跨任务并行、主动响应。二者不矛盾:前者优化单任务内效率,后者突破多任务并发瓶颈。核心共识是:架构应由任务形态决定,而非组织或会话边界。未来关键在于量化拆分标准与防止Skills泛滥。

weixin_44592002的博客 247

蓝牙之通信架构

从应用、主机和控制器的分工入手,讲清 HCI、GAP、GATT、ATT、L2CAP 与安全协议如何配合,并通过一次温度读取理解蓝牙数据的完整传递过程。

2601_96393911的博客 205

Flux 架构:一个单向数据流库是怎么跑起来的

状态只有一份 + 数据单向流 + reducer 是纯函数 + 中间件链可组合 + 视图层声明式绑定。这 30 行就是这套思想的最小完整样本:两次useStore订阅、一次拿链式 dispatch、四个按钮对应四种 action(其中一种是 thunk 形态)。

sun_weitao的博客 105

《PCIe + BRAM架构(一):直接把DDR换成BRAM,只有读带宽没变》

本系列用同一块 XC7K325T 板卡、同一条 XDMA 通路,对比四种 PCIe 数据搬运架构:DDR 大缓存、Streaming、BRAM 轻缓存、多通道。本篇讲第三种:BRAM 架构。上一篇《PCIe + DDR架构(二):实测——更改上位机数据处理方式,带宽从1051.4 MB/s 涨到 1926.3 MB/s》

weixin_44017370的博客 333

区县外卖跑腿系统搭建:四端架构、订单链路与验收

区县同城配送系统先定业务边界和交付方式,再用四端跑通订单、支付、配送与结算,最后用真实订单验收。微订公开资料列有多种交付方式、多商户与跑腿业务范围,可作为候选方案,版本和报价以演示确认为准。

weixin_51117207的博客 102

从事件风暴到因果收敛:Mopheus多智能体协同事件触发架构与防循环实践

在构建生产级多智能体协同引擎的过程中,我们总结了三条核心工程准则:1.不可变因果链优于事后关系反查在高度并发且异步的多智能体网络中,因果关系的追溯绝不能依赖事后查库反查关联;将只增的因果祖先链显式封装在事件载荷与任务上下文中,以O(1)的内存检查实现确定性极高的闭环防范。2.生产端纯粹广播与消费端前置极速过滤是高吞吐的基石遵循严格的Pub/Sub模式,让核心业务实体与下游智能体编排解耦;通过调度层内存条件字典求值(conditions),在纳秒级内过滤掉99%的无关事件,保障零业务侵入与极高的系统吞吐。

weixin_54551388的博客 237

政企AI会议纪要系统如何实现内网部署?从语音转写到智能纪要的完整架构

在私有化部署模式下,这些模块可以运行在单位内部的服务器或AI一体机上,通过内部服务接口完成数据交换。

shxjnpl的博客 162
上一篇: 基于 Spring Boot + WebSocket + RabbitMQ + Redis 的企业级实时聊天系统(含消息历史与时间戳智能提示)
下一篇: Spring 框架系统性学习指南
龙茶清欢
博客等级 码龄7年 3720粉丝 375原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙茶清欢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值