共计 3768 个字符,预计需要花费 10 分钟才能阅读完成。
置信大家碰到源码一开始都是比拟无从下手的🙃,不晓得从哪开始浏览,面对大量代码昏头昏脑,索性就读不上来了,又节约了一次晋升本人的机会😭。
我认为 有一种办法 ,能够解决大家的困扰! 那就是通过浏览某一次开源【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/>
创作不易,无妨点赞、关注、珍藏反对一下,各位的反对就是我创作的最大能源❤️