使用C# 和Consul进行分布式系统协调
随着大数据时代的到来,分布式是解决大数据问题的一个主要手段,随着越来越多的分布式的服务,如何在分布式的系统中对这些服务做协调变成了一个很棘手的问题。今天我们就来看看如何使用C# ,利用开源对分布式服务做协调。
在对分布式的应用做协调的时候,主要会碰到以下的应用场景:
- 业务发现(service discovery)
找到分布式系统中存在那些可用的服务和节点
- 名字服务 (name service)
通过给定的名字知道到对应的资源
- 配置管理 (configuration management)
如何在分布式的节点中共享配置文件,保证一致性。
- 故障发现和故障转移 (failure detection and failover)
当某一个节点出故障的时候,如何检测到并通知其它节点, 或者把想用的服务转移到其它的可用节点
- 领导选举(leader election)
如何在众多的节点中选举一个领导者,来协调所有的节点
- 分布式的锁 (distributed exclusive lock)
如何通过锁在分布式的服务中进行同步
- 消息和通知服务 (message queue and notification)
如何在分布式的服务中传递消息,以通知的形式对事件作出主动的响应
Consul
Consul是用Go开发的分布式服务协调管理的工具,它提供了服务发现,健康检查,Key/Value存储等功能,并且支持跨数据中心的功能。consul提供的一些关键特性:
- service discovery:consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易,一些外部服务,例如saas提供的也可以一样注册。
- health checking:健康检测使consul可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面。
- key/value storage:一个用来存储动态配置的系统。提供简单的HTTP接口,可以在任何地方操作。
- multi-datacenter:无需复杂的配置,即可支持任意数量的区域。
Consul基于HTTP的API可以方便的和各种语言进行绑定,C# 语言绑定https://github.com/PlayFab/consuldotnet

