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

处理Hutool的Http工具上传大文件报OOM

程序环境

  • JDK版本: 1.8
  • Hutool版本: 5.8.25

问题描述

客服端文件上传主要代码:

HttpRequest httpRequest = HttpUtil.createPost(FILE_UPLOAD_URL);
Resource urlResource = new UrlResource(url, fileName);
httpRequest.form("file", urlResource);
HttpResponse httpResponse = httpRequest.execute();

大文件上传 java.lang.OutOfMemoryError: Java heap space

java.lang.OutOfMemoryError: Java heap spaceat java.util.Arrays.copyOf(Arrays.java:3236) ~[na:1.8.0_275]at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118) ~[na:1.8.0_275]at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93) ~[na:1.8.0_275]at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:135) ~[na:1.8.0_275]at sun.net.www.http.PosterOutputStream.write(PosterOutputStream.java:63) ~[na:1.8.0_275]at cn.hutool.http.MultipartOutputStream.write(MultipartOutputStream.java:108) ~[hutool-all-5.8.25.jar!/:5.8.25]at java.io.OutputStream.write(OutputStream.java:116) ~[na:1.8.0_275]at cn.hutool.core.io.copy.StreamCopier.doCopy(StreamCopier.java:102) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.copy.StreamCopier.copy(StreamCopier.java:68) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.IoUtil.copy(IoUtil.java:162) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.IoUtil.copy(IoUtil.java:146) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.IoUtil.copy(IoUtil.java:132) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.IoUtil.copy(IoUtil.java:119) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.core.io.resource.Resource.writeTo(Resource.java:76) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.MultipartOutputStream.appendResource(MultipartOutputStream.java:163) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.MultipartOutputStream.write(MultipartOutputStream.java:96) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.body.MultipartBody$$Lambda$2190/568941495.accept(Unknown Source) ~[na:na]at cn.hutool.core.map.TableMap.forEach(TableMap.java:253) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.body.MultipartBody.write(MultipartBody.java:78) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.body.RequestBody.writeClose(RequestBody.java:27) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.sendMultipart(HttpRequest.java:1402) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.send(HttpRequest.java:1340) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.doExecute(HttpRequest.java:1188) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.execute(HttpRequest.java:1051) ~[hutool-all-5.8.25.jar!/:5.8.25]at cn.hutool.http.HttpRequest.execute(HttpRequest.java:1027) ~[hutool-all-5.8.25.jar!/:5.8.25]at com.mbzj.ai.third.RhzClient.execute(RhzClient.java:270) ~[classes!/:1.0-SNAPSHOT]at com.mbzj.ai.third.RhzClient.uploadKnowledgeFile(RhzClient.java:184) ~[classes!/:1.0-SNAPSHOT]at com.mbzj.ai.third.RhzService.uploadKnowledgeFile(RhzService.java:132) ~[classes!/:1.0-SNAPSHOT]at com.mbzj.ai.listener.KnowledgeFileListener.handleAddKnowledgeFileEvent(KnowledgeFileListener.java:64) ~[classes!/:1.0-SNAPSHOT]at com.mbzj.ai.listener.KnowledgeFileListener$$FastClassBySpringCGLIB$$beafef7e.invoke(<generated>) ~[classes!/:1.0-SNAPSHOT]at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.28.jar!/:5.3.28]at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.28.jar!/:5.3.28]

分析问题

从异常堆栈信息中可以看出这里使用了 java.io.ByteArrayOutputStream 。实际上就是把文件全部都加载到了Byte数组中,如果上传的文件过大必定会导致OOM。

hutool httpRequest执行流程

在这里插入图片描述
这里实际上是使用的 java.net.HttpURLConnection

解决方案

java.net.HttpURLConnection 是支持 StreamingMode 传输HTTP请求的,有两种方式开启:

  • setFixedLengthStreamingMode
    当预先知道内容长度时,该方法用于使得能够在没有内部缓冲的情况下流式传输HTTP请求主体。
    如果应用程序尝试写入比指示的content-length更多的数据,或者如果应用程序在写入指示的数量之前关闭OutputStream,则将引发异常。
  • setChunkedStreamingMode
    当内容长度为不提前知道。在这种模式下,使用分块传输编码来发送请求正文。请注意,并非所有HTTP服务器都支持此模式。
    启用输出流时,无法自动处理身份验证和重定向。如果需要身份验证或重定向,则读取响应时将引发HttpRetryException。

