设为首页 收藏本站
查看: 861|回复: 0

[经验分享] Zookeeper实践方案:(4)命名服务

[复制链接]

尚未签到

发表于 2015-9-6 12:43:07 | 显示全部楼层 |阅读模式

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&quot;zookeeper.h&quot;  
#include&quot;zookeeper_log.h&quot;  
enum MODE{PROVIDER_MODE,CONSUMER_MODE,MONITOR_MODE} g_mode;
char g_host[512]= &quot;172.17.0.36:2181&quot;;  
char g_service[512]={ 0 };
char g_path[512]=&quot;/NameService&quot;;
//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(&quot;Usage : [nameservice] [-h] [-m mode] [-n servicename] [-s ip:port] \n&quot;);
printf(&quot;        -h Show help\n&quot;);
printf(&quot;        -m set mode:provider,consumer,monitor\n&quot;);
printf(&quot;        -n set servicename\n&quot;);
printf(&quot;        -s server ip:port\n&quot;);
printf(&quot;For example:\n&quot;);
printf(&quot;    nameservice -m provider -n query_bill -s172.17.0.36:2181 \n&quot;);
printf(&quot;    nameservice -m consumer -n query_bill -s172.17.0.36:2181 \n&quot;);
printf(&quot;    nameservice -m monitor  -n query_bill -s172.17.0.36:2181 \n&quot;);
}
void get_option(int argc,const char* argv[])
{
extern char    *optarg;
int            optch;
int            dem = 1;
const char    optstring[] = &quot;hm:n:s:&quot;;

while((optch = getopt(argc , (char * const *)argv , optstring)) != -1 )
{
switch( optch )
{
case 'h':
print_usage();
exit(-1);
case '?':
print_usage();
printf(&quot;unknown parameter: %c\n&quot;, optopt);
exit(-1);
case ':':
print_usage();
printf(&quot;need parameter: %c\n&quot;, optopt);
exit(-1);
case 'm':
if (strcasecmp(optarg,&quot;provider&quot;) == 0){
g_mode = PROVIDER_MODE;
}else if (strcasecmp(optarg,&quot;consumer&quot;) == 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(&quot;watcher event\n&quot;);  
printf(&quot;type: %d\n&quot;, type);  
printf(&quot;state: %d\n&quot;, state);  
printf(&quot;path: %s\n&quot;, path);  
printf(&quot;watcherCtx: %s\n&quot;, (char *)watcherCtx);  
*/  
if(type == ZOO_CHILD_EVENT &&
state == ZOO_CONNECTED_STATE &&
g_mode == CONSUMER_MODE){
printf(&quot;providers list changed!\n&quot;);
show_list(zh,path);
}else if(type == ZOO_CHILD_EVENT &&
state == ZOO_CONNECTED_STATE &&
g_mode == MONITOR_MODE){
printf(&quot;providers or consumers list changed!\n&quot;);
char child_path[512];
printf(&quot;providers:\n&quot;);
sprintf(child_path,&quot;%s/%s/provider&quot;,g_path,g_service);
show_list(zh,child_path);
printf(&quot;consumers:\n&quot;);
sprintf(child_path,&quot;%s/%s/consumer&quot;,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,&quot;%s:%d&quot;,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,&quot;failed to get the children of path %s!\n&quot;,path);
}else{
char child_path[512] ={0};
char ip_pid[64] = {0};
int ip_pid_len = sizeof(ip_pid);
printf(&quot;--------------\n&quot;);
printf(&quot;ip\tpid\n&quot;);
for(i = 0; i < procs.count; ++i){
sprintf(child_path,&quot;%s/%s&quot;,path,procs.data);
//printf(&quot;%s\n&quot;,child_path);
ret = zoo_get(zkhandle,child_path,0,ip_pid,&ip_pid_len,NULL);
if(ret != ZOK){
fprintf(stderr,&quot;failed to get the data of path %s!\n&quot;,child_path);
}else if(strcmp(ip_pid,localhost)==0){
printf(&quot;%s(Master)\n&quot;,ip_pid);
}else{
printf(&quot;%s\n&quot;,ip_pid);
}
}
}
for(i = 0; i < procs.count; ++i){
free(procs.data);
procs.data = 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,&quot;failed to create the path %s!\n&quot;,path);
}else{
printf(&quot;create path %s successfully!\n&quot;,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 *)&quot;NameService Test&quot;, 0);  
if (zkhandle ==NULL)  
{  
fprintf(stderr, &quot;Error when connecting to zookeeper servers...\n&quot;);  
exit(EXIT_FAILURE);  
}  
create(zkhandle,g_path,&quot;NameService Test&quot;,0);
sprintf(path_buffer,&quot;%s/%s&quot;,g_path,g_service);
create(zkhandle,path_buffer,&quot;NameService Test&quot;,0);
sprintf(path_buffer,&quot;%s/%s/provider&quot;,g_path,g_service);
create(zkhandle,path_buffer,&quot;NameService Test&quot;,0);
sprintf(path_buffer,&quot;%s/%s/consumer&quot;,g_path,g_service);
create(zkhandle,path_buffer,&quot;NameService Test&quot;,0);
if(g_mode == PROVIDER_MODE){
char localhost[512]={0};
getlocalhost(localhost,sizeof(localhost));
char child_path[512];
sprintf(child_path,&quot;%s/%s/provider/&quot;,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,&quot;failed to create the child_path %s,buffer:%s!\n&quot;,child_path,path_buffer);
}else{
printf(&quot;create child path %s successfully!\n&quot;,path_buffer);
}
}else if (g_mode == CONSUMER_MODE){
char localhost[512]={0};
getlocalhost(localhost,sizeof(localhost));
char child_path[512];
sprintf(child_path,&quot;%s/%s/consumer/&quot;,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,&quot;failed to create the child_path %s,buffer:%s!\n&quot;,child_path,path_buffer);
}else{
printf(&quot;create child path %s successfully!\n&quot;,path_buffer);
}
sprintf(child_path,&quot;%s/%s/provider&quot;,g_path,g_service);
show_list(zkhandle,child_path);
}else if(g_mode == MONITOR_MODE){
char child_path[512];
printf(&quot;providers:\n&quot;);
sprintf(child_path,&quot;%s/%s/provider&quot;,g_path,g_service);
show_list(zkhandle,child_path);
printf(&quot;consumers:\n&quot;);
sprintf(child_path,&quot;%s/%s/consumer&quot;,g_path,g_service);
show_list(zkhandle,child_path);
}
getchar();
zookeeper_close(zkhandle);
return 0;
}








  


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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-110137-1-1.html 上篇帖子: 分布式服务框架 Zookeeper 下篇帖子: Zookeeper基本原理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表