Etcd是一个比较新的分布式协调框架,由CoreOS的开发团队开发,现在才只到0.4.6版本,还没发布1.0版本
我看了一下GitHub上作者们的提交记录,现在应该还在如火如荼的开发以及修改Bug中,估计要有点耐心再等一等了。。。
而且2014年7月25号CoreOS(服务器操作系统)发布了自己的第一个稳定版本,其中包括:
- Linux 3.15.2
- Docker 1.0.1
- Support on all major cloud providers, including Rackspace Cloud, Amazon EC2 (including HVM), and Google Compute Engine
- Commercial support via CoreOS Managed Linux
从网上搜etcd关键字,基本上就只能看到“开源中国”的介绍:
etcd 是一个高可用的 Key/Value 存储系统,主要用于分享配置和服务发现。etcd 的灵感来自于 ZooKeeper 和 Doozer,侧重于:
- 简单:支持 curl 方式的用户 API (HTTP+JSON)
- 安全:可选 SSL 客户端证书认证
- 快速:单实例可达每秒 1000 次写操作
- 可靠:使用 Raft 实现分布式
Etcd is written in Go and uses the raft consensus algorithm to manage a highly-available replicated log.
一、安装和测试
安装非常简单,大概经历以下几个步骤吧:1、下载VMWare9.0虚拟机和一个Ubuntu12 desktop版的ISO,安装好Ubuntu,以及root用户,vim软件等的初始化设置。(必须安装Linux-64bit,否则运行时etcd会出错)
2、下载Go语言编译器,用来编译Etcd的,下载地址是:http://tip.golang.so/dl/,上面有解压说明教程。
3、下载CURL,用于在Linux终端发送HTTP请求到Etcd服务器,网上有它的编译和安装教程,比如这个http://blog.csdn.net/lifan5/article/details/7350154。
4、下载etcd源码,到GitHub下载就可以,下载了以后解压,然后用Go编译器进行编译,它的GitHub网页上有说明。
5、环境都搞完了以后就可以启动etcd了,然后你可以先照着上面的API教程操作一把:https://github.com/coreos/etcd/blob/master/Documentation/api.md
二、.NET客户端代码测试
我准备先开发.NET的客户端,因为这个目前急需。
下载 drusellers/etcetera
然后用VS202打开自行编译成DLL,将DLL加入到自己的新的工程中。
1、节点存活周期测试:
普通创建的节点(不加TTL)在ETCD崩溃或者重启之后,不会被删除,下次再启动Etcd这些节点还会在,值也不会变。
2、节点监视
设置和监视单层节点,正常工作:
1
2
3
4
5
6
7
8
9
10
11static string registryCenterIP = "192.168.195.128"; static int registryCenterPort = 4001; static string sysFlag = "systemA"; static string URL = "http://" + registryCenterIP + ":" + registryCenterPort + "/v2/keys/" + sysFlag + "/"; static EtcdClient client = new EtcdClient(new Uri(URL)); static void Main(string[] args) { client.Set("config1", "value1"); client.Watch("config1", FollowUp_Config); Thread.Sleep(3000); client.Set("config1", "value2"); //watch回调函数会被触发
设置和监视多层节点,将不管用:
1
2
3
4
5
6
7
8
9
10
11static string registryCenterIP = "192.168.195.128"; static int registryCenterPort = 4001; static string sysFlag = "systemA"; static string URL = "http://" + registryCenterIP + ":" + registryCenterPort + "/v2/keys/" + sysFlag + "/"; static EtcdClient client = new EtcdClient(new Uri(URL)); static void Main(string[] args) { client.Set("config1/x", "value1"); client.Watch("config1/x", FollowUp_Config); Thread.Sleep(3000); client.Set("config1/x", "value2"); //watch回调函数不会被触发
因为config1和你预想的不一样,实际上config1不是一个目录,因为内部实现没有解析这样的格式,然后为config1创建一个对应的目录。
而是提供了一个createDir()的接口来创建目录。
所以在为config1创建了目录的前提下,监视config1/x的watch回调函数才会被触发:
1
2
3
4
5client.CreateDir("config1"); client.Set("config1/x", "value1"); client.Watch("config1/x", FollowUp_Config); Thread.Sleep(3000); client.Set("config1/x", "value2"); //watch回调函数会被触发
另外更重要的一点,设置对节点的watch只是一次有效的!!!
比如下面代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19static string registryCenterIP = "192.168.195.128"; static int registryCenterPort = 4001; static string sysFlag = "systemA"; static string URL = "http://" + registryCenterIP + ":" + registryCenterPort + "/v2/keys/" + sysFlag + "/"; static EtcdClient client = new EtcdClient(new Uri(URL)); static void Main(string[] args) { client.Watch("conf", FollowUp_Config); Thread.Sleep(2000); client.Set("conf", "value1"); //会触发watch回调函数 Thread.Sleep(2000); client.Set("conf", "value2"); //不会触发watch回调函数 Thread.Sleep(2000); client.Set("conf", "valuejiyiqin"); //不会触发watch回调函数 Thread.Sleep(2000); client.Delete("conf"); //不会触发watch回调函数
必须要连续设置watch才会有效:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18static string registryCenterIP = "192.168.195.128"; static int registryCenterPort = 4001; static string sysFlag = "systemA"; static string URL = "http://" + registryCenterIP + ":" + registryCenterPort + "/v2/keys/" + sysFlag + "/"; static EtcdClient client = new EtcdClient(new Uri(URL)); static void Main(string[] args) { client.Watch("conQ", FollowUp_Config); Thread.Sleep(2000); client.Set("conQ", "value1"); //会触发watch回调函数 client.Watch("conQ", FollowUp_Config); Thread.Sleep(2000); client.Set("conQ", "value2"); //会触发watch回调函数 client.Watch("conQ", FollowUp_Config); Thread.Sleep(2000); client.Delete("conQ"); //会触发watch回调函数
3、目录监视
如果要监视config1目录,需要在Watch函数的第三个参数recursive = true?指定为true,这样才会触发回调函数。
而且监视只是一次有效,比如这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20static string registryCenterIP = "192.168.195.128"; static int registryCenterPort = 4001; static string sysFlag = "systemA"; static string URL = "http://" + registryCenterIP + ":" + registryCenterPort + "/v2/keys/" + sysFlag + "/"; static EtcdClient client = new EtcdClient(new Uri(URL)); static void Main(string[] args) { client.CreateDir("config2"); client.Watch("config2", FollowUp_Config, true); Thread.Sleep(2000); client.Set("config2/x", "value1"); //会触发watch回调函数 Thread.Sleep(2000); client.Set("config2/x", "value2"); //不会触发watch回调函数 Thread.Sleep(2000); client.Set("config2/y", "valuejiyiqin"); //不会触发watch回调函数 Thread.Sleep(2000); client.Delete("config2/x"); //不会触发watch回调函数
这样才会所有在这个目录下面的增删该操作都会触发回调函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20static string registryCenterIP = "192.168.195.128"; static int registryCenterPort = 4001; static string sysFlag = "systemA"; static string URL = "http://" + registryCenterIP + ":" + registryCenterPort + "/v2/keys/" + sysFlag + "/"; static EtcdClient client = new EtcdClient(new Uri(URL)); static void Main(string[] args) { client.CreateDir("config2"); client.Watch("config2", FollowUp_Config, true); Thread.Sleep(2000); client.Set("config2/x", "value1"); //会触发 client.Watch("config2", FollowUp_Config, true); Thread.Sleep(2000); client.Set("config2/x", "value2"); //会触发 client.Watch("config2", FollowUp_Config, true); Thread.Sleep(2000); client.Set("config2/y", "valuejiyiqin"); //会触发 client.Watch("config2", FollowUp_Config, true); Thread.Sleep(2000); client.Delete("config2/x"); //会触发
4、同一个进程下监视多个节点,同时设置节点值
不要尝试在一个进程中,用一个线程开启对多个节点的监视,然后又在另外一个线程中设置被监视的节点值,然后眼巴巴地期望监视回调函数呗调用,像这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16static void Main(string[] args) { IRegistryCenterClient rCenter = new RegistryCenterClient(registryCenterIP, registryCenterPort, sysFlag); client.Watch(sysFlag + "/config/" + "user1DBConstr", FollowUp_Config, true); client.Watch(sysFlag + "/config/" + "user2DBConstr", FollowUp_Config2, true); Console.WriteLine("设置监视完成"); Thread thread1 = new Thread(Server3); thread1.Start(); Thread.Sleep(15000); } private static void Server3() { IRegistryCenterClient rCenter = new RegistryCenterClient(registryCenterIP, registryCenterPort, sysFlag); Thread.Sleep(4000); rCenter.SetConfigItem("user1DBConstr", "v7"); }
回调函数不会被调用,不管你加不加watch中的recursive参数,也不管你的回调函数指定的是同一个还是不同的,总之不会被调用。
现象就是卡住不动,像这样:
然后我调试了一下,发现是set操作向etcd写值失败!!!原因是response中指示错误。
我非常担心是这个C#的etcd客户端有问题,然后立刻去掉thread1线程的创建,只保留上面的两段监视代码,像这样:
1
2
3
4
5
6
7
8
9
10static void Main(string[] args) { IRegistryCenterClient rCenter = new RegistryCenterClient(registryCenterIP, registryCenterPort, sysFlag); client.Watch(sysFlag + "/config/" + "user1DBConstr", FollowUp_Config, true); client.Watch(sysFlag + "/config/" + "user2DBConstr", FollowUp_Config2, true); Console.WriteLine("设置监视完成"); //Thread thread1 = new Thread(Server3); //thread1.Start(); Thread.Sleep(15000); }
1
2
3
4static void Main(string[] args) { IRegistryCenterClient rCenter = new RegistryCenterClient(registryCenterIP, registryCenterPort, sysFlag); rCenter.SetConfigItem("user1DBConstr", "v7");
果然是同一个进程里面不能同时监视多个节点,然后在另一个线程中给节点写值。
这个问题测试的时候必须要注意!!!
5 etcetera的Bug???
(1)同一个进程下面不能同时监视三个及以上节点
同一个进/线程中使用etcd 的这个C#客户端同时监视三个或者以上的节点不行,开启终端设置这几个节点的值只有监视的前两个节点的回调函数会触发,第三个节点以及之后的节点的回调函数都不会触发了。
(2)Clustering模式下面无法创建目录:
我有这么一段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17try { if (source != null && source is ServiceInfo) { ServiceInfo serviceInfo = source as ServiceInfo; string serviceDir = sysFlag + "/service/" + serviceInfo.serviceName; client.CreateDir(serviceDir); string key = serviceDir + "/" + serviceInfo.serviceIP; string value = JsonSerializer.GetJsonByObject(serviceInfo); client.Set(key, value, nodeTTL); logger.Info("注册服务成功:[key]" + key + ",[value]" + value); } } catch (Exception ee) { logger.Info("[KeepAliveTimer]注册服务失败,原因是:" + ee.Message); }
但是当使用Clustering模式的时候,创建目录这段代码就会抛出异常,原因是Invalid JSON string。
但是我打开Linux终端运行下面命令:
1curl -L http://127.0.0.1:4001/v2/keys/CBIP/service/HelloService -XPUT -d dir=true
我估计就是etcetera的问题,需要查看源码确认调试一下。
这些问题需要在深入研究其源码进行确认!
未完待续。。。
By 季义钦 jiq408694711@163.com
最后
以上就是幸福故事最近收集整理的关于Etcd学习(一)安装和.NET客户端测试的全部内容,更多相关Etcd学习(一)安装和内容请搜索靠谱客的其他文章。
发表评论 取消回复