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机制进行日志记录,即使在系统崩溃后也能进行数据恢复
相关推荐
深圳市恒星物联科技有限公司5 小时前
水质流量监测仪:复合指标监测的管网智能感知设备
大数据·网络·人工智能
三水不滴5 小时前
有 HTTP 了为什么还要有 RPC?
经验分享·笔记·网络协议·计算机网络·http·rpc
科技块儿5 小时前
2026年我会推荐哪些IP归属地查询网站?
网络·ip地址·ip归属地·运维工具·网络工具·实用网站·2026工具推荐
米羊1216 小时前
已有安全措施确认(中)
网络
迎仔6 小时前
A-算力中心网络隔离总览:数字世界的“酒店房间“
网络
宝塔面板7 小时前
AllinSSL 一站式搞定 SSL 自动续期:永久免费,开源可自托管
网络·网络协议·ssl
csdn今天倒闭了吗7 小时前
飞牛lucky配置ipv6 ddns+ssl+反向代理
网络·网络协议·ssl
JavinLu7 小时前
ios 配置了代理且使用 chls.pro/ssl 下载不了证书,无法弹出下载证书的提示问题
网络协议·ios·ssl
强风7947 小时前
Linux-网络层
网络
独行soc7 小时前
2026年渗透测试面试题总结-19(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