Hutool 的 HttpRequest中只提供了 setChunkedStreamingMode方式,setFixedLengthStreamingMode 方式其实感觉上会更好,不会出现服务端不支持的情况,作者表示下一版本中将会支持setFixedLengthStreamingMode

先来测试一下 setChunkedStreamingMode 的效果。

这里自己写一个服务端的接口看看StreamingMode的header有什么区别。

@PostMapping("test")
public void test(MultipartFile file, HttpServletRequest request) {System.out.println("fileSize" + file.getSize());// 打印所有headerEnumeration<String> headerNames = request.getHeaderNames();while (headerNames.hasMoreElements()) {String name = headerNames.nextElement();System.out.println(name + ":" + request.getHeader(name));}
}

这是修改前会出现OOM的客户端代码

HttpRequest httpRequest = HttpUtil.createPost("http://127.0.0.1:8064/test");
URL fileUrl = new URL("https://xxxx/1a67c727f8a845dd8b0b9825026349dd.mp4");
UrlResource urlResource = new UrlResource(fileUrl, "test.mp4");
httpRequest.form("file", urlResource);
System.out.println(httpRequest);
HttpResponse httpResponse = httpRequest.execute();
System.out.println(httpResponse);

堆内存明显增高
在这里插入图片描述

服务端日志输出:

accept:text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 Hutool
accept-encoding:gzip, deflate
content-type:multipart/form-data; boundary=--------------------Hutool_rV0KKNQCkTkwywrQ
cache-control:no-cache
pragma:no-cache
host:127.0.0.1:8064
connection:keep-alive
content-length:128553150

客户端上传日志:

Request Url: http://127.0.0.1:8064/ai/knowledge/test
Request Headers: Accept: text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 HutoolAccept-Encoding: gzip, deflate
Request Body: file=https%3A%2F%2Fcos-uclass.lconrise.cn%2Fbiz%2Fai%2Fknowledge%2Ffile%2F1a67c727f8a845dd8b0b9825026349dd.mp4Response Headers: Keep-Alive=[timeout=60]X-Frame-Options=[DENY]null=[HTTP/1.1 200]Cache-Control=[no-cache, no-store, max-age=0, must-revalidate]X-Content-Type-Options=[nosniff]Connection=[keep-alive]Expires=[0]Pragma=[no-cache]Content-Length=[0]X-XSS-Protection=[1; mode=block]Date=[Wed, 11 Sep 2024 01:59:55 GMT]
Response Body: 

客户端通过 setChunkedStreamingMode 开启 StreamingMode:

HttpRequest httpRequest = HttpUtil.createPost("http://127.0.0.1:8064/ai/knowledge/test");
URL fileUrl = new URL("https://cos-uclass.lconrise.cn/biz/ai/knowledge/file/1a67c727f8a845dd8b0b9825026349dd.mp4");
UrlResource urlResource = new UrlResource(fileUrl, "test.mp4");
httpRequest.form("file", urlResource);
httpRequest.setChunkedStreamingMode(1024 * 8);
System.out.println(httpRequest);
HttpResponse httpResponse = httpRequest.execute();
System.out.println(httpResponse);

上传文件时堆内存无明细变化:
在这里插入图片描述

服务端日志输出:

accept:text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 Hutool
accept-encoding:gzip, deflate
content-type:multipart/form-data; boundary=--------------------Hutool_Zn5eac5m74pQH1IJ
cache-control:no-cache
pragma:no-cache
host:127.0.0.1:8064
connection:keep-alive
transfer-encoding:chunked

客户端上传日志:

Request Url: http://127.0.0.1:8064/ai/knowledge/test
Request Headers: Accept: text/html,application/json,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36 HutoolAccept-Encoding: gzip, deflate
Request Body: file=https%3A%2F%2Fcos-uclass.lconrise.cn%2Fbiz%2Fai%2Fknowledge%2Ffile%2F1a67c727f8a845dd8b0b9825026349dd.mp4Response Headers: Keep-Alive=[timeout=60]X-Frame-Options=[DENY]null=[HTTP/1.1 200]Cache-Control=[no-cache, no-store, max-age=0, must-revalidate]X-Content-Type-Options=[nosniff]Connection=[keep-alive]Expires=[0]Pragma=[no-cache]Content-Length=[0]X-XSS-Protection=[1; mode=block]Date=[Wed, 11 Sep 2024 02:02:28 GMT]
Response Body: 

正常上传请求包含 content-lengt header, 来告诉服务端当前请求主体内容的字节数。
StreamingMode 中 没有 content-length ,而是新增了 transfer-encoding:chunked

扩展

  1. Transfer-Encoding: chunked

    • 这是一种 HTTP 传输编码,允许服务器在不知道整个响应内容长度的情况下,分批次发送数据。
    • 每个数据块前会有一个指定大小的头部,表明该块的大小,直到遇到大小为 0 的块,表示传输结束。
  2. 服务端处理

    • 服务端(如 Tomcat)在接收到 chunked 编码的请求时,会按照分块传输编码的规则来读取数据。
    • 服务端会持续读取数据块,直到检测到一个大小为 0 的块,这表示输入流已经结束。
  3. Tomcat 配置

    • Tomcat 允许通过配置 <Connector> 标签的 maxPostSize 属性来限制请求体的最大大小。
    • fileSizeThreshold 参数定义了上传文件写入磁盘的阈值,这对于处理大文件上传尤为重要。
  4. 流式上传

    • Tomcat 支持流式上传,这意味着数据可以边读边写,不需要将整个文件内容一次性加载到内存中。
    • 流式上传适用于大文件或实时数据传输,如视频流。
  5. 异步处理

    • Tomcat 支持 Servlet 3.0 规范中的异步处理机制,允许长时间运行的操作在单独的线程中执行。
    • 这可以提高 Tomcat 的并发处理能力和系统吞吐量。
  6. 异常处理

    • 在文件上传过程中,如果出现异常(如文件大小超出限制),Tomcat 会抛出相应的异常。
    • 开发者需要在代码中妥善处理这些异常,并在必要时进行异常捕获和处理。
  7. 请求结束

    • 处理完所有数据块后,Tomcat 会关闭输入流,并根据请求的内容执行相应的业务逻辑。

用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding

用了这么久HTTP, 你是否了解Content-Length和Transfer-Encoding

HTTP响应字段Transfer-Encoding含义及作用详解

相关文章:

处理Hutool的Http工具上传大文件报OOM

程序环境 JDK版本&#xff1a; 1.8Hutool版本&#xff1a; 5.8.25 问题描述 客服端文件上传主要代码&#xff1a; HttpRequest httpRequest HttpUtil.createPost(FILE_UPLOAD_URL); Resource urlResource new UrlResource(url, fileName); httpRequest.form("file&q…...

transforms的使用

示例代码 from PIL import Image from torch.utils.tensorboard import SummaryWriter from torchvision import transforms#打开该图片 img_path"hymenoptera_data/val/bees/10870992_eebeeb3a12.jpg" imgImage.open(img_path) writerSummaryWriter("logs&quo…...

python-PyQt项目实战案例:制作一个视频播放器

文章目录 1. 关键问题描述2. 通过OpenCV读取视频/打开摄像头抓取视频3. 通过PyQt 中的 QTimer定时器实现视频播放4. PyQt 视频播放器实现代码参考文献 1. 关键问题描述 在前面的文章中已经分享了pyqt制作图像处理工具的文章&#xff0c;也知道pyqt通过使用label控件显示图像的…...

反向传播的微积分原理 | Chapter 4 | Deep Learning | 3Blue1Brown

