尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

基于微服务的即时通讯系统 -- etcd实现服务注册与发现

基于微服务的即时通讯系统 -- etcd实现服务注册与发现
📅 发布时间:2026/7/24 18:05:59

前言

我们首先通过一个架构图来理解即时通讯系统:

即时通讯系统是高并发高可用的,倘若不加注册中心,网关需要轮询每个子服务,子服务需要主动通知网关自己准备好了,不说效率,只是注册发现都会存在海量网络传输,引入注册中心将发现和注册解耦,极大提高效率。

etcd实现注册中心

etcd是一个存储键值对的服务器(可以理解为数据库),该项目中引入了etcd实现注册中心,根本原因是其中的高级特性与机制能够解决多个子服务的数据一致性,换句话说,它可以监听一个服务的变化从而通知子服务,这在多个子服务的场景下十分重要,否则注册中心只有一个服务备份,谁更改了它,其他子服务都无从得知。

(1)主机与etcd

从主机与etcd的角度看,主机 a 向 etcd 中注册一个 (服务名,提供服务的主机地址)键值对,

主机 b 从etcd中申请到可用的服务。

(2)etcd - CP架构

那etcd底层如何实现最重要的数据一致性呢,注册流程保持一致,不过在注册接口 put 中我们注意到一个 lease_id ,它是租约ID,什么是租约?简单来说就是键值对数据能存储在 etcd 中的时间,通过创建一个租约对象就能让键值对数据在租约过后自动删除。

如果想续租呢?通常使用一个Keepalive(长连接对象)为租约续租,其实就是为 etcd 客户端和外部注册服务的主机建立一个长连接,一旦外部服务下线了,长连接自然也断开,从而通知 etcd 服务端删除该服务。

监听客户端如何知道这样的变化呢?它首先从 etcd 服务端拉取在 base_service 目录下的服务,之后交给 Watcher 对象监听,Watcher 对象监听到服务变化后,通过回调函数反馈给监听客户端。

注册服务客户端代码示例:

// 注册服务的客户端类 class Registery { public: // 创建一个智能指针便于外部访问 using ptr = std::shared_ptr<Registery>; Registery(const std::string& registery_host) :_registery_host(registery_host), _put_client(std::make_shared<etcd::Client>(registery_host)), _keepalive(_put_client->leasekeepalive(3).get()), _lease_id(_keepalive->Lease()) { // 先创建客户端 // 再创建长连接保活对象 // 最后得到租约id } bool registery(const std::string& key, const std::string &val) { auto resp = _put_client->put(key, val, _lease_id).get(); if(resp.is_ok() == false) { LOG_ERROR("{} 注册的 {}服务失败\n", val, key); return false; } LOG_DEBUG("{} 注册的 {}服务成功\n", val, key) return true; } ~Registery() { LOG_DEBUG("主机{}已下线\n", _registery_host); _keepalive->Cancel();} private: std::string _registery_host; // 主机名 std::shared_ptr<etcd::Client> _put_client; // 注册客户端 std::shared_ptr<etcd::KeepAlive> _keepalive; // 长连接租约保活对象 uint64_t _lease_id; // 租约id };

监听服务客户端代码示例:

// 监听(发现)服务的客户端类 // 提供两个put和get回调函数,以此让用户做出响应 using callback = std::function<void(etcd::Response)>; class Discovery { public: // 创建一个智能指针便于外部访问 using ptr = std::shared_ptr<Discovery>; using NotifyCallback = std::function<void(std::string, std::string)>; Discovery(const std::string& registery_host, const std::string& base_dir, const NotifyCallback& put_cb, const NotifyCallback& del_cb) :_registery_host(registery_host), _get_client(std::make_shared<etcd::Client>(_registery_host)), _base_dir(base_dir), _put_cb(put_cb), _del_cb(del_cb) { // 2、拉取所有注册过的服务 auto resp = _get_client->ls(_base_dir).get(); if(resp.is_ok()) { // 遍历所有注册的服务 for(int i = 0; i < resp.keys().size(); i++) { std::cout << resp.key(i) << "可以提供" << resp.value(i) << "服务" << std::endl; // 发现服务并触发回调 if(_put_cb) _put_cb(resp.key(i), resp.value(i).as_string()); } } else { LOG_ERROR("获取键值对数据失败-{}\n", resp.error_message()); } // 3、创建监听对象 _watcher = std::make_shared<etcd::Watcher>(*_get_client.get(), _base_dir, std::bind(&Discovery::WatcherCallback, this, std::placeholders::_1)); _watcher->Wait(); } private: void WatcherCallback(const etcd::Response& resp) { if (resp.is_ok() == false) { std::cout << "获取到一个错误的事件通知" << "-" << resp.error_message() << std::endl; return; } for(const auto& ev : resp.events()) { if(ev.event_type() == etcd::Event::EventType::PUT) { std::cout << "新增服务" << ev.kv().key() << "-" << ev.kv().as_string() << std::endl; if(_put_cb) _put_cb(ev.kv().key(), ev.kv().as_string()); } else if(ev.event_type() == etcd::Event::EventType::DELETE_) { std::cout << "删除服务" << ev.prev_kv().key() << "-" << ev.prev_kv().as_string() << std::endl; if(_del_cb) _del_cb(ev.prev_kv().key(), ev.prev_kv().as_string()); } } } private: NotifyCallback _put_cb; // 注册回调 NotifyCallback _del_cb; // 发现回调 std::string _registery_host; // 主机名 std::string _base_dir; // 监听目录 std::shared_ptr<etcd::Client> _get_client; // 监听客户端 std::shared_ptr<etcd::Watcher> _watcher; // 监听对象 };

相关新闻

  • 【化工仪表底层拆解】从 FMCW 雷达回波 FFT 算法到本安防爆,揭秘“化工防爆液位计原厂推荐”的 RD 实力审查红线
  • 基于SpringBoot3+Vue3的家政服务系统(源码)
  • MAA明日方舟助手终极指南:从零开始掌握自动公招与基建管理

最新新闻

  • 7月合肥蜀山黄金回收避坑攻略!五家正规机构实测名录,黄金变现少走弯路 - 逸程奢侈品回收中心
  • 多模态大模型技术解析:从GPT-4V到LLaVA的架构与优化
  • 解锁AMD Ryzen处理器潜力:SMUDebugTool免费开源调试工具完全指南
  • 基于MFC+原生GDI手动自绘仪表盘控件
  • ncmdumpGUI:解锁网易云音乐NCM文件,让音乐随处可听
  • MSP430电气特性深度解析:从参数手册到低功耗数据采集实战

日新闻

  • 武汉卡地亚LOVE钻戒与钻石项链回收变现攻略|多家门店行情参考 - 大牌深度测评
  • 2026年无锡地区健康管理如何考量?四家机构业务体系概览
  • 2026图片去水印软件哪个好用 手机电脑免费工具盘点 - 免费软件工具方法教程

周新闻

  • SaaS软件行业GEO实践:AI搜索时代的品牌可见性与获客新路径
  • 什么是PCTFE?医药高端包装的“防潮王牌“材料
  • 【JVM调优实战】16-可视化利器-JConsole-VisualVM-JMC

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号