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

上传文件至S3时遇java.net.UnknownHostException问题求助

问题分析:间歇性java.net.UnknownHostException连接Amazon S3

问题描述

上传文件至Amazon S3时,间歇性抛出java.net.UnknownHostException: bucketName.s3.ap-south-1.amazonaws.com异常。异常有时在重新部署WAR包后恢复,有时自行消失。当前使用AWS Java SDK 1.12.305版本,需排查该异常属于代码问题、DNS问题还是AWS相关问题。

代码片段

连接S3客户端方法

public static AmazonS3 connectToAmazonS3(String accessKeyID, String secretAccessKey) {

        LOGGER.info("Connect to the amazon s3 service using the credentials");
        try {
            final BasicAWSCredentials awsCreds = new BasicAWSCredentials(accessKeyID, secretAccessKey);

            final AmazonS3 s3Client = new AmazonS3Client(awsCreds);
            LOGGER.info("Successfully connected to Amazon S3 service");

            return s3Client;
        } catch (Exception e) {
            LOGGER.error("Error occured while connecting to Amazon S3 service" + e, e);
        }

        LOGGER.info("Connection not established with Amazon S3 service");
        return null;
    }

上传文件至S3方法

public static void uploadFileToAmazonS3(final AmazonS3 s3Client, final String bucketName, final String keyName, String cmdStr) {
        LOGGER.info("Started upload file to Amazon S3 for key: " + keyName);

        try {
            byte[] contentAsBytes = cmdStr.getBytes(EPSCommonConstants.CHARSET_UTF8);
            ByteArrayInputStream contentAsStream = new ByteArrayInputStream(contentAsBytes);

            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(contentAsBytes.length);

            PutObjectRequest req = new PutObjectRequest(bucketName, keyName, contentAsStream, metadata);
            s3Client.putObject(req);

        } catch (AmazonServiceException ase) {

            LOGGER.error("Caught an AmazonServiceException, which " + "means your request made it "
                    + "to Amazon S3, but was rejected with an error response" + " for some reason.", ase);

            LOGGER.error("Error Message:    " + ase.getMessage() + " " + "HTTP Status Code: " + ase.getStatusCode()
                    + " " + "AWS Error Code:   " + ase.getErrorCode() + " " + "Error Type:       " + ase.getErrorType()
                    + " " + "Request ID:       " + ase.getRequestId());
        } catch (AmazonClientException ace) {
            LOGGER.error(
                    "Caught an AmazonClientException, which " + "means the client encountered "
                            + "an internal error while trying to " + "communicate with S3, "
                            + "such as not being able to access the network." + "Error Message: " + ace.getMessage(),
                    ace);
        } catch (IOException ioe) {
            LOGGER.error("Caught an IOException Error Message: " + ioe.getMessage(), ioe);
        }
    }

排查方向

1. DNS相关问题(最可能)

UnknownHostException本质是无法解析目标域名,间歇性出现且自行恢复的特征完全匹配DNS解析故障:

  • 应用服务器本地DNS缓存过期或失效,重启JVM(重新部署WAR包)会清除旧缓存,可能恢复解析
  • 网络运营商或本地DNS服务器的解析服务不稳定,出现间歇性解析失败
  • 异常发生时,可在应用服务器上执行nslookup bucketName.s3.ap-south-1.amazonaws.com或dig bucketName.s3.ap-south-1.amazonaws.com,手动验证域名解析是否正常

2. 代码/客户端配置问题

当前代码存在潜在优化点,虽不直接导致间歇性异常,但可能加重解析负担:

  • 未指定S3区域:AmazonS3Client默认使用US East 1区域,而bucket在ap-south-1,SDK自动重定向可能增加解析风险,建议初始化时指定区域:
    final AmazonS3 s3Client = AmazonS3Client.builder()
            .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
            .withRegion(Regions.AP_SOUTH_1)
            .build();
    
  • 客户端实例管理:频繁创建AmazonS3实例可能引发连接池或DNS缓存问题,建议复用客户端实例(单例模式)
  • JVM DNS缓存设置:可通过调整networkaddress.cache.ttl(正缓存时长)和networkaddress.cache.negative.ttl(负缓存时长)参数,避免缓存过期的无效解析结果

3. AWS相关问题(可能性极低)

AWS S3区域性解析故障概率极低,可通过AWS状态页面查看ap-south-1区域S3服务状态。另外,确认bucket名称符合S3命名规则(特殊字符可能导致解析异常,但不会是间歇性的)

总结

优先排查DNS解析问题,其次优化代码中的客户端配置与实例管理,最后确认AWS服务状态。

内容的提问来源于stack exchange,提问作者Sanket Vidwans

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 15:05:59