Spring RestTemplate 升级 WebClient 导致 OutOfMemoryError

news2024/9/27 14:27:11

Spring Boot是 Java 企业应用程序的一个非常流行的框架。与内部或外部应用程序集成的一种常见方法是通过 HTTP REST 连接。我们正在从RestTemplate升级到基于 Java NIO 的WebClient,它可以通过允许在调用 REST 服务端点时进行并发来显著提高应用程序性能。WebClients 的好处如下:

  1. 并发性: WebClient 能够同时处理多个连接而不会阻塞线程,从而实现更好的并发性。
  2. 异步 :异步编程允许应用程序在等待I/O操作完成时执行其他任务,从而提高整体效率。
  3. 性能: 非阻塞 I/O 可以用更少的线程管理更多的连接,从而减少处理并发请求所需的资源。

虽然性能有所改善,但在并发连接数相同的情况下,WebClient 会因 OutOfMemoryError 而崩溃。我们将分析 WebClient 崩溃问题以及如何排除故障和修复这些问题。

Spring RestTemplate 到 WebClient 升级

为了利用 NIO 的优势(例如并发和异步处理),我们将 REST 客户端调用从 Spring RestTemplate 升级为 WebClient,如下所示。

Spring Rest模板

  public void restClientCall(Integer id, String url,String imagePath) {

    	// Create RestTemplate instance
    	RestTemplate restTemplate = new RestTemplate();

    	// Prepare the image file
    	File imageFile = new File(imagePath);

    	// Prepare headers
   	HttpHeaders headers = new HttpHeaders();
    	headers.setContentType(MediaType.MULTIPART_FORM_DATA);

    	// Prepare the request body
   	MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
    	body.add("file",new org.springframework.core.io.FileSystemResource(imageFile));

    	// Create the HTTP entity with headers and the multipart body
   	HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);

    	System.out.println("Starting to post an image for Id"+id);

    	// Perform the POST request
    	ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, requestEntity, String.class);

    	// Print the response status code and body
    	System.out.println("Response Id "+id +":"+ responseEntity.getBody());
   	System.out.println(" Time: " + LocalTime.now());}

如下所示的 Spring WebClient

public void webHeavyClientCall(Integer id,String url, String imagePath) {

	// Create a WebClient instance
	WebClient webClient = WebClient.create();

	// Prepare the image file
        File imageFile = new File(imagePath);

	// Perform the POST request with the image as a part of the request body
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
	body.add("file", new FileSystemResource(imageFile));
        System.out.println("Image upload started "+id);
		webClient.post().uri(url).contentType(MediaType.MULTIPART_FORM_DATA).body(BodyInserters.fromMultipartData(body)).retrieve().bodyToMono(String.class).subscribe(response -> {
           System.out.println("Response Id"+id+ ":" + response);
	});
}

WebClient 导致 OutOfMemoryError

当我们在OpenJDK 11中运行这两个程序时。使用基于 NIO 的 Spring WebClient 的程序在几次迭代后导致 “java.lang.OutOfMemoryError:直接缓冲内存” ,而基于 Spring RestTemplate 的程序成功完成。以下是基于 NIO 的 Spring WebClient 程序的输出。您可以注意到报告了“java.lang.OutOfMemoryError”。

Starting to post an image for Id0

Starting to post an image for Id1

Starting to post an image for Id2

Starting to post an image for Id3

Starting to post an image for Id4

Starting to post an image for Id5

Starting to post an image for Id6

Starting to post an image for Id7

Starting to post an image for Id8

Starting to post an image for Id9

Starting to post an image for Id10

Starting to post an image for Id11

Starting to post an image for Id12

Starting to post an image for Id13

Starting to post an image for Id14

2023-12-06 17:21:46.730  WARN 13804 --- [tor-http-nio-12] io.netty.util.concurrent.DefaultPromise  : An exception was thrown by reactor.ipc.netty.FutureMono$FutureSubscription.operationComplete()

reactor.core.Exceptions$ErrorCallbackNotImplemented: io.netty.channel.socket.ChannelOutputShutdownException: Channel output shutdown

