将文件导入 java 中的 zookeeper

import file to zookeeper in java

我正在使用 zookeeper 对我的 java 微服务进行配置管理。为此,我使用 apache curator 和 java zookeeper 客户端。

如何在微服务初始化时导入配置文件(属性或json)到zookeeper?

关于如何使用 curator 框架,您应该使用 curator framework if you wanted to load your config in zookeeper. See the post

yml 文件(spring 配置)有一些基本代码示例:

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.BoundedExponentialBackoffRetry;
import org.springframework.core.io.ClassPathResource;
import org.yaml.snakeyaml.Yaml;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

@Slf4j
public class LoadConfigsInZoo {
    // base path of your config
    // /CONFIG_PATH/APP_NAME,CONTEXT_NAME
    private static final String BASE_PATH = "/configuration/myApp";
    private static final String ZOO_URL = "localhost:2181";
    private static final String CONFIG_FILE = "bootstrap.yml";
    private final ObjectMapper objectMapper = new ObjectMapper();

    public static void main(String[] args) throws IOException {
        new LoadConfigsInZoo().loadConfig();
    }

    private void loadConfig() throws IOException {
        BoundedExponentialBackoffRetry retryPolicy =
                new BoundedExponentialBackoffRetry(100, 300, 10);
        Map<String, String> config = flattenInnerProperties("", getContentOfYaml(CONFIG_FILE));

        try (CuratorFramework client = CuratorFrameworkFactory.builder()
                .connectString(ZOO_URL)
                .retryPolicy(retryPolicy)
                .build()) {
            client.start();
            for (Map.Entry<String, String> entry : config.entrySet()) {
                String path = createPath(BASE_PATH, entry.getKey());
                try {
                    log.info("Try add node with name '{}'", path);
                    client.create()
                            .creatingParentsIfNeeded()
                            .forPath(path, entry.getValue().getBytes());
                    log.info("Node with name '{}' was created", path);
                } catch (Exception e) {
                    log.warn("Unable to create node by path: {}, exception: {}", path, e.getMessage());
                }
            }
        }
    }

    // need your own implementation for properties/json files
    @SuppressWarnings("unchecked")
    private Map<String, Object> getContentOfYaml(String path) throws IOException {
        Yaml yaml = new Yaml();
        try (InputStream in = new ClassPathResource(path).getInputStream()) {
            return yaml.loadAs(in, Map.class);
        }
    }

    @SuppressWarnings("unchecked")
    private Map<String, String> getContentOfProperties(String path) throws IOException {
        try (InputStream in = new ClassPathResource(path).getInputStream()) {
            Properties properties = new Properties();
            properties.load(in);
            return (Map) (properties);
        }
    }

    @SuppressWarnings("unchecked")
    private Map<String, String> getContentOfJson(String path) throws IOException {
        try (InputStream in = new ClassPathResource(path).getInputStream()) {
            return new ObjectMapper().readValue(in, HashMap.class);
        }
    }

    @SuppressWarnings("unchecked")
    private Map<String, String> flattenInnerProperties(String prefix, Map<String, Object> rootMap) {
        Map<String, String> result = new HashMap<>();
        for (Map.Entry<String, Object> entry : rootMap.entrySet()) {
            String newPrefix = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey();
            Object value = entry.getValue();
            if (value instanceof Map) {
                result.putAll(flattenInnerProperties(newPrefix, (Map<String, Object>) value));
            } else if (value instanceof List) {
                result.putAll(flattenInnerListInProperties(newPrefix, (List) value));
            } else {
                result.put(newPrefix, String.valueOf(value));
            }
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    private Map<String, String> flattenInnerListInProperties(String prefix, List value) {
        int i = 0;
        Map<String, String> result = new HashMap<>();
        for (Object v : value) {
            String listKey = prefix + "[" + i + "]";
            if (v instanceof Map) {
                result.putAll(flattenInnerProperties(listKey, (Map) v));
            } else if (v instanceof List) {
                result.putAll(flattenInnerListInProperties(listKey, (List) v));
            } else {
                result.put(listKey, String.valueOf(v));
            }
            i++;
        }
        return result;
    }

    private String createPath(String basePath, String configName) {
        return basePath + "/" + configName.replaceAll("\.", "/");
    }
}

我有一个类似的问题,我们使用 zookeeper 作为配置服务器并且配置以 yml 格式存储在文件中。 我没有根据 yml 文件编写动态创建 znode 层次结构的代码,而是找到了一个基于 groovy 的 tool,它基本上做同样的事情。

您需要安装 groovy 和 运行,如下所示

zookeeperdump.groovy -s localhost:2181 -c /config/application < dump.yml