Consul在Cluster上的每一个节点都运行一个Agent,这个Agent可以使用Server或者Client模式。Client负责到Server的高效通信,相对为无状态的。 Server负责包括选举领导节点,维护cluster的状态,对所有的查询做出响应,跨数据中心的通信等等。
consul官网已经有编译好的二进制包,支持各种平台:win、linux等等,下载符合你平台的软件包:在这里,下载包:0.5.2_windows_386.zip。解压完毕后只有一个consul文件。
D:\GitHub\consuldotnet\Consul.Test>consul
usage: consul [--version] [--help] <command> [<args>]
Available commands are:
agent Runs a Consul agent
configtest Validate config file
event Fire a new event
exec Executes a command on Consul nodes
force-leave Forces a member of the cluster to enter the "left" state
info Provides debugging information for operators
join Tell Consul agent to join cluster
keygen Generates a new encryption key
keyring Manages gossip layer encryption keys
leave Gracefully leaves the Consul cluster and shuts down
lock Execute a command holding a lock
maint Controls node or service maintenance mode
members Lists the members of a Consul cluster
monitor Stream logs from a Consul agent
reload Triggers the agent to reload configuration files
version Prints the Consul version
watch Watch for changes in Consul
consul安装完毕后,agent就可以启动了,agent可以运行在server或者client模式,每个数据中心至少有一个agent运行在server模式,一般建议是3或者5个server。部署单个server是非常不好的,因为在失败场景中出现数据丢失是不可避免的。本文涵盖的是创建一个新的数据中心,所有其他的agents都运行在client模式,这是一个非常轻量级的服务注册进程,它会运行健康监测,并将查询结果转发到服务。agent必须运行在集群中的每一个节点上。
consul.exe agent -config-file test_config.json
我们先运行一个agent在server模式:
D:\GitHub\consuldotnet\Consul.Test> consul.exe agent -config-file test_config.json
==> WARNING: Bootstrap mode enabled! Do not enable unless necessary
==> WARNING: Windows is not recommended as a Consul server. Do not use in production.
==> WARNING: It is highly recommended to set GOMAXPROCS higher than 1
==> Starting Consul agent...
==> Starting Consul agent RPC...
==> Consul agent running!
Node name: 'GEFFZHANG-NB'
Datacenter: 'dc1'
Server: true (bootstrap: true)
Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400)
Cluster Addr: 192.168.1.4 (LAN: 8301, WAN: 8302)
Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false
Atlas: <disabled>
==> Log data will now stream in as it occurs:
2015/08/09 09:14:48 [INFO] serf: EventMemberJoin: GEFFZHANG-NB 192.168.1.4
2015/08/09 09:14:48 [INFO] serf: EventMemberJoin: GEFFZHANG-NB.dc1 192.168.1.4
2015/08/09 09:14:48 [INFO] raft: Node at 192.168.1.4:8300 [Follower] entering Follower state
2015/08/09 09:14:48 [INFO] consul: adding server GEFFZHANG-NB (Addr: 192.168.1.4:8300) (DC: dc1)
2015/08/09 09:14:48 [INFO] consul: adding server GEFFZHANG-NB.dc1 (Addr: 192.168.1.4:8300) (DC: dc1)
2015/08/09 09:14:48 [ERR] agent: failed to sync remote state: No cluster leader
2015/08/09 09:14:50 [WARN] raft: Heartbeat timeout reached, starting election
2015/08/09 09:14:50 [INFO] raft: Node at 192.168.1.4:8300 [Candidate] entering Candidate state
2015/08/09 09:14:50 [DEBUG] raft: Votes needed: 1
2015/08/09 09:14:50 [DEBUG] raft: Vote granted. Tally: 1
2015/08/09 09:14:50 [INFO] raft: Election won. Tally: 1
2015/08/09 09:14:50 [INFO] raft: Node at 192.168.1.4:8300 [Leader] entering Leader state
2015/08/09 09:14:50 [INFO] consul: cluster leadership acquired
2015/08/09 09:14:50 [INFO] consul: New leader elected: GEFFZHANG-NB
2015/08/09 09:14:50 [INFO] raft: Disabling EnableSingleNode (bootstrap)
2015/08/09 09:14:50 [DEBUG] raft: Node 192.168.1.4:8300 updated peer set (2): [192.168.1.4:8300]
2015/08/09 09:14:50 [DEBUG] consul: reset tombstone GC to index 2
2015/08/09 09:14:50 [INFO] consul: member 'GEFFZHANG-NB' joined, marking health alive
2015/08/09 09:14:51 [INFO] agent: Synced service 'consul'
2015/08/09 09:16:03 [DEBUG] agent: Service 'consul' in sync
2015/08/09 09:17:30 [DEBUG] agent: Service 'consul' in sync
2015/08/09 09:18:38 [DEBUG] agent: Service 'consul' in sync
2015/08/09 09:19:47 [DEBUG] http: Request /v1/status/peers (0)
2015/08/09 09:19:52 [DEBUG] agent: Service 'consul' in sync
正如你看到的一样,consul agent已经启动了,并且打印了一些日志到终端上,从日志中可以看到我们的agent已经运行在server模式了,并且已经是整个集群的领导节点。而且,本地成员已经被标记为集群中的健康成员了。这时候你在另一个终端中运行consul members就可以看到整个集群中的成员了。这时候你只能看到你自己,因为我们的集群中还没加入其他成员。

输出已经显示了你自己的节点信息,有地址信息、健康状况、在集群中的角色、以及一些版本信息,如果要查看一些metadata,则可以加入-detailed标记

