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

从Azure Storage SAS URL生成/下载字节流时遇StacklessClosedChannelException

问题与解决方案

问题场景

使用Java代码从Azure Storage的SAS URL读取Blob并转换为Base64字节流时,抛出io.netty.channel.StacklessClosedChannelException异常,推测为Windows系统下的版本兼容问题。

代码实现

ConnectionProvider connectionProvider = 
 ConnectionProvider.builder("custom-connection-provider")
                  .maxConnections(200)
                  .pendingAcquireMaxCount(5000)
                  .build();

BlobClient blobClient = new BlobClientBuilder()
        .endpoint(searchMultipleWrapper.getSasUrl().trim()) // 有效的SAS URL
        .httpClient(new NettyAsyncHttpClientBuilder()
                .connectionProvider(connectionProvider)
                .readTimeout(Duration.ofMinutes(10))
                .writeTimeout(Duration.ofMinutes(10))
                .responseTimeout(Duration.ofMinutes(10))
                .build())
        .retryOptions(new RequestRetryOptions(
                RetryPolicyType.EXPONENTIAL,
                5,
                2,
                null,
                null,
                null
        ))
        .buildClient();

log.info("BlobClient Object check {} ", blobClient);

// 使用try-with-resources确保InputStream关闭
try (InputStream inputStream = blobClient.openInputStream();
     ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

    // 将InputStream的数据传输到ByteArrayOutputStream
    inputStream.transferTo(byteArrayOutputStream);

    // 转换为Base64
    byte[] imageBytes = byteArrayOutputStream.toByteArray();
    String base64Image = Base64.getEncoder().encodeToString(imageBytes);

    log.info("Base 64 : {} ", base64Image);

    // 打印截断后的Base64字符串(安全起见)
    log.info("Base64 Image (truncated): " + base64Image.substring(0, Math.min(base64Image.length(), 100)) + "...");
} catch (Exception e) {
    log.error("Error while processing blob content", e);
}

异常信息

stack_trace":"reactor.core.Exceptions$ReactiveException:
io.netty.channel.StacklessClosedChannelException
at reactor.core.Exceptions.propagate(Exceptions.java:410)
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:102)
at reactor.core.publisher.Mono.block(Mono.java:1779)
at com.azure.storage.blob.specialized.BlobClientBase.openInputStream(BlobClientBase.java:393)
at com.azure.storage.blob.specialized.BlobClientBase.openInputStream(BlobClientBase.java:323)
at com.azure.storage.blob.specialized.BlobClientBase.openInputStream(BlobClientBase.java:312)
at com.azure.storage.blob.specialized.BlobClientBase.openInputStream(BlobClientBase.java:299)

解决方法

该异常由Windows环境下Netty与Azure SDK的兼容问题引发,可通过以下方式处理:

  • 替换HttpClient实现:改用Apache HttpClient替代Netty,修改代码中的HttpClient配置段:

    // 替换原Netty客户端配置
    .httpClient(HttpClient.createDefault())
    

    需确保项目引入azure-core-http-apache依赖。

  • 升级Azure SDK版本:将Azure Storage Blob SDK升级至12.25.0及以上版本,该版本已修复Windows环境下的相关兼容问题。

  • 调整Netty连接参数:若继续使用Netty,可尝试禁用连接保持:

    .httpClient(new NettyAsyncHttpClientBuilder()
            .connectionProvider(connectionProvider)
            .keepAlive(false) // 添加该配置
            .readTimeout(Duration.ofMinutes(10))
            .writeTimeout(Duration.ofMinutes(10))
            .responseTimeout(Duration.ofMinutes(10))
            .build())
    

内容的提问来源于stack exchange,提问作者Ravindra Kushwaha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 20:46:17