目录 前言1. 简介2. 神经网络中的链式法则3. 微积分的计算4. 公式含义5. 代价函数对权重偏置的敏感度6. 多个神经元的情形7. 回顾相关资料结语 前言 3Blue1Brown 视频笔记&#xff0c;仅供自己参考 这个章节主要来深度讲解反向传播中的一些微积分理论 官网&#xff1a;https://…...

matlab读取excel表格

使用matlab读取excel表格中的数据 使用推荐代码读取excel表格中的数据 path "C:\Users\24975\Desktop\503\GUI展示案例\Tx_20_0_Rx_40_90_0.1_95_L.xlsx";%文件路径 data readtable(path,Sheet,Sheet1,ReadRowNames,false,ReadVariableNames,false&#xff0c;Ra…...

基于springboot+vue实现的助学兼职系统(源码+L文+ppt)4-092

基于springbootvue实现的助学兼职系统&#xff08;源码L文ppt&#xff09;4-092 第4章 系统设计 4.1 总体功能设计 一般学生、招聘公司和管理者都需要登录才能进入助学兼职系统&#xff0c;使用者登录时会在后台判断使用的权限类型&#xff0c;包括一般使用者和管理者,一般使…...

⌈ 传知代码 ⌋ 农作物病害分类(Web端实现)

&#x1f49b;前情提要&#x1f49b; 本文是传知代码平台中的相关前沿知识与技术的分享~ 接下来我们即将进入一个全新的空间&#xff0c;对技术有一个全新的视角~ 本文所涉及所有资源均在传知代码平台可获取 以下的内容一定会让你对AI 赋能时代有一个颠覆性的认识哦&#x…...

CMU生成式人工智能大模型:从入门到放弃(九)

引言 在前面的系列博客中&#xff0c;我们深入探讨了生成式对抗网络&#xff08;GANs&#xff09;和变分自编码器&#xff08;VAEs&#xff09;等生成式模型。今天&#xff0c;我们将探索扩散模型&#xff08;Diffusion Models&#xff09;的进一步应用&#xff0c;并讨论在上…...

HTML基础总结

一、简介 HTML&#xff08;HyperText Markup Language&#xff09;即超文本标记语言&#xff0c;是用于创建网页的标准标记语言。它通过使用各种标签来定义网页的结构和内容&#xff0c;告诉浏览器如何显示网页。HTML 文档由标签和文本组成&#xff0c;标签用于描述文本的性质…...

EXCELL中如何两条线画入一张图中,标记坐标轴标题?

1&#xff0c;打开excel&#xff0c;左击选中两列&#xff0c; 2&#xff0c;菜单栏>“插入”>”二维折线图”选中一个 3&#xff0c;选中出现的两条线中的一条右击>最下一行&#xff0c;“设置数据系列格式” 4&#xff0c;右测“系列选项中”>点击“次坐标轴” 5…...

Zabbix企业级分布式监控环境部署

“运筹帷幄之中&#xff0c;决胜千里之外”。在IT运维中&#xff0c;监控占据着重要的地位&#xff0c;按比例来算&#xff0c;说占30%一点也不为过。对IT运维工程师来说&#xff0c;构建一个真正可用的监控告警系统是一项艰巨的任务。在监控系统的开源软件中&#xff0c;可供选…...

水轮发电机油压自动化控制系统解决方案介绍

在现代水电工程中&#xff0c;水轮机组油压自动化控制系统&#xff0c;不仅直接关系到水轮发电机组的安全稳定运行&#xff0c;还影响着整个水电站的生产效率和经济效益。 一、系统概述 国科JSF油压自动控制系统&#xff0c;适用于水轮发电机组调速器油压及主阀&#xff08;蝶…...

今天不分享技术,分享秋天的故事

引言 这个爱情故事好像是个悲剧&#xff0c;你说的是婚姻。爱情没有悲剧&#xff0c;对爱者而言&#xff0c;爱情怎么会是悲剧呢。对春天而言&#xff0c;秋天是它的悲剧吗。结尾是什么&#xff0c;等待&#xff0c;之后呢&#xff0c;没有之后。或者说&#xff0c;等待的结果…...

转录组上游分析流程(三)

环境部署——数据下载——查看数据(非质控)——数据质控——数据过滤(过滤低质量数据) 测序得到的原始序列含有接头序列和低质量序列&#xff0c;为了保证信息分析的准确性&#xff0c;需要对原始数据进行质量控制&#xff0c;得到高质量序列(Clean Reads)&#xff0c;原始序列…...

excel判断某一列(A列)中的数据是否在另一列(B列)中

如B列如果有7个元素&#xff0c;在A列右边的空白列中&#xff0c;输入如下公式&#xff1a; COUNTIF($B$1:$B$7,A1), 其中&#xff0c;$B$1:$B$7代表A列中的所有数据即绝对范围&#xff0c;A1代表B列中的一个单元格....

[环境配置]macOS上怎么查看vscode的commit id

macOS的commit id和windows上有点不一样&#xff0c;windows可以在帮助-关于查看 macOS则需要再左边第一个查看...

.net framework 3.5sp1组件安装进度条不动启动错误怎么解决

安装.NET Framework 3.5 SP1通常需要管理员权限。这是因为安装过程可能需要修改系统文件和注册表项&#xff0c;这些操作通常需要管理员权限才能执行。在Windows系统上&#xff0c;安装.NET Framework 3.5 SP1通常通过控制面板中的“启用或关闭Windows功能”选项进行&#xff0…...

学习threejs,利用THREE.ExtrudeGeometry拉伸几何体实现svg的拉伸

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.ExtrudeGeometry拉伸…...

大模型之三十二-语音合成TTS(coqui) 之二 fine-tune

在 大模型之三十-语音合成TTS(coqui)[shichaog CSDN]中提到了xttsv2的fine-tune。 数据情况&#xff1a; 我是从bilibili up主小Lin说提取了一些视频&#xff0c;然后进行了重新的fine-tune。 训练结果 如下图所示&#xff0c;上面波形幅度较大的是xttsv2原始模型的结果&am…...

JVM的内存模型是什么,每个区域的作用是什么,以及面试题(含答案)

JVM&#xff08;Java 虚拟机&#xff09;内存模型定义了 Java 程序在运行时如何分配、管理和优化内存。JVM 内存模型主要分为几个关键区域&#xff0c;每个区域有特定的作用&#xff1a; JVM 内存模型 堆内存&#xff08;Heap&#xff09;&#xff1a; 作用&#xff1a;用于存…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

聚六亚甲基单胍盐酸盐市场深度解析:现状、挑战与机遇

根据 QYResearch 发布的市场报告显示&#xff0c;全球市场规模预计在 2031 年达到 9848 万美元&#xff0c;2025 - 2031 年期间年复合增长率&#xff08;CAGR&#xff09;为 3.7%。在竞争格局上&#xff0c;市场集中度较高&#xff0c;2024 年全球前十强厂商占据约 74.0% 的市场…...

【java面试】微服务篇

【java面试】微服务篇 一、总体框架二、Springcloud&#xff08;一&#xff09;Springcloud五大组件&#xff08;二&#xff09;服务注册和发现1、Eureka2、Nacos &#xff08;三&#xff09;负载均衡1、Ribbon负载均衡流程2、Ribbon负载均衡策略3、自定义负载均衡策略4、总结 …...

生信服务器 | 做生信为什么推荐使用Linux服务器?

原文链接&#xff1a;生信服务器 | 做生信为什么推荐使用Linux服务器&#xff1f; 一、 做生信为什么推荐使用服务器&#xff1f; 大家好&#xff0c;我是小杜。在做生信分析的同学&#xff0c;或是将接触学习生信分析的同学&#xff0c;<font style"color:rgb(53, 1…...

Spring Boot 与 Kafka 的深度集成实践(二)

3. 生产者实现 3.1 生产者配置 在 Spring Boot 项目中&#xff0c;配置 Kafka 生产者主要是配置生产者工厂&#xff08;ProducerFactory&#xff09;和 KafkaTemplate 。生产者工厂负责创建 Kafka 生产者实例&#xff0c;而 KafkaTemplate 则是用于发送消息的核心组件&#x…...