consul members命令输出的信息是基于gossip协议产生的,并且最终一致的。
KV基本操作
Consul提供了一个简单的K/V存储系统,这可以用来动态获取配置、进行服务协调、主节点选举,其他开发人员能想到的build过程等等。
var client = new Client();
var kv = client.KV;
var key = GenerateTestKeyName();
var value = Encoding.UTF8.GetBytes("test");
var getRequest = kv.Get(key);
Assert.IsNull(getRequest.Response);
var pair = new KVPair(key)
{
Flags = 42,
Value = value
};
var putRequest = kv.Put(pair);
Assert.IsTrue(putRequest.Response);
getRequest = kv.Get(key);
var res = getRequest.Response;
Assert.IsNotNull(res);
Assert.IsTrue(StructuralComparisons.StructuralEqualityComparer.Equals(value, res.Value));
Assert.AreEqual(pair.Flags, res.Flags);
Assert.IsTrue(getRequest.LastIndex > 0);
var del = kv.Delete(key);
Assert.IsTrue(del.Response);
getRequest = kv.Get(key);
Assert.IsNull(getRequest.Response);
服务发现(Service Discovery)和健康检查(Health Check)
Consul的另一个主要的功能是用于对分布式的服务做管理,用户可以注册一个服务,同时还提供对服务做健康检测的功能。
服务定义:一个服务可以通过提供服务定义配置文件或者通过调用HTTP API来动态的增加、删除、修改服务。
服务查询:一旦agent启动后,并且服务已经同步,我们就可以使用DNS或者HTTP API来进行查询了。
服务升级:服务定义的升级可以通过先修改服务定义配置文件,然后给agent发送一个SIGHUP信号即可,这样允许你在升级服务时,而不会产生agent宕机时间或者服务不可达。或者通过HTTP API接口来动态的增加、删除、修改服务。
Consul支持三种Check的模式:
- 调用一个外部脚本(Script),在该模式下,consul定时会调用一个外部脚本,通过脚本的返回内容获得对应服务的健康状态。
- 调用HTTP,在该模式下,consul定时会调用一个HTTP请求,返回2XX,则为健康;429 (Too many request)是警告。其它均为不健康
- 主动上报,在该模式下,服务需要主动调用一个consul提供的HTTP PUT请求,上报健康状态。
C# API提供对应的接口
- Client.Agent.Service
- Client.Agent.Check
Consul的Health Check,通过调用脚本,HTTP或者主动上报的方式检查服务的状态,更为灵活,可以获得等多的信息,但是也需要做更多的工作。
故障检测(Failure Detection)
Consul提供Session的概念,利用Session可以检查服务是否存活。对每一个服务我们都可以创建一个session对象,注意这里我们设置了ttl,consul会以ttl的数值为间隔时间,持续的对session的存活做检查。对应的在服务中,我们需要持续的renew session,保证session是合法的。
var client = new Client();
var sessionRequest = client.Session.Create(new SessionEntry() { TTL = TimeSpan.FromSeconds(10) });
var id = sessionRequest.Response;
Assert.IsTrue(sessionRequest.RequestTime.TotalMilliseconds > 0);
Assert.IsFalse(string.IsNullOrEmpty(sessionRequest.Response));
var tokenSource = new CancellationTokenSource();
var ct = tokenSource.Token;
client.Session.RenewPeriodic(TimeSpan.FromSeconds(1), id, WriteOptions.Empty, ct);
tokenSource.CancelAfter(3000);
Task.Delay(3000, ct).Wait(ct);
var infoRequest = client.Session.Info(id);
Assert.IsTrue(infoRequest.LastIndex > 0);
Assert.IsNotNull(infoRequest.KnownLeader);
Assert.AreEqual(id, infoRequest.Response.ID);
Assert.IsTrue(client.Session.Destroy(id).Response);
这里注意,因为是基于ttl(最小10秒)的检测,从业务中断到被检测到,至少有10秒的时延,对应需要实时响应的情景,并不适用。
领导选举和分布式的锁
这篇文档介绍了如何利用Consul的KV存储来实现Leader Election,利用Consul的KV功能,可以很方便的实现领导选举和锁的功能。
WEB UI
consul同样也支持web界面,这个UI可以用来查看所有的服务和节点,所有的健康检测和它们当前的状态,读取设置K/V系统的值。UI默认自动支持多datacenter。这些UI是静态html你不需要单独运行一个web服务器,consul agent本身可以配置一个web服务。
下载UI组件:WEB UI
下载完成后是一个0.5.2_web_ui.zip压缩文件,解压后是一个dist目录。然后添加-ui-dir参数和-client参数重新启动agent。
D:\GitHub\consuldotnet\Consul.Test> consul.exe agent -config-file test_config.json -ui-dir=D:\GitHub\consuldotnet\Consul.Test\0.5.2_web_ui\dist
在浏览器中输入http://127.0.0.1:8500,即可访问UI了

