大家好,又见面了,我是全栈君
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列表。
完整的代码例如以下:
代码语言:javascript复制/*
* 提示:该行代码过长,系统自动注释不进行高亮。一键复制会移除系统注释
* #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 helpn"); printf(" -m set mode:provider,consumer,monitorn"); printf(" -n set servicenamen"); printf(" -s server ip:portn"); 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: %cn", optopt); exit(-1); case ':': print_usage(); printf("need parameter: %cn", 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 eventn"); printf("type: %dn", type); printf("state: %dn", state); printf("path: %sn", path); printf("watcherCtx: %sn", (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("iptpidn"); for(i = 0; i < procs.count; i){ sprintf(child_path,"%s/%s",path,procs.data[i]); //printf("%sn",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("%sn",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.cn/117707.html原文链接:https://javaforall.cn