Spring Cloud Stream实现数据流处理

news/2024/11/29 17:44:36/

1.什么是Spring Cloud Stream?

Spring Cloud Stream的核心是Stream,准确来讲Spring Cloud Stream提供了一整套数据流走向(流向)的API, 它的最终目的是使我们不关心数据的流入和写出,而只关心对数据的业务处理 我们举一个例子:你们公司有一套系统,这套系统由多个模块组成,你负责其中一个模块。数据会从第一个模块流入,处理完后再交给下一个模块。对于你负责的这个模块来说,它的功能就是接收上一个模块处理完成的数据,自己再加工加工,扔给下一个模块。
在这里插入图片描述
我们很容易总结出每个模块的流程:

1、从上一个模块拉取数据
2、处理数据
3、将处理完成的数据发给下一个模块

其中流程1和3代表两个模块间的数据交互,这种数据交互往往会采用一些中间件(middleware)。比如模块1和模块2间数据可能使用的是kafka,模块1向kafka中push数据,模块2向kafka中poll数据。而模块2和模块3可能使用的是rabbitMQ。很明显,它们的功能都是一样的:提供数据的流向,让数据可以流入自己同时又可以从自己流出发给别人。但由于中间件的不同,需要使用不同的API。 为了消除这种数据流入(输入)和数据流出(输出)实现上的差异性,因此便出现了Spring Cloud Stream。

2.环境准备

采用docker-compose搭建kafaka环境

version: '3'networks:kafka:ipam:driver: defaultconfig:- subnet: "172.22.6.0/24"services:zookepper:image: /zookeeper:latestcontainer_name: zookeeper-serverrestart: unless-stoppedvolumes:- "/etc/localtime:/etc/localtime"environment:ALLOW_ANONYMOUS_LOGIN: yesports:- "2181:2181"networks:kafka:ipv4_address: 172.22.6.11kafka:image: /kafka:3.4.1container_name: kafkarestart: unless-stoppedvolumes:- "/etc/localtime:/etc/localtime"environment:ALLOW_PLAINTEXT_LISTENER: yesKAFKA_CFG_ZOOKEEPER_CONNECT: zookepper:2181KAFKA_CFG_ADVERTISED_LISTENERS: PLAINTEXT://10.11.68.77:9092ports:- "9092:9092"depends_on:- zookeppernetworks:kafka:ipv4_address: 172.22.6.12kafka-map:image: /kafka-mapcontainer_name: kafka-maprestart: unless-stoppedvolumes:- "./kafka/kafka-map/data:/usr/local/kafka-map/data"environment:DEFAULT_USERNAME: adminDEFAULT_PASSWORD: 123456ports:- "9080:8080"depends_on:                         - kafkanetworks:kafka:ipv4_address: 172.22.6.13

run

docker-compose -f docker-compose-kafka.yml -p kafka up -d

3.代码工程

实验目标

1、生成UUID并将其发送到Kafka主题batch-in。
2、从batch-in主题接收UUID的批量消息,移除其中的数字,并将结果发送到batch-out主题。
3、监听batch-out主题并打印接收到的消息。

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springcloud-demo</artifactId><groupId>com.et</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>spring-cloud-stream-kafaka</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter Test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-stream-kafka</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>

处理流

