Tích hợp ZooKeeper cho Đăng ký Dịch vụ Cơ bản trong C++

Thiết kế Cơ chế Đăng ký Dịch vụ

Thành phần chính của hệ thống đăng ký dịch vụ sử dụng ZooKeeper là lớp CServiceRegistry kế thừa từ NonCopyable. Lớp này đảm nhiệm việc duy trì kết nối với ZooKeeper và xử lý đăng ký, kiểm tra trạng thái dịch vụ.

Lớp Thông tin Dịch vụ

Định nghĩa cấu trúc thông tin dịch vụ với các trường cần thiết:

<span class="keyword">class</span> <span class="class">ServiceInfo</span> {
<span class="keyword">public</span>:
    ServiceInfo() { Reset(); }
    <span class="keyword">void</span> Reset() {
        node_ip = <span class="string">""</span>;
        service_port = <span class="string">""</span>;
        zk_path = <span class="string">""</span>;
        service_name = <span class="string">""</span>;
        service_id = <span class="string">""</span>;
        instance_index = <span class="string">""</span>;
    }

    <span class="keyword">std::string</span> ToJsonString() <span class="keyword">const</span> {
        <span class="keyword">auto</span> format = [](<span class="keyword">const</span> <span class="keyword">std::string</span>& key, <span class="keyword">const</span> <span class="keyword">std::string</span>& val) {
            <span class="keyword">return</span> <span class="string">"\\\"</span> + key + <span class="string">"\\\": \\\"</span> + val + <span class="string">"\\\""</span>;
        };
        <span class="keyword">return</span> <span class="string">"{"</span> + format(<span class="string">"ip"</span>, node_ip) + <span class="string">", "</span> + format(<span class="string">"port"</span>, service_port) + 
               <span class="string">", "</span> + format(<span class="string">"zk_path"</span>, zk_path) + <span class="string">", "</span> + format(<span class="string">"service_name"</span>, service_name) +
               <span class="string">", "</span> + format(<span class="string">"service_id"</span>, service_id) + <span class="string">", "</span> + format(<span class="string">"instance_idx"</span>, instance_index) + <span class="string">"}"</span>;
    }

    <span class="keyword">void</span> FromJson(<span class="keyword">const</span> Json::Value& data) {
        node_ip = data[<span class="string">"ip"</span>].asString();
        service_port = data[<span class="string">"port"</span>].asString();
        zk_path = data[<span class="string">"zk_path"</span>].asString();
        service_name = data[<span class="string">"service_name"</span>].asString();
        service_id = data[<span class="string">"service_id"</span>].asString();
        instance_index = data[<span class="string">"instance_idx"</span>].asString();
        reg_type = data[<span class="string">"reg_type"</span>].asInt();
    }

<span class="keyword">private</span>:
    <span class="keyword">std::string</span> node_ip;
    <span class="keyword">std::string</span> service_port;
    <span class="keyword">std::string</span> zk_path;
    <span class="keyword">std::string</span> service_name;
    <span class="keyword">std::string</span> service_id;
    <span class="keyword">std::string</span> instance_index;
    <span class="keyword">int</span> reg_type;
};

Quản lý Đăng ký Dịch vụ

Lớp CServiceRegistry triển khai logic đăng ký và kiểm tra định kỳ:

<span class="keyword">class</span> <span class="class">CServiceRegistry</span> : <span class="keyword">public</span> NonCopyable {
<span class="keyword">public</span>:
    <span class="keyword">static</span> CServiceRegistry* GetInstance();
    <span class="keyword">int</span> Initialize(<span class="keyword">const</span> ServiceInfo& info);
    <span class="keyword">int</span> Register();
    <span class="keyword">int</span> Unregister();

<span class="keyword">private</span>:
    <span class="keyword">static</span> <span class="keyword">void</span>* RegistrationMonitor(<span class="keyword">void</span>* arg);
    <span class="keyword">int</span> AttemptRegistration();
    <span class="keyword">int</span> VerifyRegistration();
    <span class="keyword">int</span> CleanupRegistration();

    <span class="keyword">bool</span> IsRunning() <span class="keyword">const</span>;
    <span class="keyword">void</span> SetStatus(<span class="keyword">int</span> status);

    <span class="keyword">pthread_t</span> monitor_thread;
    <span class="keyword">bool</span> is_active;
    ServiceInfo service_info;
    <span class="keyword">std::string</span> registered_path;
    <span class="keyword">int</span> registration_status;
    <span class="keyword">long</span> last_check_time;
};

Quá trình Đăng ký

Quy trình đăng ký bao gồm:

  1. Tạo nút trên ZooKeeper với đường dẫn zk_path/service_name_service_id
  2. Xử lý trạng thái ZNODEEXISTS (nút đã tồn tại) bằng cách thử tạo nút tuần tự
  3. Đảm bảo thông tin nút khớp với thông tin dịch vụ
  4. Khởi tạo luồng kiểm tra định kỳ để duy trì trạng thái đăng ký

Mã nguồn Minh họa

Phương thức đăng ký thử nghiệm:

<span class="keyword">int</span> CServiceRegistry::AttemptRegistration() {
    <span class="keyword">if</span> (registration_status != REG_STATUS_UNREGISTERED) <span class="keyword">return</span> 0;

    <span class="keyword">std::string</span> target_path = service_info.zk_path + <span class="string">"/"</span> + service_info.service_name + <span class="string">"_"</span> + service_info.instance_index;
    <span class="keyword">bool</span> is_sequence = (service_info.reg_type == REG_TYPE_STANDARD);
    <span class="keyword">std::string</span> actual_path;
    <span class="keyword">int</span> result = ZooKeeperHandle::GetInstance()->CreateNode(target_path, service_info.ToJsonString(), is_sequence, actual_path);

    <span class="keyword">if</span> (result == ZNODEEXISTS) {
        <span class="comment">// Xử lý nút đã tồn tại - thử đăng ký tuần tự</span>
        result = ZooKeeperHandle::GetInstance()->CreateNode(target_path, service_info.ToJsonString(), <span class="keyword">true</span>, actual_path);
    }

    <span class="keyword">if</span> (result != ZOK) <span class="keyword">return</span> result;

    registered_path = actual_path;
    <span class="comment">// Xác minh thông tin nút</span>
    <span class="keyword">if</span> (service_info.ToJsonString() == ZooKeeperHandle::GetInstance()->GetNodeData(registered_path)) {
        registration_status = REG_STATUS_REGISTERED;
        last_check_time = GetCurrentMicroseconds();
    }
    <span class="keyword">return</span> ZOK;
}

Thẻ: zookeeper c++11 distributed-systems service-discovery

Đăng vào ngày 22 tháng 5 lúc 12:03