分享

Zookeeper场景实践:命名服务

howtodown 2015-3-9 11:36:41 发表于 推荐型 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 2 74545
本帖最后由 howtodown 于 2015-3-9 11:38 编辑
问题导读

1.什么是命名服务?
2.命名服务如何发布?
3.服务消费者启动包含哪些操作?






命名服务

是指通过指定的名字来获取资源或者服务的地址,提供者的信息。利用Zookeeper很容易创建一个全局的路径,而这个路径就可以作为一个名字,它可以指向集群中的集群,提供的服务的地址,远程对象等。简单来说使用Zookeeper做命名服务就是用路径作为名字,路径上的数据就是其名字指向的实体。
阿里巴巴集团开源的分布式服务框架Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务地址列表。在Dubbo实现中:
服务提供者在启动的时候,向ZK上的指定节点/dubbo/${serviceName}/providers目录下写入自己的URL地址,这个操作就完成了服务的发布。
服务消费者启动的时候,订阅/dubbo/{serviceName}/providers目录下的提供者URL地址, 并向/dubbo/{serviceName} /consumers目录下写入自己的URL地址。
注意,所有向ZK上注册的地址都是临时节点,这样就能够保证服务提供者和消费者能够自动感应资源的变化。
另外,Dubbo还有针对服务粒度的监控,方法是订阅/dubbo/{serviceName}目录下所有提供者和消费者的信息。

