rpc注册中心优化

心跳检测

给注册的结点信息一个倒计时,让结点定期的续期,重置倒计时,如果节点宕机了,一直不续期,etcd就会进行key的过期删除

  1. 服务者想etcd注册自己的服务信息,在注册时设置过期时间
  2. etcd收到服务方的信息后一直维持这个过期时间,并在过期后删除key
  3. 服务方定期向etcd发起请求续签自己的注册信息(续期时间小于过期时间)
java 复制代码
// 创建一个 30 秒的租约
        long leaseId = leaseClient.grant(30).get().getID();

        // 设置要存储的键值对
        String registerKey = ETCD_ROOT_PATH + serviceMetaInfo.getServiceNodeKey();
        ByteSequence key = ByteSequence.from(registerKey, StandardCharsets.UTF_8);
        ByteSequence value = ByteSequence.from(JSONUtil.toJsonStr(serviceMetaInfo), StandardCharsets.UTF_8);

        // 将键值对与租约关联起来,并设置过期时间
        PutOption putOption = PutOption.builder().withLeaseId(leaseId).build();
        kvClient.put(key, value, putOption).get();

实现心跳检测

java 复制代码
 for(String key : loaclRegistryNodeKeySet) {
                    try{
                        List<KeyValue> keyValues = kvClient.get(ByteSequence.from(key, StandardCharsets.UTF_8))
                                .get().getKvs();
                        // 如果节点过期,需要重启节点才能注册
                        if(CollUtil.isEmpty(keyValues)){
                            continue;
                        }
                        // 节点为过期,重新注册
                        KeyValue keyValue = keyValues.get(0);
                        String value = keyValue.getValue().toString(StandardCharsets.UTF_8);
                        ServiceMetaInfo serviceMetaInfo = JSONUtil.toBean(value, ServiceMetaInfo.class);
                        register(serviceMetaInfo);
                    }catch (Exception e){
                        throw new RuntimeException(key+"续签失败",e);
                    }
                }

服务节点下线机制

  • 主动下线:关闭了provider的链接
  • 被动下线:服务者出现异常后,将该节点剔除

我们需要完善的是主动下线机制,利用jvm中的shutdownHook实现,允许开发者在jvm关闭前完成一些必要操作,例如数据库的关闭,释放资源等

java 复制代码
@Override
    public void destroy() {
        System.out.println("当前节点下线");
        // 下线节点,遍历所有的key
        for(String key: loaclRegistryNodeKeySet) {
            try{
                kvClient.delete(ByteSequence.from(key, StandardCharsets.UTF_8));
            }catch (Exception e){
                throw new RuntimeException(key+"下线失败");
            }

        }
        // 释放资源
        if (kvClient != null) {
            kvClient.close();
        }
        if (client != null) {
            client.close();
        }
    }

消费者服务缓存

由于服务节点的更新频率不是很高,所以在注册后完完全可以缓存在本地,下次就不需要在注册中心获取了,此时我们通过本地缓存实现

java 复制代码
public class RegistryServiceCache {

    /**
     * 服务缓存
     */
    List<ServiceMetaInfo> serviceCache;

    /**
     * 写缓存
     *
     * @param newServiceCache
     * @return
     */
    void writeCache(List<ServiceMetaInfo> newServiceCache) {
        this.serviceCache = newServiceCache;
    }

    /**
     * 读缓存
     *
     * @return
     */
    List<ServiceMetaInfo> readCache() {
        return this.serviceCache;
    }

    /**
     * 清空缓存
     */
    void clearCache() {
        this.serviceCache = null;
    }
}

修改我们EtcdRegistry的判断逻辑

java 复制代码
// 优先从缓存获取服务
    List<ServiceMetaInfo> cachedServiceMetaInfoList = registryServiceCache.readCache();
    if (cachedServiceMetaInfoList != null) {
        return cachedServiceMetaInfoList;
    }
......
    
    
     // 写入服务缓存
        registryServiceCache.writeCache(serviceMetaInfoList);

服务端缓存更新机制

当注册信息发生改变后(例如节点下线),需要及时更新消费缓存,此时采用etcd的watch机制,当监听到某个key发生变化后,触发事件

java 复制代码
/**
     * 只监听首次加入到监听集合中的key,防止重复
     * @param serviceNodeKey
     */
    @Override
    public void watch(String serviceNodeKey) {
        Watch watchClient = client.getWatchClient();
        // 开启监听
        boolean newWatch = watchKeySet.add(serviceNodeKey);
        if (newWatch) {
            watchClient.watch(ByteSequence.from(serviceNodeKey,StandardCharsets.UTF_8),response->{
                for(WatchEvent event : response.getEvents()){
                    switch (event.getEventType()){
                        // key 删除时触发
                        case DELETE:
                            // 清除缓存
                            registryServiceCache.clearCache();
                            break;
                        case PUT:
                        default:
                            break;
                    }
                }
            });
        }
    }

tip:ETCD集群的高可用保障

  1. 多节点部署,确保集群中有足够的健康节点
  2. raft一致性算法:通过选举和复制机制,确保集群中节点状态保持一致
  3. 自动选举和复制
  4. 负载均衡:分发请求到每个节点中,确保了高可用
  5. 监控和告警
  6. 通过WAL机制进行日志记录,即使在系统崩溃后也能进行数据恢复
相关推荐
星恒讯工业路由器19 小时前
5G FWA技术演进与趋势
网络·5g·信息与通信·4g·5g fwa·3gpp规范·fwa趋势
星夜夏空991 天前
网络编程(1)
服务器·网络
上海云盾-小余1 天前
中小站点防护避坑:低价高防服务存在的各类安全短板剖析
网络·爬虫·安全·ddos
X7x51 天前
跨厂商路由引入(重发布)实战指南:华为、华三、思科的逻辑差异与配置避坑
网络协议·信息与通信·信号处理·实施路由引入
数据知道1 天前
邮件安全实战:SPF/DKIM/DMARC 配置与钓鱼绕过
网络·安全·web安全·网络安全·邮件安全
玩转4G物联网1 天前
FS800DTU 新品上线|免费使用 DMP 设备管理平台,支持远程批量配置 & OTA 升级
物联网·网络协议·tcp/ip·云平台·核心板·fs800dtu·iot管理平台
王莎莎-MinerU1 天前
MCP 解决的是工具接入,科研 Agent 还缺的是科学证据接口标准化
开发语言·网络·人工智能·深度学习·pdf·c#·php
Chloeis Syntax1 天前
JAVAEE初阶 --- 构造HTTP请求
网络·网络协议·http·postman
砚凝霜1 天前
软考网络工程师|第 1 章 计算机网络基础 完整备考笔记
网络·笔记·计算机网络
rcms152702692181 天前
NIKON 4S019-394 接口模块
网络