#pragma once #include #include #include #include #include #include #include "logger.hpp" namespace bite_im{ //服务注册客户端类 class Registry { public: using ptr = std::shared_ptr; Registry(const std::string &host): _client(std::make_shared(host)) , _keep_alive(_client->leasekeepalive(3).get()), _lease_id(_keep_alive->Lease()){} ~Registry() { _keep_alive->Cancel(); } bool registry(const std::string &key, const std::string &val) { auto resp = _client->put(key, val, _lease_id).get(); if (resp.is_ok() == false) { LOG_ERROR("注册数据失败:{}", resp.error_message()); return false; } return true; } private: std::shared_ptr _client; std::shared_ptr _keep_alive; uint64_t _lease_id; }; //服务发现客户端类 class Discovery { public: using ptr = std::shared_ptr; using NotifyCallback = std::function; Discovery(const std::string &host, const std::string &basedir, const NotifyCallback &put_cb, const NotifyCallback &del_cb): _client(std::make_shared(host)) , _put_cb(put_cb), _del_cb(del_cb){ //先进行服务发现,先获取到当前已有的数据 auto resp = _client->ls(basedir).get(); if (resp.is_ok() == false) { LOG_ERROR("获取服务信息数据失败:{}", resp.error_message()); } int sz = resp.keys().size(); for (int i = 0; i < sz; ++i) { if (_put_cb) _put_cb(resp.key(i), resp.value(i).as_string()); } //然后进行事件监控,监控数据发生的改变并调用回调进行处理 _watcher = std::make_shared(*_client.get(), basedir, std::bind(&Discovery::callback, this, std::placeholders::_1), true); } ~Discovery() { _watcher->Cancel(); } private: void callback(const etcd::Response &resp) { if (resp.is_ok() == false) { LOG_ERROR("收到一个错误的事件通知: {}", resp.error_message()); return; } for (auto const& ev : resp.events()) { if (ev.event_type() == etcd::Event::EventType::PUT) { if (_put_cb) _put_cb(ev.kv().key(), ev.kv().as_string()); LOG_DEBUG("新增服务:{}-{}", ev.kv().key(), ev.kv().as_string()); }else if (ev.event_type() == etcd::Event::EventType::DELETE_) { if (_del_cb) _del_cb(ev.prev_kv().key(), ev.prev_kv().as_string()); LOG_DEBUG("下线服务:{}-{}", ev.prev_kv().key(), ev.prev_kv().as_string()); } } } private: NotifyCallback _put_cb; NotifyCallback _del_cb; std::shared_ptr _client; std::shared_ptr _watcher; }; }