使用Guava的Cache 和CuratorFramework 建立zookeeper缓存连接池

最近生产遇到了一个问题,java客户端连接zookeeper服务端的时候,连接数超过了最大配置数60。
这个时候定位发现程序创建的zk短链接比较多,所以在增加
zookeeper服务端配置数的时候,同时使用建立Guava的Cache 和Cache 建立zookeeper缓存连接池来减少zk客户端的频繁创建和销毁。
把zk服务的客户端连接数量从之前的60调整为2000.

 


 

如图:可以看到zk客户端数量过多

 

 


代码参考如下

@Slf4j @Component
public class ZKUtils {
/**
* 创建关于zookeeper客户端的本地缓存,不适用为分布式服务
*/
private final static Cache<String, CuratorFramework> CACHE = CacheBuilder.newBuilder()

            // 如果key=test的缓存在一天内没有被访问的话,那么1天后就会被清除。
            .expireAfterAccess(1, TimeUnit.DAYS)
            // 设置要统计缓存的命中率
//            .recordStats()
            // 设置缓存最大容量为100,超过1000之后就会按照LRU最近虽少使用算法来移除缓存项
            .maximumSize(100L)
            // 设置缓存的移除通知
            .removalListener((RemovalListener<String, CuratorFramework>) notification -> {
                String key = notification.getKey();
                try (CuratorFramework value = notification.getValue()) {
                    log.info("|缓存移除并关闭成功!|key = {}|移除原因 = {}|", key, notification.getCause());
                }
            }).build();

    /**
     * 创建一个 zk 客户端
     *
     * @return
     */
    public static CuratorFramework getCuratorFramework(IZkConfig zkConfig) {

        String cacheKey = DigestUtil.md5Hex(JsonUtilsGsonImpl.toJson(BeanUtil.beanToMap(zkConfig)));
        String key = StrUtil.format("{}", cacheKey);

        CuratorFramework client;
        try {
            client = CACHE.get(key, () -> {
                CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
                        // zk的server地址,多个server之间用英文逗号隔开
                        .connectString(zkConfig.getZkInfo())
                        // 会话超时时间
                        .sessionTimeoutMs(zkConfig.getSessionTimeout())
                        // 连接超时时间
                        .connectionTimeoutMs(zkConfig.getConnectTiemout())
                        // 失败重试策略
                        .retryPolicy(new RetryNTimes(zkConfig.getMaxRetry(), zkConfig.getSleepTime()))
                        // 独立的命名空间 /namespace
                        .namespace(zkConfig.getRootNamespace()).build();
                curatorFramework.start();
                return curatorFramework;
            });
        } catch (ExecutionException e) {
            log.error(StrUtil.format("|zk客户端创建失败|错误信息 = {}|zkConfig = {}|", e.getMessage(), zkConfig), e);
            return null;
        }

        return client;
    }
}

Guava参考连接:http://ifeve.com/google-guava/

CuratorFramework参考链接:

 

posted @ 2021-09-07 18:30  kurl88  阅读(305)  评论(0)    收藏  举报