有services、nodes、K/V、acl、datacenter的管理,很完善的一个系统了。
总结
Consul作为使用Go语言开发的分布式协调,对业务发现的管理提供很好的支持,他的HTTP API也能很好的和不同的语言绑定,并支持跨数据中心的应用。缺点是相对较新,适合喜欢尝试新事物的用户。
https://github.com/anurse/Consulate
https://github.com/geffzhang/Consul-IO-WindowsDemo
https://github.com/catwithboots/Hortlak
https://github.com/catwithboots/Orek
https://github.com/geffzhang/Pk.OrleansUtils
http://blog.csdn.net/u010246789/article/category/6286612
使用C# 和Consul进行分布式系统协调的更多相关文章
- 使用Python进行分布式系统协调 (ZooKeeper/Consul/etcd)
来源:naughty 链接:my.oschina.net/taogang/blog/410864 笔者之前的博文提到过,随着大数据时代的到来,分布式是解决大数据问题的一个主要手段,随着越来越多的分布式 ...
- consul 集群安装
上图是官网提供的一个事例系统图,图中的Server是consul服务端高可用集群,Client是consul客户端.consul客户端不保存数据,客户端将接收到的请求转发给响应的Server端.Ser ...
- .NET Core微服务之路:文章系列和内容索引汇总 (v0.52)
微服务架构,对于从事JAVA架构的童鞋来说,早已不是什么新鲜的事儿,他们有鼎鼎大名的Spring Cloud这样的全家桶框架支撑,包含微服务核心组件如 1. Eureka:实现服务注册与发现. 2. ...
- 使用 Redis 实现分布式系统轻量级协调技术
http://www.ibm.com/developerworks/cn/opensource/os-cn-redis-coordinate/index.html 在分布式系统中,各个进程(本文使用进 ...
- etcd 与 Zookeeper、Consul 等其它 kv 组件的对比
基于etcd的分布式配置中心 etcd docs | etcd versus other key-value stores https://etcd.io/docs/v3.4.0/learning/w ...
- Zookeeper分布式系统协同器概念快速学习
原文格式可以访问:https://www.rockysky.tech 分布式系统的基本操作 主节点选举:在绝大多数分布式系统中,都需要进行主节点选举.主节点负责管理协调其它节点或者同步集群中其它节点的 ...
- zookeeper与分布式系统
1.1. 分布式系统基础知识 一个tomcat打天下的时代,不能说完全淘汰了,在一个管理系统,小型项目中还经常使用,这并不过分,出于成本的考虑,这反而值得提倡. 1.1.1. 分布式系统是什么 分 ...
- [转载] nosql 数据库的分布式算法
原文: http://juliashine.com/distributed-algorithms-in-nosql-databases/ NoSQL数据库的分布式算法 On 2012年11月9日 in ...
- HBase架构
文章作者:luxianghao 文章来源:http://www.cnblogs.com/luxianghao/p/6573817.html 转载请注明,谢谢合作. 免责声明:文章内容仅代表个人观点, ...
随机推荐
- logstash file输入,无输出原因与解决办法
1.现象 很多同学在用logstash input 为file的时候,经常会出现如下问题:配置文件无误,logstash有时一直停留在等待输入的界面 2.解释 logstash作为日志分析的管道,在实 ...
- bootstrap-fileinput 简单使用
bootstrap-fileinput 是一款图片/文件上传 bootstrap 插件,简单示例代码: <!DOCTYPE html> <html> <head> ...
- java 利用ManagementFactory获取jvm,os的一些信息--转
原文地址:http://blog.csdn.net/dream_broken/article/details/49759043 想了解下某个Java项目的运行时jvm的情况,可以使用一些监控工具,比如 ...
- C#数组,List,Dictionary的相互转换
本篇文章会向大家实例讲述以下内容: 将数组转换为List 将List转换为数组 将数组转换为Dictionary 将Dictionary 转换为数组 将List转换为Dictionary 将Dicti ...
- Opserver开源的服务器监控系统(ASP.NET)
Opserver是Stack Exchange下的一个开源监控系统,系统本身由C#语言开发的ASP.NET(MVC)应用程序,无需任何复杂的应用配置,入门很快.下载地址:https://github. ...
- Jvm 内存浅析 及 GC个人学习总结
从诞生至今,20多年过去,Java至今仍是使用最为广泛的语言.这仰赖于Java提供的各种技术和特性,让开发人员能优雅的编写高效的程序.今天我们就来说说Java的一项基本但非常重要的技术内存管理 了解C ...
- golang sync.WaitGroup bug
注意,这个结构体,要是想在函数之间传来传去的话,必须要使用指针....... 这个结构体里没有 指针,这个类型可以说没有“引用特性”. 被坑了一晚上.特此记录.
- Java 教程整理:基础、项目全都有
Java 在编程语言排行榜中一直位列前排,可知 Java 语言的受欢迎程度了. 网上有很多 Java 教程,无论是基础入门还是开发小项目的教程都比比皆是,可是系统的很少,对于Java 学习者来说找到系 ...
- 用Swagger生成接口文档
Swagger简介 在系统设计的时候,各个应用之间往往是通过接口进行交互的.因此接口的定义在整个团队中就变得尤为重要.我们可以把接口的规范用接口描述语言进行描述,然后Swagger可以根据我们定义的接 ...
- DevOps对于企业IT的价值
其实从敏捷延展开的 DevOps 概念很早就已经被提出,不过由于配套的技术成熟度水平层次不齐, DevOps 的价值一直没有有效地发挥出来.现如今,随着容器技术的发展, DevOps 在企业中的实践难 ...