zoukankan      html  css  js  c++  java
  • Zookeeper实践方案:(4)命名服务

    1.基本介绍

    命名服务是指通过指定的名字来获取资源或者服务的地址,提供者的信息。利用Zookeeper非常easy创建一个全局的路径,而这个路径就能够作为一个名字。它能够指向集群中的集群。提供的服务的地址,远程对象等。简单来说使用Zookeeper做命名服务就是用路径作为名字,路径上的数据就是其名字指向的实体。

    阿里巴巴集团开源的分布式服务框架Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务地址列表。在Dubbo实现中:

    服务提供者在启动的时候,向ZK上的指定节点/dubbo/${serviceName}/providers文件夹下写入自己的URL地址,这个操作就完毕了服务的公布

    服务消费者启动的时候。订阅/dubbo/{serviceName}/providers文件夹下的提供者URL地址, 并向/dubbo/{serviceName} /consumers文件夹下写入自己的URL地址。

    注意,全部向ZK上注冊的地址都是暂时节点。这样就行保证服务提供者和消费者可以自己主动感应资源的变化。

    另外,Dubbo还有针对服务粒度的监控。方法是订阅/dubbo/{serviceName}文件夹下全部提供者和消费者的信息。

    场景实践

    上面的介绍已经满具体。实际实现起来也比較easy。以下讲讲模拟程序的主要特点。模拟程序有3个參数

    • -m 程序执行的方式,指定是服务提供者provider还是服务消费者consumer,或者是服务监控者monitor
    • -n 表示服务名称
    • -s 表示Zookeeper的服务地址IP:PORT
      执行命令例如以下:
      服务提供者:
      >nameservice -m provider -n query_bill -s172.17.0.36:2181
      服务消费者:
      >nameservice -m consumer -n query_bill -s172.17.0.36:2181
      服务监控者:
      >nameservice -m monitor -n query_bill -s172.17.0.36:2181

    第一条命令是启动一个服务提供进程,它提供了一个名为query_bill的服务。程序首次执行时会创建
    /NameService,/NameService/query_bill,/NameService/query_bill/provider,/NameService/query_bill/consumer/等几个路径。然后在服务提供进程在/NameService/query_bill/provider下创建暂时序列节点.

    第二条命令是启动一个服务消费进程,它在/NameService/query_bill/consumer/下创建暂时序列节点,并watch/NameService/query_bill/provider的子节点变化事件。及时更新provider列表。

    第三条命令是启动一个服务监控进程。它watch /NameService/query_bill/provider,/NameService/query_bill/consumer/两个路径的子节点变化,及时更新provider列表和comsumer列表。

    完整的代码例如以下:

    #include<stdio.h>  
    #include<string.h>  
    #include<unistd.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    #include"zookeeper.h"  
    #include"zookeeper_log.h"  
    
    enum MODE{PROVIDER_MODE,CONSUMER_MODE,MONITOR_MODE} g_mode;
    char g_host[512]= "172.17.0.36:2181";  
    char g_service[512]={ 0 };
    char g_path[512]="/NameService";
    
    //watch function when child list changed
    void zktest_watcher_g(zhandle_t* zh, int type, int state, const char* path, void* watcherCtx);
    //show all process ip:pid
    void show_list(zhandle_t *zkhandle,const char *path);
    //if success,the g_mode will become MODE_MONITOR
    void choose_mater(zhandle_t *zkhandle,const char *path);
    //get localhost ip:pid
    void getlocalhost(char *ip_pid,int len);
    
    void print_usage();
    void get_option(int argc,const char* argv[]);
    
    /**********unitl*********************/  
    void print_usage()
    {
        printf("Usage : [nameservice] [-h] [-m mode] [-n servicename] [-s ip:port] 
    ");
        printf("        -h Show help
    ");
        printf("        -m set mode:provider,consumer,monitor
    ");
        printf("        -n set servicename
    ");
        printf("        -s server ip:port
    ");
        printf("For example:
    ");
        printf("    nameservice -m provider -n query_bill -s172.17.0.36:2181 
    ");
        printf("    nameservice -m consumer -n query_bill -s172.17.0.36:2181 
    ");
        printf("    nameservice -m monitor  -n query_bill -s172.17.0.36:2181 
    ");
    }
    
    void get_option(int argc,const char* argv[])
    {
        extern char    *optarg;
        int            optch;
        int            dem = 1;
        const char    optstring[] = "hm:n:s:";
    
    
        while((optch = getopt(argc , (char * const *)argv , optstring)) != -1 )
        {
            switch( optch )
            {
            case 'h':
                print_usage();
                exit(-1);
            case '?':
                print_usage();
                printf("unknown parameter: %c
    ", optopt);
                exit(-1);
            case ':':
                print_usage();
                printf("need parameter: %c
    ", optopt);
                exit(-1);
            case 'm':
                if (strcasecmp(optarg,"provider") == 0){
                    g_mode = PROVIDER_MODE;
                }else if (strcasecmp(optarg,"consumer") == 0){
                    g_mode = CONSUMER_MODE;
                }else{
                    g_mode = MONITOR_MODE;
                }
                break;
            case 'n':
                strncpy(g_service,optarg,sizeof(g_service));
                break;
            case 's':
                strncpy(g_host,optarg,sizeof(g_host));
                break;
            default:
                break;
            }
        }
    } 
    void zktest_watcher_g(zhandle_t* zh, int type, int state, const char* path, void* watcherCtx)  
    {  
    /*  
        printf("watcher event
    ");  
        printf("type: %d
    ", type);  
        printf("state: %d
    ", state);  
        printf("path: %s
    ", path);  
        printf("watcherCtx: %s
    ", (char *)watcherCtx);  
    */  
    
        if(type == ZOO_CHILD_EVENT &&
           state == ZOO_CONNECTED_STATE &&
           g_mode == CONSUMER_MODE){
    
            printf("providers list changed!
    ");
            show_list(zh,path);
        }else if(type == ZOO_CHILD_EVENT &&
                 state == ZOO_CONNECTED_STATE &&
                 g_mode == MONITOR_MODE){
    
            printf("providers or consumers list changed!
    ");
    
            char child_path[512];
            printf("providers:
    ");
            sprintf(child_path,"%s/%s/provider",g_path,g_service);
            show_list(zh,child_path);
    
            printf("consumers:
    ");
            sprintf(child_path,"%s/%s/consumer",g_path,g_service);
            show_list(zh,child_path);
        }
    }  
    void getlocalhost(char *ip_pid,int len)
    {
        char hostname[64] = {0};
        struct hostent *hent ;
    
        gethostname(hostname,sizeof(hostname));
        hent = gethostbyname(hostname);
    
        char * localhost = inet_ntoa(*((struct in_addr*)(hent->h_addr_list[0])));
    
        snprintf(ip_pid,len,"%s:%d",localhost,getpid());
    }
    
    void show_list(zhandle_t *zkhandle,const char *path)
    {
    
        struct String_vector procs;
        int i = 0;
        char localhost[512]={0};
    
        getlocalhost(localhost,sizeof(localhost));
    
        int ret = zoo_get_children(zkhandle,path,1,&procs);
    
        if(ret != ZOK){
            fprintf(stderr,"failed to get the children of path %s!
    ",path);
        }else{
            char child_path[512] ={0};
            char ip_pid[64] = {0};
            int ip_pid_len = sizeof(ip_pid);
            printf("--------------
    ");
            printf("ip	pid
    ");
            for(i = 0; i < procs.count; ++i){
                sprintf(child_path,"%s/%s",path,procs.data[i]);
                //printf("%s
    ",child_path);
                ret = zoo_get(zkhandle,child_path,0,ip_pid,&ip_pid_len,NULL);
                if(ret != ZOK){
                    fprintf(stderr,"failed to get the data of path %s!
    ",child_path);
                }else if(strcmp(ip_pid,localhost)==0){
                    printf("%s(Master)
    ",ip_pid);
                }else{
                    printf("%s
    ",ip_pid);
                }
            }
        }
    
        for(i = 0; i < procs.count; ++i){
            free(procs.data[i]);
            procs.data[i] = NULL;
        }
    }
    int create(zhandle_t *zkhandle,const char *path,const char *ctx,int flag)
    {
        char path_buffer[512];  
        int bufferlen=sizeof(path_buffer);  
    
        int ret = zoo_exists(zkhandle,path,0,NULL); 
        if(ret != ZOK){
            ret = zoo_create(zkhandle,path,ctx,strlen(ctx),  
                              &ZOO_OPEN_ACL_UNSAFE,flag,  
                              path_buffer,bufferlen);  
            if(ret != ZOK){
                fprintf(stderr,"failed to create the path %s!
    ",path);
            }else{
                printf("create path %s successfully!
    ",path);
            }
        }
    
        return ZOK;
    }
    
    int main(int argc, const char *argv[])  
    {  
        int timeout = 30000;  
        char path_buffer[512];  
        int bufferlen=sizeof(path_buffer);  
        int ret = 0;
        zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR); //设置日志级别,避免出现一些其它信息  
    
        get_option(argc,argv);
    
        zhandle_t* zkhandle = zookeeper_init(g_host,zktest_watcher_g, timeout, 0, (char *)"NameService Test", 0);  
    
        if (zkhandle ==NULL)  
        {  
            fprintf(stderr, "Error when connecting to zookeeper servers...
    ");  
            exit(EXIT_FAILURE);  
        }  
    
        create(zkhandle,g_path,"NameService Test",0);
    
        sprintf(path_buffer,"%s/%s",g_path,g_service);
        create(zkhandle,path_buffer,"NameService Test",0);
    
        sprintf(path_buffer,"%s/%s/provider",g_path,g_service);
        create(zkhandle,path_buffer,"NameService Test",0);
    
        sprintf(path_buffer,"%s/%s/consumer",g_path,g_service);
        create(zkhandle,path_buffer,"NameService Test",0);
    
        if(g_mode == PROVIDER_MODE){
    
            char localhost[512]={0};
            getlocalhost(localhost,sizeof(localhost));
    
            char child_path[512];
            sprintf(child_path,"%s/%s/provider/",g_path,g_service);
            ret = zoo_create(zkhandle,child_path,localhost,strlen(localhost),  
                              &ZOO_OPEN_ACL_UNSAFE,ZOO_SEQUENCE|ZOO_EPHEMERAL,  
                              path_buffer,bufferlen);  
            if(ret != ZOK){
                fprintf(stderr,"failed to create the child_path %s,buffer:%s!
    ",child_path,path_buffer);
            }else{
                printf("create child path %s successfully!
    ",path_buffer);
            }
    
        }else if (g_mode == CONSUMER_MODE){
    
            char localhost[512]={0};
            getlocalhost(localhost,sizeof(localhost));
    
            char child_path[512];
            sprintf(child_path,"%s/%s/consumer/",g_path,g_service);
            ret = zoo_create(zkhandle,child_path,localhost,strlen(localhost),  
                              &ZOO_OPEN_ACL_UNSAFE,ZOO_SEQUENCE|ZOO_EPHEMERAL,  
                              path_buffer,bufferlen);  
            if(ret != ZOK){
                fprintf(stderr,"failed to create the child_path %s,buffer:%s!
    ",child_path,path_buffer);
            }else{
                printf("create child path %s successfully!
    ",path_buffer);
            }
    
            sprintf(child_path,"%s/%s/provider",g_path,g_service);
            show_list(zkhandle,child_path);
    
        }else if(g_mode == MONITOR_MODE){
            char child_path[512];
            printf("providers:
    ");
            sprintf(child_path,"%s/%s/provider",g_path,g_service);
            show_list(zkhandle,child_path);
    
            printf("consumers:
    ");
            sprintf(child_path,"%s/%s/consumer",g_path,g_service);
            show_list(zkhandle,child_path);
        }
    
        getchar();
    
        zookeeper_close(zkhandle); 
    
        return 0;
    }




    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    bzoj-4433 小凸玩矩阵(二分图,二分+匈牙利)
    HDU-2255 奔小康赚大钱(二分图、km算法、模板)
    python queue和生产者和消费者模型
    python Events
    python递归锁与信号量
    python 线程锁
    python GIL锁
    python 守护进程
    python 继承式多线程
    python 多线程效果演示
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4611377.html
Copyright © 2011-2022 走看看