Caused by: java.lang.OutOfMemoryError: Direct buffer memory

	at java.base/java.nio.Bits.reserveMemory(Bits.java:175) ~[na:na]

	at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:118) ~[na:na]

	at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:318) ~[na:na]

	at java.base/sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:242) ~[na:na]

	at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:164) ~[na:na]

	at java.base/sun.nio.ch.IOUtil.write(IOUtil.java:130) ~[na:na]

	at java.base/sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:496) ~[na:na]

	at io.netty.channel.socket.nio.NioSocketChannel.doWrite(NioSocketChannel.java:418) ~[netty-transport-4.1.23.Final.jar!/:4.1.23.Final]

	at io.netty.channel.AbstractChannel$AbstractUnsafe.flush0(AbstractChannel.java:934) ~[netty-transport-4.1.23.Final.jar!/:4.1.23.Final]

	... 18 common frames omitted

解决“OutOfMemoryError:直接缓冲内存”问题

为了解决这个问题,我们利用了 yCrash 监控工具。此工具能够在生产环境中出现中断之前预测中断。一旦它预测到环境中出现中断,它就会从您的环境中捕获 360° 故障排除工件,对其进行分析并立即生成根本原因分析报告。它捕获的工件包括垃圾收集日志、线程转储、堆替换、netstat、vmstat、iostat、top、top -H、dmesg、内核参数、磁盘使用情况……

您可以在此处注册并开始使用此工具的免费版本。

yCrash 服务器分析了 Spring Boot Rest Client,并提供了问题的明确指示和建议。以下是 yCrash 为 SpringBoot WebClient 应用程序生成的事件摘要报告。您可以注意到 yCrash 清楚地指出了错误,并提供了解决问题的必要建议。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
图 1:yCrash 的事故总结报告

垃圾收集分析报告

yCrash 的垃圾收集 (GC) 分析报告显示,完整 GC 正在连续运行(见下面的屏幕截图)。当 GC 运行时,整个应用程序都会暂停,不会处理任何事务。整个应用程序将变得无响应。我们在 SpringBoot WebClient 应用程序因 OutOfMemoryError 崩溃之前观察到了无响应行为。

yCrash 报告指出了我们的连续完整 GC 问题
图 2:yCrash 报告指出了连续完整 GC 问题

日志分析报告 OutOfMemoryError:直接缓冲内存

yCrash 的应用程序日志分析报告显示,应用程序受到“ java.lang.OutOfMemoryError:直接缓冲内存” 的影响(见下面的屏幕截图),导致应用程序崩溃。

yCrash 日志报告指出 java.lang.OutOfMemoryError: Direct buffer memory
图 3:yCrash 日志报告指出 java.lang.OutOfMemoryError:直接缓冲内存

为什么Spring WebClient会出现OutOfMemoryError?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 4:存储在本机内存其他区域中的 RestTemplate 对象

存储在本机内存的直接内存区域中的 WebClient 对象
图 5:存储在本机内存的直接内存区域中的 WebClient 对象

Spring WebClient 是基于Java NIO技术开发的。在 Java NIO 中,对象存储在 JVM 本机内存的“直接缓冲内存”区域中,而 RestTemplate 对象存储在 JVM 本机内存的“其他”区域中。JVM 中有不同的内存区域。要了解它们,您可以观看此视频片段。

当我们执行上述两个程序时,我们将直接缓冲区内存大小设置为 200k(即 -XX:MaxDirectMemorySize=200k)。这个大小对于 Spring RestTemplate 来说足够了,因为对象从未存储在这个区域中,但另一方面对于 Spring WebClient 来说却不够。因此 Spring WebClient 遭受了* java.lang.OutOfMemoryError: Direct buffer memory 的困扰。 *

增加 -XX:MaxDirectMemorySize

确定此问题后,我们使用 JVM 参数 -XX:MaxDirectMemorySize=1000k 将直接内存大小增加到更高的值。进行此更改后,Spring WebClient 程序运行正常,没有任何问题。

Starting to post an image for Id0

Starting to post an image for Id1

Starting to post an image for Id2

Starting to post an image for Id3

Starting to post an image for Id4

Starting to post an image for Id5

Starting to post an image for Id6

Starting to post an image for Id7

Starting to post an image for Id8

Starting to post an image for Id9

Starting to post an image for Id10

Starting to post an image for Id11

Starting to post an image for Id12

Starting to post an image for Id13

Starting to post an image for Id14

Starting to post an image for Id15

Starting to post an image for Id16

Starting to post an image for Id17

Starting to post an image for Id18

Starting to post an image for Id19

Response Id11:Image uploaded successfully!

Response Id4:Image uploaded successfully!

Response Id1:Image uploaded successfully!

Response Id18:Image uploaded successfully!

Response Id2:Image uploaded successfully!

Response Id3:Image uploaded successfully!

