Zookeeper实践方案:(4)命名服务

Zookeeper实践方案:(4)命名服务

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

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 changedvoid zktest_watcher_g(zhandle_t* zh, int type, int state, const char* path, void* watcherCtx);//show all process ip:pidvoid show_list(zhandle_t *zkhandle,const char *path);//if success,the g_mode will become MODE_MONITORvoid choose_mater(zhandle_t *zkhandle,const char *path);//get localhost ip:pidvoid 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] \n");    printf("        -h Show help\n");    printf("        -m set mode:provider,consumer,monitor\n");    printf("        -n set servicename\n");    printf("        -s server ip:port\n");    printf("For example:\n");    printf("    nameservice -m provider -n query_bill -s172.17.0.36:2181 \n");    printf("    nameservice -m consumer -n query_bill -s172.17.0.36:2181 \n");    printf("    nameservice -m monitor  -n query_bill -s172.17.0.36:2181 \n");}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\n", optopt);            exit(-1);        case ':':            print_usage();            printf("need parameter: %c\n", 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\n");      printf("type: %d\n", type);      printf("state: %d\n", state);      printf("path: %s\n", path);      printf("watcherCtx: %s\n", (char *)watcherCtx);  */      if(type == ZOO_CHILD_EVENT &&       state == ZOO_CONNECTED_STATE &&       g_mode == CONSUMER_MODE){        printf("providers list changed!\n");        show_list(zh,path);    }else if(type == ZOO_CHILD_EVENT &&             state == ZOO_CONNECTED_STATE &&             g_mode == MONITOR_MODE){        printf("providers or consumers list changed!\n");        char child_path[512];        printf("providers:\n");        sprintf(child_path,"%s/%s/provider",g_path,g_service);        show_list(zh,child_path);        printf("consumers:\n");        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!\n",path);    }else{        char child_path[512] ={0};        char ip_pid[64] = {0};        int ip_pid_len = sizeof(ip_pid);        printf("--------------\n");        printf("ip\tpid\n");        for(i = 0; i < procs.count; ++i){            sprintf(child_path,"%s/%s",path,procs.data[i]);            //printf("%s\n",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!\n",child_path);            }else if(strcmp(ip_pid,localhost)==0){                printf("%s(Master)\n",ip_pid);            }else{                printf("%s\n",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!\n",path);        }else{            printf("create path %s successfully!\n",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...\n");          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!\n",child_path,path_buffer);        }else{            printf("create child path %s successfully!\n",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!\n",child_path,path_buffer);        }else{            printf("create child path %s successfully!\n",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:\n");        sprintf(child_path,"%s/%s/provider",g_path,g_service);        show_list(zkhandle,child_path);        printf("consumers:\n");        sprintf(child_path,"%s/%s/consumer",g_path,g_service);        show_list(zkhandle,child_path);    }    getchar();    zookeeper_close(zkhandle);     return 0;}

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/117707.html原文链接:https://javaforall.net

(0)
上一篇 2022年1月1日 下午5:00
下一篇 2022年1月1日 下午5:00


相关推荐

  • LaTex学习笔记——LaTeX公式换行

    LaTex学习笔记——LaTeX公式换行ps.  1、“\!”表示其前后字符之间无间隙       2、暂留       3、段落中的数学表达式应该置于(和), $和$ 或者begin{math}和end{math} 之间。       4、对于较大的数学式子,最好的方法是使用显示式样来排版:将它们放置于[和]或begin{displaymath}和end{displaymath}之间。这样排版出的公式是没有编号…

    2022年6月7日
    163
  • 主流浏览器以及兼容问题

    主流浏览器以及兼容问题一 主流浏览器浏览器可以分为两部分 外壳 内核 其中外壳的种类相对比较多 内核则比较少 外壳 Shell 浏览器的外壳 例如菜单 工具栏等 主要是提供给用户界面操作 参数设置等等 它是调用内核来实现各种功能的 内核 浏览器内核分成两部分 渲染引擎和 js 引擎 由于 js 引擎越来越独立 内核就倾向于只指渲染引擎 负责请求网络页面资源加以解析排版并呈现给用户主要组件包括

    2026年3月17日
    2
  • 代理模式(proxy)

    前言 代理模式是一个大类,而且会经常用到,它包含了远程代理,虚拟代理,防火墙代理等,当然还有动态代理了,学过spring的人应该不陌生。 各种代理模式样式差别很大,不容易从程序上辨认,但是可以从功能上认出来,今天我就举个例子聊聊代理模式最基本的样子,从例子中认识代理模式。 举例为静态代理的基本应用,稍后再介绍代理模式的一些特点。  情境引入      本次我们以滴滴为例…

    2022年4月4日
    47
  • mysql删除表语句_navicat不小心把表删了

    mysql删除表语句_navicat不小心把表删了MySQL删除表#1、droptable表名:直接删除表,删除较干净彻底.删除表全部数据和表结构,立刻释放磁盘空间,不管是Innodb和MyISAM;删除学生表:droptablestudent;#2、truncatetable表名:truncatetable:是对表进行先删除,再创建(与原表一致)删除表全部数据,保留表结构,立刻释放磁盘空间,不管是Innodb和MyISAM;删除学生表:truncatetablestudent;#3、dele

    2025年8月5日
    3
  • 斯坦福大学机器学习——EM算法求解高斯混合模型

    斯坦福大学机器学习——EM算法求解高斯混合模型EM算法(Expection-Maximizationalgorithm,EM)是一种迭代算法,通过E步和M步两大迭代步骤,每次迭代都使极大似然函数增加。但是,由于初始值的不同,可能会使似然函数陷入局部最优。下面来谈谈EM算法以及其在求解高斯混合模型中的作用。

    2022年6月28日
    33
  • 2022年化工自动化控制仪表考试模拟100题及答案详解_化工仪表及自动化答案

    2022年化工自动化控制仪表考试模拟100题及答案详解_化工仪表及自动化答案题库来源:安全生产模拟考试一点通公众号小程序2022化工自动化控制仪表上岗证题目系化工自动化控制仪表培训试题上机考试练习题!2022年化工自动化控制仪表考试模拟100题及答案根据化工自动化控制仪表考试大纲。化工自动化控制仪表判断题通过安全生产模拟考试一点通准确把握考试要点。1、【单选题】“硬水”是指水中所溶的()离子较多的水。(B)A、钙和钠B、钙和镁C、镁和铁2、【单选题】串级控制系统具有一定的自适应能力可用于负荷和操作条件有较大变化的场合,是由于增加了()。(B…

    2025年9月27日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号