场景实践
上面的介绍已经满详细,实际实现起来也比较容易。下面讲讲模拟程序的主要特点。模拟程序有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列表。
完整的代码如下:
  1. #include<stdio.h>  
  2. #include<string.h>  
  3. #include<unistd.h>
  4. #include <netinet/in.h>
  5. #include <netdb.h>
  6. #include <arpa/inet.h>
  7. #include"zookeeper.h"  
  8. #include"zookeeper_log.h"  
  9. enum MODE{PROVIDER_MODE,CONSUMER_MODE,MONITOR_MODE} g_mode;
  10. char g_host[512]= "172.17.0.36:2181";  
  11. char g_service[512]={ 0 };
  12. char g_path[512]="/NameService";
  13. //watch function when child list changed
  14. void zktest_watcher_g(zhandle_t* zh, int type, int state, const char* path, void* watcherCtx);
  15. //show all process ip:pid
  16. void show_list(zhandle_t *zkhandle,const char *path);
  17. //if success,the g_mode will become MODE_MONITOR
  18. void choose_mater(zhandle_t *zkhandle,const char *path);
  19. //get localhost ip:pid
  20. void getlocalhost(char *ip_pid,int len);
  21. void print_usage();
  22. void get_option(int argc,const char* argv[]);
  23. /**********unitl*********************/  
  24. void print_usage()
  25. {
  26.     printf("Usage : [nameservice] [-h] [-m mode] [-n servicename] [-s ip:port] \n");
  27.     printf("        -h Show help\n");
  28.     printf("        -m set mode:provider,consumer,monitor\n");
  29.     printf("        -n set servicename\n");
  30.     printf("        -s server ip:port\n");
  31.     printf("For example:\n");
  32.     printf("    nameservice -m provider -n query_bill -s172.17.0.36:2181 \n");
  33.     printf("    nameservice -m consumer -n query_bill -s172.17.0.36:2181 \n");
  34.     printf("    nameservice -m monitor  -n query_bill -s172.17.0.36:2181 \n");
  35. }
  36. void get_option(int argc,const char* argv[])
  37. {
  38.     extern char    *optarg;
  39.     int            optch;
  40.     int            dem = 1;
  41.     const char    optstring[] = "hm:n:s:";
  42.     while((optch = getopt(argc , (char * const *)argv , optstring)) != -1 )
  43.     {
  44.         switch( optch )
  45.         {
  46.         case 'h':
  47.             print_usage();
  48.             exit(-1);
  49.         case '?':
  50.             print_usage();
  51.             printf("unknown parameter: %c\n", optopt);
  52.             exit(-1);
  53.         case ':':
  54.             print_usage();
  55.             printf("need parameter: %c\n", optopt);
  56.             exit(-1);
  57.         case 'm':
  58.             if (strcasecmp(optarg,"provider") == 0){
  59.                 g_mode = PROVIDER_MODE;
  60.             }else if (strcasecmp(optarg,"consumer") == 0){
  61.                 g_mode = CONSUMER_MODE;
  62.             }else{
  63.                 g_mode = MONITOR_MODE;
  64.             }
  65.             break;
  66.         case 'n':
  67.             strncpy(g_service,optarg,sizeof(g_service));
  68.             break;
  69.         case 's':
  70.             strncpy(g_host,optarg,sizeof(g_host));
  71.             break;
  72.         default:
  73.             break;
  74.         }
  75.     }
  76. }
  77. void zktest_watcher_g(zhandle_t* zh, int type, int state, const char* path, void* watcherCtx)  
  78. {  
  79. /*  
  80.     printf("watcher event\n");  
  81.     printf("type: %d\n", type);  
  82.     printf("state: %d\n", state);  
  83.     printf("path: %s\n", path);  
  84.     printf("watcherCtx: %s\n", (char *)watcherCtx);  
  85. */  
  86.     if(type == ZOO_CHILD_EVENT &&
  87.        state == ZOO_CONNECTED_STATE &&
  88.        g_mode == CONSUMER_MODE){
  89.         printf("providers list changed!\n");
  90.         show_list(zh,path);
  91.     }else if(type == ZOO_CHILD_EVENT &&
  92.              state == ZOO_CONNECTED_STATE &&
  93.              g_mode == MONITOR_MODE){
  94.         printf("providers or consumers list changed!\n");
  95.         char child_path[512];
  96.         printf("providers:\n");
  97.         sprintf(child_path,"%s/%s/provider",g_path,g_service);
  98.         show_list(zh,child_path);
  99.         printf("consumers:\n");
  100.         sprintf(child_path,"%s/%s/consumer",g_path,g_service);
  101.         show_list(zh,child_path);
  102.     }
  103. }  
  104. void getlocalhost(char *ip_pid,int len)
  105. {
  106.     char hostname[64] = {0};
  107.     struct hostent *hent ;
  108.     gethostname(hostname,sizeof(hostname));
  109.     hent = gethostbyname(hostname);
  110.     char * localhost = inet_ntoa(*((struct in_addr*)(hent->h_addr_list[0])));
  111.     snprintf(ip_pid,len,"%s:%d",localhost,getpid());
  112. }
  113. void show_list(zhandle_t *zkhandle,const char *path)
  114. {
  115.     struct String_vector procs;
  116.     int i = 0;
  117.     char localhost[512]={0};
  118.     getlocalhost(localhost,sizeof(localhost));
  119.     int ret = zoo_get_children(zkhandle,path,1,&procs);
  120.     if(ret != ZOK){
  121.         fprintf(stderr,"failed to get the children of path %s!\n",path);
  122.     }else{
  123.         char child_path[512] ={0};
  124.         char ip_pid[64] = {0};
  125.         int ip_pid_len = sizeof(ip_pid);
  126.         printf("--------------\n");
  127.         printf("ip\tpid\n");
  128.         for(i = 0; i < procs.count; ++i){
  129.             sprintf(child_path,"%s/%s",path,procs.data[i]);
  130.             //printf("%s\n",child_path);
  131.             ret = zoo_get(zkhandle,child_path,0,ip_pid,&ip_pid_len,NULL);
  132.             if(ret != ZOK){
  133.                 fprintf(stderr,"failed to get the data of path %s!\n",child_path);
  134.             }else if(strcmp(ip_pid,localhost)==0){
  135.                 printf("%s(Master)\n",ip_pid);
  136.             }else{
  137.                 printf("%s\n",ip_pid);
  138.             }
  139.         }
  140.     }
  141.     for(i = 0; i < procs.count; ++i){
  142.         free(procs.data[i]);
  143.         procs.data[i] = NULL;
  144.     }
  145. }
  146. int create(zhandle_t *zkhandle,const char *path,const char *ctx,int flag)
  147. {
  148.     char path_buffer[512];  
  149.     int bufferlen=sizeof(path_buffer);  
  150.     int ret = zoo_exists(zkhandle,path,0,NULL);
  151.     if(ret != ZOK){
  152.         ret = zoo_create(zkhandle,path,ctx,strlen(ctx),  
  153.                           &ZOO_OPEN_ACL_UNSAFE,flag,  
  154.                           path_buffer,bufferlen);  
  155.         if(ret != ZOK){
  156.             fprintf(stderr,"failed to create the path %s!\n",path);
  157.         }else{
  158.             printf("create path %s successfully!\n",path);
  159.         }
  160.     }
  161.     return ZOK;
  162. }
  163. int main(int argc, const char *argv[])  
  164. {  
  165.     int timeout = 30000;  
  166.     char path_buffer[512];  
  167.     int bufferlen=sizeof(path_buffer);  
  168.     int ret = 0;
  169.     zoo_set_debug_level(ZOO_LOG_LEVEL_ERROR); //设置日志级别,避免出现一些其他信息  
  170.     get_option(argc,argv);
  171.     zhandle_t* zkhandle = zookeeper_init(g_host,zktest_watcher_g, timeout, 0, (char *)"NameService Test", 0);  
  172.     if (zkhandle ==NULL)  
  173.     {  
  174.         fprintf(stderr, "Error when connecting to zookeeper servers...\n");  
  175.         exit(EXIT_FAILURE);  
  176.     }  
  177.     create(zkhandle,g_path,"NameService Test",0);
  178.     sprintf(path_buffer,"%s/%s",g_path,g_service);
  179.     create(zkhandle,path_buffer,"NameService Test",0);
  180.     sprintf(path_buffer,"%s/%s/provider",g_path,g_service);
  181.     create(zkhandle,path_buffer,"NameService Test",0);
  182.     sprintf(path_buffer,"%s/%s/consumer",g_path,g_service);
  183.     create(zkhandle,path_buffer,"NameService Test",0);
  184.     if(g_mode == PROVIDER_MODE){
  185.         char localhost[512]={0};
  186.         getlocalhost(localhost,sizeof(localhost));
  187.         char child_path[512];
  188.         sprintf(child_path,"%s/%s/provider/",g_path,g_service);
  189.         ret = zoo_create(zkhandle,child_path,localhost,strlen(localhost),  
  190.                           &ZOO_OPEN_ACL_UNSAFE,ZOO_SEQUENCE|ZOO_EPHEMERAL,  
  191.                           path_buffer,bufferlen);  
  192.         if(ret != ZOK){
  193.             fprintf(stderr,"failed to create the child_path %s,buffer:%s!\n",child_path,path_buffer);
  194.         }else{
  195.             printf("create child path %s successfully!\n",path_buffer);
  196.         }
  197.     }else if (g_mode == CONSUMER_MODE){
  198.         char localhost[512]={0};
  199.         getlocalhost(localhost,sizeof(localhost));
  200.         char child_path[512];
  201.         sprintf(child_path,"%s/%s/consumer/",g_path,g_service);
  202.         ret = zoo_create(zkhandle,child_path,localhost,strlen(localhost),  
  203.                           &ZOO_OPEN_ACL_UNSAFE,ZOO_SEQUENCE|ZOO_EPHEMERAL,  
  204.                           path_buffer,bufferlen);  
  205.         if(ret != ZOK){
  206.             fprintf(stderr,"failed to create the child_path %s,buffer:%s!\n",child_path,path_buffer);
  207.         }else{
  208.             printf("create child path %s successfully!\n",path_buffer);
  209.         }
  210.         sprintf(child_path,"%s/%s/provider",g_path,g_service);
  211.         show_list(zkhandle,child_path);
  212.     }else if(g_mode == MONITOR_MODE){
  213.         char child_path[512];
  214.         printf("providers:\n");
  215.         sprintf(child_path,"%s/%s/provider",g_path,g_service);
  216.         show_list(zkhandle,child_path);
  217.         printf("consumers:\n");
  218.         sprintf(child_path,"%s/%s/consumer",g_path,g_service);
  219.         show_list(zkhandle,child_path);
  220.     }
  221.     getchar();
  222.     zookeeper_close(zkhandle);
  223.     return 0;
  224. }
复制代码

相关文章:





本帖被以下淘专辑推荐:

已有(2)人评论

跳转到指定楼层
ainubis 发表于 2015-3-29 06:43:33

学习了(*^__^*) 嘻嘻……
回复

使用道具 举报

spftoto 发表于 2018-7-17 17:01:37
“”阿里巴巴集团开源的分布式服务框架Dubbo中使用ZooKeeper来作为其命名服务,维护全局的服务地址列表。“”这个可否说的更详细点 究竟是怎么利用统一命名的呀?服务提供者在zookeeper中注册一个节点,然后将自己的URL作为那个节点的数据写进去。然后消费者是怎么访问这个服务的呢?怎么通过zookeeper的这个统一命名空间访问服务的呢?大佬,可否说的更详细点,谢谢了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条