Response Id6:Image uploaded successfully!

Response Id5:Image uploaded successfully!

Response Id10:Image uploaded successfully!

Response Id13:Image uploaded successfully!

Response Id15:Image uploaded successfully!

Response Id8:Image uploaded successfully!

Response Id17:Image uploaded successfully!

Response Id9:Image uploaded successfully!

Response Id7:Image uploaded successfully!

Response Id0:Image uploaded successfully!

Response Id16:Image uploaded successfully!

Response Id14:Image uploaded successfully!

Response Id19:Image uploaded successfully!

Response Id12:Image uploaded successfully!

结论

在这篇文章中,我们讨论了从 Spring RestTemplate 升级到基于 Java NIO 的 WebClient 时遇到的 OutOfMemoryError 问题。我们还分享了我们采取的诊断方法以及解决问题的方法。希望您觉得它有用。

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

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

相关文章

Windows环境部署Oracle 11g

Windows环境部署Oracle 11g 1.安装包下载2. 解压安装包3. 数据库安装3.1 执行安装脚本3.2 电子邮件设置3.3 配置安装选项3.4 配置系统类3.5 选择数据库安装类型3.6 选择安装类型3.7 数据库配置3.8 确认安装信息3.9 设置口令 Oracle常用命令 2023年10月中旬就弄出大致的文章&…

【Linux学习】【Ubuntu入门】2-1-1 vim编辑器设置

设置TAB键为4字节及显示行号 VIM编辑器默认TAB键为8空格&#xff0c;改为4空格 输入命令sudo vi /etc/vim/vimrc回车后输入密码按键盘下键到最后&#xff0c;按下“a”进入编辑模式&#xff0c;输入set ts4设置为4空格下一行输入set nu显示行号

华为HarmonyOS灵活高效的消息推送服务(Push Kit) -- 7 推送卡片刷新消息

场景介绍 如今衣食住行娱乐影音应用占据了大多数人的手机&#xff0c;一部手机可以满足日常大多需求&#xff0c;但对需要经常查看或进行简单操作的应用来说&#xff0c;总需要用户点开应用体验较繁琐。针对此种场景&#xff0c;HarmonyOS提供了Form Kit&#xff08;卡片开发服…

Harbor安装笔记

下载离线安装包 wget https://github.com/goharbor/harbor/releases/download/v2.11.1/harbor-offline-installer-v2.11.1.tgz 解压 tar -zxvf harbor-offline-installer-v2.11.1.tgz 复制一份配置文件出来&#xff0c;修改配置 cp harbor.yml.tmpl harbor.yml vim harbor…

You are not allowed to push code to this project

原因1 用户权限不够。 具体查看用户权限路径&#xff1a; 原因2 vscode之前都能提交代码&#xff0c;但是突然就提交不上了。 表现为:前端代码能拉取&#xff0c;但是不能提交。使用idea进行前端代码的提交&#xff0c;完全没问题。 解决方案&#xff1a;修改TortoiseG…

【MySQL】常见的SQL优化方式

目录 1、插入数据 &#xff08;1&#xff09;批量插入 &#xff08;2&#xff09;手动提交事务 &#xff08;3&#xff09;主键顺序插入 2、主键优化 &#xff08;1&#xff09;页分裂 &#xff08;2&#xff09;页合并 3、order by 优化 &#xff08;1&#xff09;排…

探索有向图深度优先搜索的路径与时间的猜想:反例研究

探索有向图深度优先搜索的路径与时间的猜想:反例研究 引言深度优先搜索(DFS)猜想描述反例构造图结构提供一个DFS遍历顺序伪代码具体的DFS遍历时间戳记录分析C语言实现代码解释运行结果结论引言 在图论中,深度优先搜索(DFS)是一种重要的图遍历算法,被广泛应用于寻找路径…

VMware ESXi 8.0U3b macOS Unlocker OEM BIOS 2.7 标准版和厂商定制版

VMware ESXi 8.0U3b macOS Unlocker & OEM BIOS 2.7 标准版和厂商定制版 ESXi 8.0U3 标准版&#xff0c;Dell (戴尔)、HPE (慧与)、Lenovo (联想)、Inspur (浪潮)、Cisco (思科)、Hitachi (日立)、Fujitsu (富士通)、NEC (日电) 定制版、Huawei (华为) OEM 定制版 请访问…

【讲解+样例】使用opencv对aruco Markers识别