package com.et;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;import java.util.List;
import java.util.UUID;
import java.util.function.Function;
import java.util.function.Supplier;@SpringBootApplication
public class CloudStreamsFunctionBatch {public static void main(String[] args) {SpringApplication.run(CloudStreamsFunctionBatch.class, args);}@Beanpublic Supplier<UUID> stringSupplier() {return () -> {var uuid = UUID.randomUUID();System.out.println(uuid + " -> batch-in");return uuid;};}@Beanpublic Function<List<UUID>, List<Message<String>>> digitRemovingConsumer() {return idBatch -> {System.out.println("Removed digits from batch of " + idBatch.size());return idBatch.stream().map(UUID::toString)// Remove all digits from the UUID.map(uuid -> uuid.replaceAll("\\d","")).map(noDigitString -> MessageBuilder.withPayload(noDigitString).build()).toList();};}@KafkaListener(id = "batch-out", topics = "batch-out")public void listen(String in) {System.out.println("batch-out -> " + in);}}
  • 定义一个名为stringSupplier的Bean,它实现了Supplier接口。这个方法生成一个随机的UUID,并打印到控制台,表示这个UUID将被发送到batch-in主题。
  • 定义一个名为digitRemovingConsumer的Bean,它实现了Function<List, List<Message>>接口。这个方法接受一个UUID的列表,打印出处理的UUID数量,然后将每个UUID转换为字符串,移除其中的所有数字,最后将结果封装为消息并返回。
  • 使用@KafkaListener注解定义一个Kafka监听器,监听batch-out主题。当接收到消息时,调用listen方法并打印接收到的消息内容。

配置文件

spring:cloud:function:definition: stringSupplier;digitRemovingConsumerstream:bindings:stringSupplier-out-0:destination: batch-indigitRemovingConsumer-in-0:destination: batch-ingroup: batch-inconsumer:batch-mode: truedigitRemovingConsumer-out-0:destination: batch-outkafka:binder:brokers: localhost:9092bindings:digitRemovingConsumer-in-0:consumer:configuration:# Forces consumer to wait 5 seconds before polling for messagesfetch.max.wait.ms: 5000fetch.min.bytes: 1000000000max.poll.records: 10000000

参数解释
1、spring.cloud.function.definition:定义了两个函数,stringSupplier和digitRemovingConsumer。这两个函数将在应用程序中被使用。

spring:cloud:function:definition: stringSupplier;digitRemovingCon

2、stream.bindings.stringSupplier-out-0.destination:将stringSupplier函数的输出绑定到Kafka主题batch-in。

stream:bindings:stringSupplier-out-0:destination: batch-in

3、stream.bindings.digitRemovingConsumer-in-0.destination:将digitRemovingConsumer函数的输入绑定到Kafka主题batch-in。

digitRemovingConsumer-in-0:destination: batch-ingroup: batch-inconsumer:batch-mode: true

4、group: batch-in:指定消费者组为batch-in,这意味着多个实例可以共享这个组来处理消息。

5、consumer.batch-mode: true:启用批处理模式,允许消费者一次处理多条消息。

6、stream.bindings.digitRemovingConsumer-out-0.destination:将digitRemovingConsumer函数的输出绑定到Kafka主题batch-out。

digitRemovingConsumer-out-0:destination: batch-out

4.测试

启动弄Spring Boot应用,可以看到控制台输出日志如下:

291ea6cc-1e5e-4dfb-92b6-5d5ea43d4277 -> batch-in
c746ba4e-835e-4f66-91c5-7a5cf8b01068 -> batch-in
a661145b-2dd9-4927-8806-919ad258ade5 -> batch-in
db150918-0f0b-49f6-b7bb-77b0f580de4c -> batch-in
b0d4917b-6777-4d96-a6d0-bb96715b5b20 -> batch-in
Removed digits from batch of 5
batch-out -> eacc-ee-dfb-b-dead
batch-out -> cbae-e-f-c-acfb
batch-out -> ab-dd—adade
batch-out -> db-fb-f-bbb-bfdec
batch-out -> bdb–d-ad-bbbb


http://www.ppmy.cn/news/1550953.html

相关文章

Linux快速入门:3.硬盘分区与RHEL8系统安装

点击蓝字 | 关注我们 规划Linux的硬盘分区 在安装RHEL8前&#xff0c;我们先根据上节的内容Linux快速入门&#xff1a;2.Linux的文件系统和目录结构&#xff0c;对硬盘进行分区规划。 对于Linux初学者&#xff0c;在学习过程中建议分区方案越简单越好&#xff0c;只需要将硬盘分…

Vim操作指南

Vim 是一款功能强大的文本编辑器&#xff0c;它广泛应用于程序员、系统管理员和普通用户的日常工作中。Vim 以其高效、灵活和可扩展性著称&#xff0c;虽然上手有一定难度&#xff0c;但掌握后可以极大提高编辑效率。本指南旨在为用户提供一个详细的 Vim 操作教程&#xff0c;从…

人工智能技术的工程伦理问题 --以美团外卖大数据杀熟为例

引言 最近朋友圈刷屏的一篇文章《我被美团会员割了韭菜》很多人都看过&#xff0c;针对该事件&#xff0c;网经社电子商务研究中心主任曹磊指出&#xff1a;大数据“杀熟”暴露出大数据产业发展过程中的非对称以及不透明。由此也带来的最大伦理危机—个人隐私权问题。 背景信…

深度学习:完整的模型训练流程

深度学习&#xff1a;完整的模型训练流程 为了确保我们提供一个彻底和清晰的指导&#xff0c;让我们深入分析在model.py和train.py文件中定义的模型训练和验证流程。以下部分将详细讨论模型结构的定义、数据的加载与预处理、训练参数的配置、训练与测试循环&#xff0c;以及模…

如何通过PHP爬虫模拟表单提交,抓取隐藏数据

引言 在网络爬虫技术中&#xff0c;模拟表单提交是一项常见的任务&#xff0c;特别是对于需要动态请求才能获取的隐藏数据。在电商双十一、双十二等促销活动期间&#xff0c;商品信息的实时获取尤为重要&#xff0c;特别是针对不断变化的价格和库存动态。为了满足这种需求&…

泷羽sec-蓝队基础之网络七层杀伤链(上) 学习笔记

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…

界面控件DevExpress Blazor UI v24.1亮点:全新的渲染引擎和项目模板等

DevExpress Blazor UI组件使用了C#为Blazor Server和Blazor WebAssembly创建高影响力的用户体验&#xff0c;这个UI自建库提供了一套全面的原生Blazor UI组件&#xff08;包括Pivot Grid、调度程序、图表、数据编辑器和报表等&#xff09;。 DevExpress Blazor控件目前已经升级…

算力100问☞第28问:智算中心的软件基础设施有哪些?

1、智算操作系统 作为智算中心的核心软件&#xff0c;智算操作系统负责对计算、存储、网络等硬件资源进行统一管理和调度&#xff0c;实现资源的灵活分配与高效利用。例如&#xff0c;九章云极 DataCanvas 的 Alaya NeW 智算操作系统&#xff0c;能够纳管智算资源、输出智算服…