首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >jclouds: getBucketLocation超时在getBlob上

jclouds: getBucketLocation超时在getBlob上
EN

Stack Overflow用户
提问于 2022-07-29 18:47:30
回答 1查看 177关注 0票数 0

我使用的是jclouds 2.5.0。它在我们所有的部署中都是完美的,除了一个。在本例中,我们在log4j2日志中看到了以下jclouds消息:

代码语言:javascript
复制
2022-07-14 21:37:29.263 +0000,3124098302712886 {} ERROR o.j.h.h.BackoffLimitedRetryHandler [clrd-highpri-1] Cannot retry after server error, command has exceeded retry limit 5: [method=org.jclouds.aws.s3.AWSS3Client.public abstract java.lang.String org.jclouds.s3.S3Client.getBucketLocation(java.lang.String)[hammerspace-data-bucket-us-west-2], request=GET https://s3.amazonaws.com/hammerspace-data-bucket-us-west-2?location HTTP/1.1]

此消息发生在getBlob调用过程中,因此我假设getBlob的一部分是确定应该从哪个桶中检索blob。这个调用失败了5次--但不仅仅是错误的返回代码失败--它挂起并超时了,所以这5次重试占用了下载blob所需的大部分时间。

在getBlob最终停止调用getBucketLocation之后,它将尝试使用默认区域(Us 1)进行下载。因为这个桶实际上是在我们(west-2)中,下载所需的时间比应该的要长一些,但是--同样地--实际的下载瓶颈是对getBucketLocation的失败调用。

以前有人见过这样的东西吗?

我还想知道如何打开更多jclouds日志记录。我过去常常在log4j2.xml文件中取消这样的行:

代码语言:javascript
复制
        <!-- <logger name="org.jclouds" level="debug" additivity="true" /> -->
        <!-- <logger name="jclouds.compute" level="debug" additivity="true" /> -->
        <!-- <logger name="jclouds.wire" level="debug" additivity="true" /> -->
        <!-- <logger name="jclouds.headers" level="debug" additivity="true" /> -->
        <!-- <logger name="jclouds.ssh" level="debug" additivity="true" /> -->
        <!-- <logger name="software.amazon.awssdk" level="debug" additivity="true" /> -->
        <!-- <logger name="org.apache.http.wire" level="debug" additivity="true" /> -->

但在2.5.0中,这些似乎没有任何效果。

最后,如果有人知道如何阻止getBlob打电话给getBucketLocation,我将非常感谢这里的一些建议。我认为,必须有一种方法可以预先为jclouds上下文指定所需的桶,这样它就不必解决它。

约翰

更新1

我们最初以为问题是我们的AIM配置文件没有为桶正确配置,但是在使用它之后,我们能够从这个桶上的同一个主机运行AWS命令行工具,并且它没有挂起,但是jclouds仍然挂在同一个框上的getBucketLocation上。我完全被这件事弄糊涂了。它必须是jclouds 2.5.0与AWS提供者的内部特性。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-09-29 23:34:55

我已经发现了这个问题的根本原因,并认为可能会有其他人想知道发生了什么。

Amazon发布了一个通用工作流,允许客户始终为给定的桶找到正确的URL端点:

  1. 询问s3.amazonaws.com的桶位置
  2. 使用返回的url使容器特定的请求(get/put等)

如果客户端稍微更智能一些,它只会在第一个请求上询问,并缓存桶位置URL并在后续请求中重用它。

如果客户端更加智能,并且它注意到指定了一个特定于区域的URL,它将直接使用该URL来尝试一个请求。一旦失败,它将打电话回美国西海岸,获取桶的位置,缓存并使用它。

显然,jclouds只是在上面的智能级别1。它完全忽略了指定的URL,但它至少缓存了第一个getBucketLocation调用的结果,并根据需要使用该区域特定的URL。

在内部,它使用谷歌番石榴LoadingCache进行此过程。如果jclouds中有一种机制来为给定的桶预加载这个缓存,使用已知的特定于区域的URL,那就更好了。然后,它将不必离开框的getLocation数据-即使是在第一个请求。

我希望这对其他人有帮助。我花了很大的力气才知道的。而且,由于我没有收到来自jclouds邮件列表查询的任何答复,所以我不得不假设jclouds社区中也没有人知道这是如何工作的。(也可能我只是没有很好地表达我的查询。)

更新

我确实为这件事找到了工作。我在我的jclouds消费客户机中编写了这个静态的内部类:

代码语言:javascript
复制
@ConfiguresHttpApi
private static class BucketToRegionHack extends AWSS3HttpApiModule {
    private String region;
    private String bucket;

    public void setBucketForRegion(String region, String bucket) {
        this.region = region;
        this.bucket = bucket;
    }

    @Override
    @SuppressWarnings("Guava")
    protected CacheLoader<String, Optional<String>> bucketToRegion(Supplier<Set<String>> regionSupplier, S3Client client) {
        Set<String> regions = regionSupplier.get();
        if (regions.isEmpty()) {
            return new CacheLoader<String, Optional<String>>() {

                @Override
                @SuppressWarnings({"Guava", "NullableProblems"})
                public Optional<String> load(String bucket) {
                    if (BucketToRegionHack.this.bucket != null && BucketToRegionHack.this.bucket.equals(bucket)) {
                        return Optional.of(BucketToRegionHack.this.region);
                    }
                    return Optional.absent();
                }

                @Override
                public String toString() {
                    return "noRegions()";
                }
            };
        } else if (regions.size() == 1) {
            final String onlyRegion = Iterables.getOnlyElement(regions);
            return new CacheLoader<String, Optional<String>>() {
                @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
                final Optional<String> onlyRegionOption = Optional.of(onlyRegion);

                @Override
                @SuppressWarnings("NullableProblems")
                public Optional<String> load(String bucket) {
                    if (BucketToRegionHack.this.bucket != null && BucketToRegionHack.this.bucket.equals(bucket)) {
                        return Optional.of(BucketToRegionHack.this.region);
                    }
                    return onlyRegionOption;
                }

                @Override
                public String toString() {
                    return "onlyRegion(" + onlyRegion + ")";
                }
            };
        } else {
            return new CacheLoader<String, Optional<String>>() {
                @Override
                @SuppressWarnings("NullableProblems")
                public Optional<String> load(String bucket) {
                    if (BucketToRegionHack.this.bucket != null && BucketToRegionHack.this.bucket.equals(bucket)) {
                        return Optional.of(BucketToRegionHack.this.region);
                    }
                    try {
                        return Optional.fromNullable(client.getBucketLocation(bucket));
                    } catch (ContainerNotFoundException e) {
                        return Optional.absent();
                    }
                }

                @Override
                public String toString() {
                    return "bucketToRegion()";
                }
            };
        }
    }
}

这主要是代码的副本,因为它存在于jclouds中的S3HttpApiModule中。然后,我在我的init代码中添加了以下代码片段,用于设置JClouds客户端:

代码语言:javascript
复制
        BucketToRegionHack b2mModule = new BucketToRegionHack();
        contextBuilder.modules(ImmutableSet.of(b2mModule));
        Pattern pattern = Pattern.compile("s3-([a-z0-9-]+)\\.amazonaws.com");
        Matcher matcher = pattern.matcher(endpoint);
        if (matcher.find()) {
            String region = matcher.group(1);
            b2mModule.setBucketForRegion(region, cspInfo.getContainer());
        }

...where 'contextBuilder‘是我正在使用的jclouds上下文生成器。这实际上是用我自己的版本覆盖S3HttpApiModule,它允许我提供自己的逐区方法,用已知的桶和区域预加载LoadingCache。

更好的解决方法是公开一种方法,用户可以简单地用桶映射预加载加载缓存到区域,这样就不会对预加载的缓存进行getBucketLocation调用。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73169813

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档