You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GlassFish服务器缓冲区大小设置问题:WebSocket传大文件报错

解决WebSocket传输大文件时的Buffer Overflow问题

我来帮你排查这个困扰你的WebSocket缓冲区溢出问题,咱们一步步来分析和解决:

首先,先明确你遇到的错误信息:

Warning: Unexpected error, closing connection. java.lang.IllegalArgumentException: Buffer overflow. 
at org.glassfish.tyrus.core.Utils.appendBuffers(Utils.java:346) 
at org.glassfish.tyrus.core.TyrusWebSocketEngine$TyrusReadHandler.handle(TyrusWebSocketEngine.java:523)

这个错误确实是因为Tyrus(GlassFish的WebSocket实现)的默认接收缓冲区太小(默认大概3MB左右),无法容纳你发送的大文件数据。你尝试修改glassfish-web.xml的思路是对的,但可能是配置方式有误,或者还有其他需要调整的地方,下面给你几个可行的解决方案:


1. 修正glassfish-web.xml的配置格式

你可能遗漏了把参数包裹在<parameter>标签里,这是GlassFish web应用配置的必填结构。正确的配置应该是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app>
  <context-root>/PROJECT</context-root>
  <!-- 正确添加WebSocket接收缓冲区配置 -->
  <parameter>
    <param-name>org.glassfish.tyrus.servlet.incoming-buffer-size</param-name>
    <param-value>17000000</param-value> <!-- 设为17MB,给16MB的文件留余量 -->
  </parameter>
</glassfish-web-app>

修改完成后一定要重启GlassFish服务器,否则配置不会生效。


2. 尝试全局配置(如果应用级配置不生效)

如果上面的应用级配置还是没起作用,可以试试在GlassFish的全局域配置文件domain.xml中添加参数,作用于整个服务器:
找到domain.xml中的<config>节点(通常是<config name="server-config">),在其中添加:

<property name="org.glassfish.tyrus.incoming-buffer-size" value="17000000"/>

同样,修改后需要重启服务器。


3. 分块传输文件(更稳定的备选方案)

如果调整缓冲区大小的方式始终不生效,建议换个思路:把大文件拆分成多个小的WebSocket帧发送(比如每帧1MB),接收端再拼接成完整文件。这种方式不仅能避开缓冲区限制,还能提升传输的稳定性(大帧更容易在网络中出问题)。

伪代码示例:

发送端分块逻辑

File targetFile = new File("your-large-file.bin");
byte[] chunkBuffer = new byte[1024 * 1024]; // 1MB的块大小
try (FileInputStream fis = new FileInputStream(targetFile)) {
    int bytesRead;
    while ((bytesRead = fis.read(chunkBuffer)) != -1) {
        // 发送单个数据块
        webSocketSession.getBasicRemote().sendBinary(ByteBuffer.wrap(chunkBuffer, 0, bytesRead));
    }
    // 发送结束标记,告诉接收端文件传输完成
    webSocketSession.getBasicRemote().sendText("FILE_TRANSFER_COMPLETE");
} catch (IOException e) {
    // 处理传输异常
}

接收端拼接逻辑

private List<ByteBuffer> fileChunks = new ArrayList<>();

@OnMessage
public void onBinaryMessage(ByteBuffer chunk, Session session) {
    // 保存每个数据块
    fileChunks.add(chunk);
}

@OnMessage
public void onTextMessage(String message, Session session) {
    if ("FILE_TRANSFER_COMPLETE".equals(message)) {
        // 拼接所有块并写入文件
        int totalSize = fileChunks.stream().mapToInt(ByteBuffer::remaining).sum();
        ByteBuffer fullFileBuffer = ByteBuffer.allocate(totalSize);
        for (ByteBuffer chunk : fileChunks) {
            fullFileBuffer.put(chunk);
        }
        fullFileBuffer.flip();
        // 写入本地文件
        try (FileOutputStream fos = new FileOutputStream("received-file.bin")) {
            fos.write(fullFileBuffer.array());
        } catch (IOException e) {
            // 处理写入异常
        }
        // 清空缓存,准备下一次传输
        fileChunks.clear();
    }
}

4. 额外检查项

  • 确认Tyrus版本:如果你的GlassFish版本较新,可能参数名有变化,可以试试去掉servlet前缀,用org.glassfish.tyrus.incoming-buffer-size。
  • 检查JVM内存:如果缓冲区设置过大,JVM堆内存不足也可能导致问题,可以调整GlassFish的JVM参数(比如-Xmx)增加堆内存。

内容的提问来源于stack exchange,提问作者Mirjan Pecenko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:15:56