aruco标记与传统棋盘格功能相似&#xff0c;但是更快更便捷。棋盘格使用移步&#xff1a;【鱼眼&#xff0b;普通相机】相机标定 一、 aruco简介 aruco又称为aruco标记、aruco标签、aruco二维码。ArUco 标记通常是正方形的黑白图案。由黑色边框和内部的二进制矩阵组成。内部矩…

63.HDMI显示器驱动设计与验证-彩条实验

&#xff08;1&#xff09;常见的视频传输接口有三种&#xff1a; VGA 接口、 DVI 接口和 HDMI 接口&#xff0c;目前的显示设备都配有这三种视频传输接口。三类视频接口的发展历程为 VGA→DVI→HDMI。其中 VGA 接口出现最早&#xff0c;只能传输模拟图像信号&#xff1b; 随后…

CSS 背景属性概览:颜色、图像、位置、组合及透明

目录 非 VIP 用户可前往公众号回复“css”进行免费阅读 background - color background - image background - repeat background - position background - attachment background组合 背景透明 非 VIP 用户可前往公众号回复“css”进行免费阅读 background - color …

Stable Diffusion绘画 | SDXL模型的优缺点及模型推荐

现在 SD 已经开始全面进入 SDXL 的高分辨率时代。 SDXL 模型的优点 学习参数最多的模型&#xff1a;参数总量超过100亿&#xff0c;可对标 Midjourney 分辨率提升4倍&#xff1a;底模分辨率直接为 1024 x 1024 多出 Refiner 采样重构器&#xff1a;能增加更多的细节 更强的提示…

2024上海工博会,正运动展位新品与应用方案(二)

上海&#xff0c;9月26日&#xff0c;上海工博会已成功开展三天。正运动展位&#xff08;6.1H-E261&#xff09;依然人气高涨&#xff0c;吸引了众多专业观众和行业同仁的关注。精彩仍在继续&#xff5e; 展会现场 01 多元工业应用场景方案展示 DEMO应用演示在本次展会上&…

云打包p12苹果证书和profile文件在线制作流程

使用hbuilderx的uniapp框架&#xff0c;除了开发小程序外&#xff0c;还可以打包出原生的安卓或苹果应用。 假如是打包安卓应用个&#xff0c;则需要安卓证书。 而假如打包ios应用&#xff0c;则需要p12格式的苹果证书和苹果证书的profile文件。其中苹果证书可以理解为基于非…

c++----继承(初阶)

大家好呀&#xff0c;今天我们也是多久没有更新博客了&#xff0c;今天来讲讲我们c加加中的一个比较重要的知识点继承。首先关于继承呢&#xff0c;大家从字面意思看&#xff0c;是不是像我们平常日常生活中很容易出现的&#xff0c;比如说电视剧里面什么富豪啊&#xff0c;去了…

CDF 累积分布函数图 怎么看

以上图为例&#xff0c;图中有五个数据集&#xff0c;每条曲线代表每个数据集中流的数量&#xff0c;然后我以蓝色的线条为例去解释怎么看这个图。 红色的方框的点说明&#xff0c;dataset-1中流数量少于500的app占全部app的20%&#xff1b;紫色的方框的点说明&#xff0c;da…

win10下NAT 端口转发及ssh VMware ubuntu24虚拟机

问题&#xff1a;win10无法访问VMware ubuntu24虚拟机。ping不通&#xff0c;ssh不通。 现象&#xff1a; 无法设置网桥模式。原因不明。win10 网络连接 中没有vmnet0 网桥模式。win10 网络连接 中&#xff0c;有vmnet8的NAT模式&#xff0c;有vmnet1的仅主机模式。VMware ub…

【Redis】Linux下安装配置及通过C++访问Redis

文章目录 一、Linux Centos 7.0版本下的安装及配置二、通过C访问Redis 一、Linux Centos 7.0版本下的安装及配置 通过源来安装&#xff0c;此次安装的版本为 redis 5.0 的&#xff0c;要通过其他源进行安装&#xff0c;首先安装 scl 源 yum install centos-release-scl-rh再安…

【LeetCode】每日一题 2024_9_26 数组元素和与数字和的绝对差(模拟)

前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动&#xff01; 题目&#xff1a;数组元素和与数字和的绝对差 代码与解题思路 func differenceOfSum(nums []int) int {sum1, sum2 : 0, 0for _, v : range nums {sum1 vfor v > 0 {sum2 v%10v / 10}}return sum1-s…

教师工作量在线管理服务

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…