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] \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;
}

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

Zookeeper实践方案:(4)命名服务的更多相关文章

  1. ZooKeeper实践方案:(7) 分布式锁

    1.基本介绍 分布式锁是控制分布式系统之间同步訪问共享资源的一种方式,须要相互排斥来防止彼此干扰来保证一致性. 利用Zookeeper的强一致性能够完毕锁服务.Zookeeper的官方文档是列举了两种 ...

  2. 中小型研发团队架构实践:分布式协调服务ZooKeeper

    一.ZooKeeper 是什么 Apache ZooKeeper 由 Apache Hadoop 的子项目发展而来,于 2010 年 11 月正式成为了 Apache 的顶级项目. 相关厂商内容 优秀 ...

  3. AMQ学习笔记 - 14. 实践方案:基于ZooKeeper + ActiveMQ + replicatedLevelDB的主从部署

    概述 基于ZooKeeper + ActiveMQ + replicatedLevelDB,在Windows平台的主从部署方案. 主从部署可以提供数据备份.容错[1]的功能,但是不能提供负载均衡的功能 ...

  4. ZooKeeper实现命名服务

    使用场景  命名服务就是提供名称的服务,Zookeeper的命名服务有两个应用方面.一个是提供类似JNDI功能,另一个是制作分布式的序列号生成器.         JNDI功能,我们利用Zookeep ...

  5. zookeeper命名服务

    zookeeper概念 zooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,底层组成单元是znode,对于zookeeper来说,所有的功能都是基于znode来实现的,因此有万物皆节点 ...

  6. zookeeper全局数据一致性及其典型应用(发布订阅、命名服务、帮助其他集群选举)

    ZooKeeper全局数据一致性: 全局数据一致:集群中每个服务器保存一份相同的数据副本,client 无论连接到哪个服务器,展示的数据都是一致的,这是最重要的特征. 那么zookeeper集群是怎样 ...

  7. springcloud实践(一)服务发现:Eureka

    Eureka 入门 是什么? Eureka 是 Netflix 开源的一个 RESTful服务,主要用于服务注册与发现. 它由Eureka server 和Eureka client组成. Eurek ...

  8. 全链路实践Spring Cloud 微服务架构

    Spring Cloud 微服务架构全链路实践Spring Cloud 微服务架构全链路实践 阅读目录: 网关请求流程 Eureka 服务治理 Config 配置中心 Hystrix 监控 服务调用链 ...

  9. nginx及其常用实践方案

    nginx及其常用实践方案 1.概述 1.1 什么是nginx? 1.2 什么是反向代理? 2.nginx常用命令 3.ningx配置实践 3.1 nginx.conf基础配置项 3.2 http 反 ...

随机推荐

  1. 【Android每周专题】触摸屏事件

    本系列文章均为A2BGeek原创,转载务必在明显处注明: 转载自A2BGeek的[Android每周专题]系列,原文链接:http://blog.csdn.net/benbmw2008/article ...

  2. broadcom6838开发环境实现函数栈追踪

    在嵌入式设备开发中.内核为内核模块的函数栈追踪已经提供了非常好的支持,但用户层的函数栈追踪确没有非常好的提供支持. 在网上收集学习函数栈跟踪大部分都是描写叙述INTER体系架构支持栈帧的实现机制.或者 ...

  3. HTML5:footer定位(底部+居中)的探讨+div图片居中问题

    初学HTML+CSS布局,尝试自己写一个百度首页,可是footer的定位遇到麻烦而且百度没有好的解决方法,在此记录下逐步的过程.记录之,备忘. 初学,解决方法难免出现不妥之处,也请看到这篇文章的前辈指 ...

  4. jeecg 3.5.2 新版本号4种首页风格 【经典风格,shortcut风格,ACE bootstrap风格,云桌面风格】

    [1]经典风格: [2]Shortcut风格: [3]ACE bootsrap风格: [4]云桌面风格: [5]自己定义图表 watermark/2/text/aHR0cDovL2Jsb2cuY3Nk ...

  5. 关于http接口开发中json格式数据编码问题处理

    关于http接口开发中json格式数据编码问题处理 在实际工作中,接口很多时候返回json格式,但有时返回的格式会有编码问题 假设如下接口:http://service.test.com/interf ...

  6. 【Cloud Foundry】Could Foundry学习(三)——Router

    在阅读的过程中有不论什么问题.欢迎一起交流 邮箱:1494713801@qq.com    QQ:1494713801 一.概述 Router组件在Cloud Foundry中是对全部进来的Reque ...

  7. 解决:Could not find debuginfo pkg for dependency package glibc-2.12-1.132.el6_5.3.i686

    场景: (gdb) break main Breakpoint 1 at 0x8048417 (gdb) r Starting program: /usr/local/src/ccode/ch11/s ...

  8. 异常学习笔记+打包+doc该软件包编译

    jvm调用默认的异常处理机制printStackTrace办法      欲了解更多异常处理.问题      捕获异常代码块出现继承关系 应该把被继承的异常放在子类异常块的后面 watermark/2 ...

  9. http协议之cookie标准RFC6265介绍

      [Docs] [txt|pdf] [draft-ietf-httpst...] [Diff1] [Diff2] [Errata] PROPOSED STANDARD Errata Exist In ...

  10. WPF如何获得变量异步回调函数时产生的异步回调

    有这样的问题,WPF当使用异步回调,需要使用产生的异步变量中的回调函数.数据库中查询诸如异步函数来获得一DataTable.怎样传递给回调函数呢? [方案一]使用全局变量 非常easy想到的是用全局变 ...