首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Couchbase:从静态代码块中初始化要花费更长的时间

Couchbase:从静态代码块中初始化要花费更长的时间
EN

Stack Overflow用户
提问于 2015-11-29 11:01:51
回答 1查看 102关注 0票数 4

我将couchbase初始化代码放在一个静态代码块中:

代码语言:javascript
复制
static {
        initCluster();
        bucket = initBucket("graph");
        metaBucket = initBucket("meta");
        BLACKLIST = new SetObservingCache<String>(() -> getBlackList(), BLACKLIST_REFRESH_INTERVAL_SEC * 1000); 
       }

我知道这不是一个很好的实践,但它非常方便,并且达到了它的目的,因为我需要这段代码在多线程环境中运行一次,并阻止其他线程的所有后续调用,直到它完成为止(黑名单已经初始化)。

令我惊讶的是,对getBlacklist()的调用超时了,无法完成。然而,当2分钟后再次调用它(这就是ObservingCache所做的),它在不到一秒钟的时间内就完成了。

为了解决这个问题,我重构了我的代码,并使黑名单的获取变得懒惰:

代码语言:javascript
复制
    public boolean isBlacklisted(String key) {
        // BLACKLIST variable should NEVER be touched outside of this context.
        assureBlacklistIsPopulated();
        return BLACKLIST != null ? BLACKLIST.getItems().contains(key) : false;
    }

    private void assureBlacklistIsPopulated() {
        if (!ENABLE_BLACKLIST) {
            return;
        }
        if (BLACKLIST == null) {
            synchronized (CouchConnectionManager.class) {
                if (BLACKLIST == null) {
                    BLACKLIST = new SetObservingCache<String>(() -> getBlackList(), BLACKLIST_REFRESH_INTERVAL_SEC * 1000);
                }
            }
        }
    }

isBlacklisted()的调用会阻塞所有其他线程,这些线程试图检查一个条目是否黑名单,直到黑名单被初始化。我不太喜欢这个解决方案,因为它非常冗长且容易出错--人们可能会尝试从黑名单中读取,而不事先调用assureBlacklistIsPopulated()

类中的静态(和非最终)字段如下:

代码语言:javascript
复制
private static CouchbaseCluster cluster;
private static Bucket bucket;
private static Bucket metaBucket;
private static SetObservingCache<String> BLACKLIST;

当调用不是静态初始化块的一部分时,我不知道为什么调用成功。是否存在我不知道的静态初始化块中与性能相关的已知漏洞?

编辑:添加了每个请求的初始化代码

代码语言:javascript
复制
private Bucket initBucket(String bucketName) {
    while(true) {
        Throwable t = null;
        try {
            ReportableThread.updateStatus("Initializing bucket " + bucketName);
            return cluster.openBucket(bucketName);
        } catch(Throwable t1) {
            t1.printStackTrace();
            t = t1;
        }
        try {
            ReportableThread.updateStatus(String.format("Failed to open bucket: %s reason: %s", bucketName,  t));
            Thread.sleep(500);              
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

private void initCluster() {
    CouchbaseEnvironment env = DefaultCouchbaseEnvironment
            .builder()
            .kvTimeout(MINUTE)
            .connectTimeout(MINUTE)
            .retryStrategy(FailFastRetryStrategy.INSTANCE)
            .requestBufferSize(16384 * 2)
            .responseBufferSize(16384 * 2)
            .build();
    while(true) {
        ReportableThread.updateStatus("Initializing couchbase cluster");
        Throwable t = null;
        try {
            cluster = CouchbaseCluster.create(env, getServerNodes());
            if(cluster != null) {
                return;
            }
        } catch(Throwable t1) {
            t1.printStackTrace();
            t = t1;
        }
        try {
            ReportableThread.updateStatus(String.format("Failed to create connection to couch %s", t));
            Thread.sleep(500);              
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public Set<String> getBlackList() {
    ReportableThread.updateStatus("Getting black list");
    AbstractDocument<?> abstractDoc = get("blacklist", metaBucket, JsonArrayDocument.class);
    JsonArrayDocument doc = null;
    if (abstractDoc != null && abstractDoc instanceof JsonArrayDocument) {
        doc = (JsonArrayDocument)abstractDoc;
    } else {
        return new HashSet<String>();
    }
    ReportableThread.updateStatus(String.format("%s: Got %d items | sorting items", new Date(System.currentTimeMillis()).toString(), doc.content().size()));
    HashSet<String> ret = new HashSet<String>();
    for (Object string : doc.content()) {
        if (string != null) {
            ret.add(string.toString());             
        }
    }
    return ret;
}
EN

回答 1

Stack Overflow用户

发布于 2016-02-07 14:30:45

第一:你在做复核成语。那总是很糟糕。只放置一个if(BLACKLIST==null),它必须在同步的内部。

第二:懒散init很好,但是在静态getInstance()中这样做,并且从不公开黑名单字段。

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

https://stackoverflow.com/questions/33982030

复制
相关文章

相似问题

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