关于后端:进大厂前先学会阅读源码之shenyu网关替换ZooKeeper客户端

置信大家碰到源码一开始都是比拟无从下手的🙃,不晓得从哪开始浏览,面对大量代码昏头昏脑,索性就读不上来了,又节约了一次晋升本人的机会😭。

我认为有一种办法,能够解决大家的困扰!那就是通过浏览某一次开源【commit】、某一次社区【ISSUE】,从这个入口登程去浏览源码!!

至此,咱们发现自己开始从大量堆砌的源码中脱离开来😀。恍然大悟,柳暗花明又一村🍀。

一、前瞻

明天咱们攻克的一次开源提交:commit链接

本次commit的核心内容就在下图红框中,意思很清晰明了:替换以后的ZooKeeper客户端。

看看Magic Header是什么

Magic Header 通常指的是文件结尾的一段特定字节序列,用来标识或确认文件的格局和类型。这些字节序列是事后定义的,不同的文件格式有不同的 Magic Header。操作系统和应用程序通过读取这些特定的字节序列来辨认文件的格局,即便文件扩展名被更改或失落。

简略来说就是用来标识文件。

咱们先整体看下本次所有提交的内容,尽管看起来波及了大量的模块、大量的代码,但外围其实就是红框对应的内容。既然是要替换以后的ZooKeeper客户端,那便是要新建Curator这个新的客户端,同时批改调用端的调用对象!

上面咱们就来看看贡献者是怎么实现替换的!!同时上文提到并将数据保留在没有 magic header 的 zk 中,正确翻译应该是保留数据在zk时,不应用magic header来标识数据,那他又是怎么做的??

二、摸索

咱们参照上图,先看下ZookeeperClient类,该类很显眼的引入了本次提交的配角CuratorFramework,ZookeeperClient封装了CuratorFramework作为ZooKeeper新的客户端。

public class ZookeeperClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperClient.class);

    private final ZookeeperConfig config;

    private final CuratorFramework client;

    private final Map<String, CuratorCache> caches = new ConcurrentHashMap<>();

    public ZookeeperClient(final ZookeeperConfig zookeeperConfig) {
        this.config = zookeeperConfig;
        ExponentialBackoffRetry retryPolicy = new ExponentialBackoffRetry(config.getBaseSleepTimeMilliseconds(), config.getMaxRetries(), config.getMaxSleepTimeMilliseconds());

        CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
                .connectString(config.getServerLists())
                .retryPolicy(retryPolicy)
                .connectionTimeoutMs(config.getConnectionTimeoutMilliseconds())
                .sessionTimeoutMs(config.getSessionTimeoutMilliseconds())
                .namespace(config.getNamespace());

        if (!StringUtils.isEmpty(config.getDigest())) {
            builder.authorization("digest", config.getDigest().getBytes(StandardCharsets.UTF_8));
        }

        this.client = builder.build();
    }

    /**
     * start.
     */
    public void start() {
        this.client.start();
        try {
            this.client.blockUntilConnected();
        } catch (InterruptedException e) {
            LOGGER.warn("Interrupted during zookeeper client starting.");
            Thread.currentThread().interrupt();
        }
    }
}

而ZookeeperInstanceRegisterRepository就是起到控制器的作用,把ZookeeperConfig类的配置注册到ZookeeperClient来初始化咱们新的客户端

咱们在代码能够看到初始化办法init()。

@Join
public class ZookeeperInstanceRegisterRepository implements ShenyuInstanceRegisterRepository {

    private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperInstanceRegisterRepository.class);

    private ZookeeperClient client;

    private final Map<String, String> nodeDataMap = new HashMap<>();

    @Override
    public void init(final InstanceConfig config) {
        Properties props = config.getProps();
        int sessionTimeout = Integer.parseInt(props.getProperty("sessionTimeout", "3000"));
        int connectionTimeout = Integer.parseInt(props.getProperty("connectionTimeout", "3000"));

        int baseSleepTime = Integer.parseInt(props.getProperty("baseSleepTime", "1000"));
        int maxRetries = Integer.parseInt(props.getProperty("maxRetries", "3"));
        int maxSleepTime = Integer.parseInt(props.getProperty("maxSleepTime", String.valueOf(Integer.MAX_VALUE)));

        ZookeeperConfig zkConfig = new ZookeeperConfig(config.getServerLists());
        zkConfig.setBaseSleepTimeMilliseconds(baseSleepTime)
                .setMaxRetries(maxRetries)
                .setMaxSleepTimeMilliseconds(maxSleepTime)
                .setSessionTimeoutMilliseconds(sessionTimeout)
                .setConnectionTimeoutMilliseconds(connectionTimeout);

        String digest = props.getProperty("digest");
        if (!StringUtils.isEmpty(digest)) {
            zkConfig.setDigest(digest);
        }

        this.client = new ZookeeperClient(zkConfig);
        this.client.getClient().getConnectionStateListenable().addListener((c, newState) -> {
            if (newState == ConnectionState.RECONNECTED) {
                nodeDataMap.forEach((k, v) -> {
                    if (!client.isExist(k)) {
                        client.createOrUpdate(k, v, CreateMode.EPHEMERAL);
                        LOGGER.info("zookeeper client register instance success: {}", v);
                    }
                });
            }
        });

        client.start();
    }
}

替换客户端的操作其实不会太简单,次要就是把所有旧的客户端入参批改为新的客户端对象,能够看下贡献者的提交代码。

咱们关上commit链接指向的ISSUE

意思其实是旧的zkClient保留数据时默认会把magic header头信息插入到数据中,导致了咱们的序列化数据失败

而贡献者本次提交把客户端改为了Curator客户端,也就不会有下面插入magic header头信息的操作了。

大家是否感触通过commit、ISSUE这种形式来浏览源码的乐趣呢!

<br/>

创作不易,无妨点赞、关注、珍藏反对一下,各位的反对就是我创作的最大能源❤️

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理