任务
研究 divide 底层原理,ip端口探活
divide 插件底层原理
hash 负载策略
聚焦于 divide-plugin 中的 HashLoadBalance。看到虚拟节点的参数,猜测是采用一致性哈希的负载均衡策略。
整体的策略是:
- 针对每个真实服务的 url 在哈希环上分配 5 个虚拟节点
- 通过调用服务的真实IP计算得到的哈希值,找到离它最近的服务节点;若没找到,则默认取哈希环的第一个服务节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| //虚拟节点的个数为 5 private static final int VIRTUAL_NODE_NUM = 5;
//入参为配置的服务的列表,及调用服务的真实际IP public DivideUpstream doSelect(final List<DivideUpstream> upstreamList, final String ip) { //用跳表存储服务节点 final ConcurrentSkipListMap<Long, DivideUpstream> treeMap = new ConcurrentSkipListMap<>(); for (DivideUpstream address : upstreamList) { //每个服务设置 5 个虚拟节点 for (int i = 0; i < VIRTUAL_NODE_NUM; i++) { //通过服务的 url 计算哈希值 long addressHash = hash("SOUL-" + address.getUpstreamUrl() + "-HASH-" + i); //存储到跳表中 treeMap.put(addressHash, address); } } //通过 IP 计算哈希值 long hash = hash(String.valueOf(ip)); //返回离该哈希值最近的节点 SortedMap<Long, DivideUpstream> lastRing = treeMap.tailMap(hash); if (!lastRing.isEmpty()) { return lastRing.get(lastRing.firstKey()); } //如果离该哈希值最近的节点为空,则返回哈希环的第一个节点 return treeMap.firstEntry().getValue(); }
|
ip 端口探活
聚焦于 soul-admin 中的 UpstreamCheckService 。
可以看到 soul.upstream.check,soul.upstream.scheduledTime 在代码中体现为两个变量。
1 2 3 4 5 6 7 8 9 10 11
| /** * 是否开启ip探活 **/ @Value("${soul.upstream.check:true}") private boolean check;
/** * 时间间隔 **/ @Value("${soul.upstream.scheduledTime:10}") private int scheduledTime;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public void setup() { ... //线程池隔 scheduledTime 执行一次 scheduled 方法 if (check) { new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors(), SoulThreadFactory.create("scheduled-upstream-task", false)) .scheduleWithFixedDelay(this::scheduled, 10, scheduledTime, TimeUnit.SECONDS); } }
private void scheduled() { //检查每个服务的节点 if (UPSTREAM_MAP.size() > 0) { UPSTREAM_MAP.forEach(this::check); } }
//检查的方法 private void check(final String selectorName, final List<DivideUpstream> upstreamList) { ... for (DivideUpstream divideUpstream : upstreamList) { //检查服务的 url 是否正常连接 final boolean pass = UpstreamCheckUtils.checkUrl(divideUpstream.getUpstreamUrl()); if (pass) { ... successList.add(divideUpstream); } else { //检查 url 不能正常连接,则设置状态为 false,打印日志 divideUpstream.setStatus(false); log.error("check the url={} is fail ", divideUpstream.getUpstreamUrl()); } } ... if (successList.size() > 0) { //重置服务的列表 UPSTREAM_MAP.put(selectorName, successList); updateSelectorHandler(selectorName, successList); } else { //如果没有服务活着,那就把选择器给删了 UPSTREAM_MAP.remove(selectorName); updateSelectorHandler(selectorName, null); } }
|
后续安排
Link
Author:
Eazon Shaw
Permalink:
http://eazon.xyz/2021/01/28/soul12/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Solgan:
Do you believe in DESTINY?