C#使用zookeeper
C#使用zookeeper
https://blog.csdn.net/XuWei_XuWei/article/details/80611659
1.简述
zookeeper适用于分布式锁,配置管理,服务器管理,服务发现场景
c#使用zookeeper基于开源组件ZooKeeperNetEx,详情GitHub搜一下
2.安装开发包
使用nuget安装ZooKeeperNetEx和ZooKeeperNetEx.Recipes,版本是3.4.9.3
3.配置
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.8.0" newVersion="2.6.8.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<appSettings>
<add key="forcerun" value="0"/>
<add key="pathname" value="ZooKeeperTest"/>
<add key="servicename" value="ZooKeeperTest1"/>
<add key="isonline" value="0"/>
</appSettings>
4.封装(依赖log4net)
--------AuthEnum.cs------
public enum AuthEnum
{
world = 0,
auth = 1,
digest = 2,
ip = 3,
super = 4
}
-------DefaultWatcher.cs-----
/// <summary>
/// 默认监听
/// </summary>
public class DefaultWatcher : Watcher
{
private readonly ILog _log;
internal static readonly Task CompletedTask = TaskEx.FromResult(1);
public DefaultWatcher(ILog log)
{
_log = log;
}
/// <summary>
/// 接收通知
/// </summary>
/// <param name="event"></param>
/// <returns></returns>
public override Task process(WatchedEvent @event)
{
_log.ErrorFormat("接收到ZooKeeper服务端的通知,State是:{0},EventType是:{1},Path是:{2}", @event.getState(), @event.get_Type(), @event.getPath() ?? string.Empty);
return CompletedTask;
}
}
---------NodeWatcher.cs--------
/// <summary>
/// 节点监听
/// </summary>
public class NodeWatcher : Watcher
{
private readonly ILog _log;
private string _state;
private Event.EventType _type;
private string _path;
internal static readonly Task CompletedTask = TaskEx.FromResult(1);
public NodeWatcher(ILog log)
{
_log = log;
}
public override Task process(WatchedEvent @event)
{
_state = @event.getState().ToString();
_type = @event.get_Type();
_path = @event.getPath();
switch (_type)
{
case Event.EventType.NodeCreated:
HandleCreate();
break;
case Event.EventType.NodeDeleted:
HandleDelete();
break;
case Event.EventType.NodeDataChanged:
HandleDataChange();
break;
case Event.EventType.NodeChildrenChanged:
HandleChildrenChange();
break;
default:
HandleNone();
break;
}
return CompletedTask;
}
/// <summary>
/// 创建节点事件
/// </summary>
private void HandleCreate()
{
_log.ErrorFormat("NodeCreated");
}
private void HandleDelete()
{
_log.ErrorFormat("NodeDeleted");
}
private void HandleDataChange()
{
_log.ErrorFormat("NodeDataChanged");
}
private void HandleChildrenChange()
{
_log.ErrorFormat("NodeChildrenChanged");
}
private void HandleNone()
{
_log.ErrorFormat(_state);
}
}
--------ZooKeeperHelper.cs--------
public class ZooKeeperHelper
{
private readonly ILog _log;
private bool _isonline = Convert.ToBoolean(ConfigurationManager.AppSettings["isonline"].ConventToInt32());
private List<string> _address;
private int _sessiontTimeout = 10*1000;//10秒
private ZooKeeper _zooKeeper;
private int _connectTimeout = 3*30*1000;//每个zookeeper实例尝试连接最长30秒
private string _success = "success";
private string _fail = "fail";
public ZooKeeperHelper(ILog log,int sessionTimeOut = 10*1000)
{
_log = log;
_sessiontTimeout = sessionTimeOut;
if (_isonline)
{
//正式环境
_address = new List<string> { "192.168.204.92:2181", "192.168.204.92:2182", "192.168.204.92:2183" };
}
else
{
//本地调试环境
_address = new List<string> { "10.168.100.102:2181", "10.168.100.102:2182", "10.168.100.102:2183" };
}
}
/// <summary>
/// 返回null表示连接不成功
/// </summary>
/// <param name="authEnum"></param>
/// <param name="authInfo"></param>
/// <returns></returns>
public ZooKeeper Connect(AuthEnum authEnum ,string authInfo) {
try
{
foreach (string address in _address)
{
_zooKeeper = new ZooKeeper(address, _sessiontTimeout, new DefaultWatcher(_log));
if (authEnum != AuthEnum.world)
{
_zooKeeper.addAuthInfo(authEnum.ToString(), System.Text.Encoding.UTF8.GetBytes(authInfo));
}
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
while (stopwatch.ElapsedMilliseconds < _connectTimeout/_address.Count)
{
ZooKeeper.States states = _zooKeeper.getState();
if (states == ZooKeeper.States.CONNECTED || states == ZooKeeper.States.CONNECTEDREADONLY)
{
break;
}
}
stopwatch.Stop();
if (_zooKeeper.getState().ToString().ToUpper().Contains("CONNECTED"))
{
break;
}
}
return _zooKeeper;
}
catch (Exception ex)
{
_log.ErrorFormat("连接zookeeper发生异常:{0}", ex.Message + ex.StackTrace);
}
return null;
}
/// <summary>
/// 创建节点,不能在临时节点下创建子节点
/// </summary>
/// <param name="path">不要使用path等关键字作为路径</param>
/// <param name="data"></param>
/// <param name="persistent"></param>
/// <returns></returns>
public string CreateNode(string path,string data,bool persistent = false) {
try {
Task<string> task = _zooKeeper.createAsync(path, System.Text.Encoding.UTF8.GetBytes(data), ZooDefs.Ids.OPEN_ACL_UNSAFE, persistent ? CreateMode.PERSISTENT : CreateMode.EPHEMERAL);
task.Wait();
if (!string.IsNullOrEmpty(task.Result) && task.Status.ToString().ToLower() == "RanToCompletion".ToLower())
{
return task.Result;
}
}
catch (Exception ex) {
_log.ErrorFormat("创建节点发生异常:{0}({1}),{2}",path ,data,ex.Message + ex.StackTrace);
}
return _fail;
}
/// <summary>
/// 删除节点,删除节点的子节点个数必须为0,否则请先删除子节点
/// </summary>
/// <param name="path">不要使用path等关键字作为路径</param>
/// <returns></returns>
public string DeleteNode(string path) {
try
{
Task task = _zooKeeper.deleteAsync(path);
task.Wait();
if (task.Status.ToString().ToLower() == "RanToCompletion".ToLower())
{
return _success;
}
}
catch (Exception ex)
{
_log.ErrorFormat("删除节点发生异常:{0},{1}", path,ex.Message + ex.StackTrace);
}
return _fail;
}
/// <summary>
/// 给节点设置数据
/// </summary>
/// <param name="path">不要使用path等关键字作为路径</param>
/// <param name="data"></param>
/// <returns></returns>
public string SetData(string path,string data) {
try
{
Task<org.apache.zookeeper.data.Stat> stat = _zooKeeper.setDataAsync(path, System.Text.Encoding.UTF8.GetBytes(data));
stat.Wait();
if (stat.Result != null && stat.Status.ToString().ToLower() == "RanToCompletion".ToLower())
{
return _success;
}
}
catch (Exception ex)
{
_log.ErrorFormat("设置节点数据发生异常:{0}({1}),{2}",path,data, ex.Message + ex.StackTrace);
}
return _fail;
}
/// <summary>
/// 判断节点是否存在
/// </summary>
/// <param name="path">不要使用path等关键字作为路径</param>
/// <param name="watcher"></param>
/// <returns></returns>
public string ExistsNode(string path, Watcher watcher = null) {
try
{
Task<org.apache.zookeeper.data.Stat> stat = _zooKeeper.existsAsync(path, watcher);
stat.Wait();
if (stat.Result != null && stat.Status.ToString().ToLower() == "RanToCompletion".ToLower())
{
return _success;
}
}
catch (Exception ex)
{
_log.ErrorFormat("判定节点存在与否发生异常:{0},{1}", path, ex.Message + ex.StackTrace);
}
return _fail;
}
/// <summary>
/// 得到节点相关信息
/// </summary>
/// <param name="path">不要使用path等关键字作为路径</param>
/// <param name="watcher"></param>
/// <returns></returns>
public Stat GetNode(string path, Watcher watcher = null)
{
try
{
Task<org.apache.zookeeper.data.Stat> stat = _zooKeeper.existsAsync(path, watcher);
stat.Wait();
if (stat.Result != null && stat.Status.ToString().ToLower() == "RanToCompletion".ToLower())
{
return stat.Result;
}
}
catch (Exception ex)
{
_log.ErrorFormat("得到节点信息发生异常:{0},{1}", path, ex.Message + ex.StackTrace);
}
return null;
}
/// <summary>
/// 得到节点数据
/// </summary>
/// <param name="path">不要使用path等关键字作为路径</param>
/// <param name="watcher"></param>
/// <returns></returns>
public string GetData(string path, Watcher watcher = null) {
try
{
Task<DataResult> dataResult = _zooKeeper.getDataAsync(path, watcher);
dataResult.Wait();
if (dataResult.Result != null && dataResult.Status.ToString().ToLower() == "RanToCompletion".ToLower())
{
return Encoding.UTF8.GetString(dataResult.Result.Data);
}
}
catch (Exception ex)
{
_log.ErrorFormat("得到节点数据发生异常:{0},{1}", path, ex.Message + ex.StackTrace);
}
return _fail;
}
/// <summary>
/// 得到后代节点路径
/// </summary>
/// <param name="path">不要使用path等关键字作为路径</param>
/// <param name="watcher"></param>
/// <returns></returns>
public List<string> GetChildren(string path,Watcher watcher = null) {
try
{
Task<ChildrenResult> childrenResult = _zooKeeper.getChildrenAsync(path, watcher);
childrenResult.Wait();
if (childrenResult.Result != null && childrenResult.Status.ToString().ToLower() == "RanToCompletion".ToLower())
{
return childrenResult.Result.Children;
}
}
catch (Exception ex)
{
_log.ErrorFormat("得到后代节点发生异常:{0},{1}", path, ex.Message + ex.StackTrace);
}
return null;
}
/// <summary>
/// 关闭连接
/// </summary>
/// <returns></returns>
public string Close() {
try
{
Task task = _zooKeeper.closeAsync();
task.Wait();
if (task.Status.ToString().ToLower() == "RanToCompletion".ToLower())
{
return _success;
}
}
catch (Exception ex)
{
LogHelper.GetLoger().ErrorFormat("关闭zookeeper发生异常:{0}", ex.Message + ex.StackTrace);
}
return _fail;
}
/// <summary>
/// 得到连接状态
/// </summary>
/// <returns></returns>
public string GetState() {
try
{
if (_zooKeeper != null)
{
ZooKeeper.States states = _zooKeeper.getState();
return states.ToString();
}
}
catch (Exception ex)
{
_log.ErrorFormat("获取zookeeper连接状态发生异常:{0}", ex.Message + ex.StackTrace);
}
return _fail;
}
/// <summary>
/// 是否已经连接
/// </summary>
/// <returns></returns>
public bool Connected()
{
try
{
if (_zooKeeper != null)
{
ZooKeeper.States states = _zooKeeper.getState();
if (states == ZooKeeper.States.CONNECTED || states == ZooKeeper.States.CONNECTEDREADONLY)
{
return true;
}
}
}
catch (Exception ex)
{
_log.ErrorFormat("获取zookeeper连接状态发生异常:{0}", ex.Message + ex.StackTrace);
}
return false;
}
}
--------TaskHelper.cs--------
public class TaskHelper
{
private readonly ILog _log;
private int forcerun = Convert.ToInt32(ConfigurationManager.AppSettings["forcerun"]);
private string servicename = ConfigurationManager.AppSettings["servicename"];
private string pathname = ConfigurationManager.AppSettings["pathname"];
private ZooKeeperHelper _zooKeeperHelper;
private ZooKeeper _zooKeeper;
//单例输出,否则通知过多可能导致内存溢出
private static TaskHelper _taskHelper;
private static object _obj = new object();
private TaskHelper(ILog log,int sessionTimeOut = 10 * 1000)
{
_log = log;
_zooKeeperHelper = new ZooKeeperHelper(_log,sessionTimeOut);
}
public static TaskHelper GetInstance(ILog log, int sessionTimeOut = 10 * 1000)
{
if (_taskHelper == null)
{
lock (_obj)
{
if (_taskHelper == null)
{
_taskHelper = new TaskHelper(log,sessionTimeOut);
}
}
}
return _taskHelper;
}
public bool Return()
{
if (forcerun != 1)
{
try
{
if (!_zooKeeperHelper.Connected())
{
_zooKeeper = _zooKeeperHelper.Connect(AuthEnum.world, "");
if (_zooKeeper == null)
{
_log.ErrorFormat("连接zooKeeper失败,时间是:{0}", DateTime.Now);
return true;
}
}
string path = ("/" + pathname);
string data = servicename;
string str = _zooKeeperHelper.ExistsNode(path, new NodeWatcher(_log));
if (str != "success")
{
str = _zooKeeperHelper.CreateNode(path, data);
if (str != path)
{
_log.ErrorFormat("创建路径失败,时间是:{0}", DateTime.Now);
return true;
}
}
string lockname = _zooKeeperHelper.GetData(path, new NodeWatcher(_log));
#region 测试通知
//string cg = _zooKeeperHelper.SetData(path, "hahhahahah");
//cg = _zooKeeperHelper.GetData(path, new NodeWatcher(_log));
//cg = _zooKeeperHelper.SetData(path, "1111111111");
//cg = _zooKeeperHelper.GetData(path, new NodeWatcher(_log));
//cg = _zooKeeperHelper.DeleteNode(path);
#endregion
//执行标识
if (lockname != servicename)
{
_log.ErrorFormat("非工作时间,当前执行的服务是:{0},时间是:{1}", lockname, DateTime.Now);
return true;
}
}
catch (Exception exception)
{
_log.ErrorFormat("zooKeeperHelper出现异常:{0},时间是:{1}", exception.Message + exception.StackTrace, DateTime.Now);
}
}
return false;
}
}
5.分布式锁应用场景
//协调分布式服务
TaskHelper.GetInstance(log).Return()
---------------------
作者:DO_DAJIANGJUN
来源:CSDN
原文:https://blog.csdn.net/XuWei_XuWei/article/details/80611659
版权声明:本文为博主原创文章,转载请附上博文链接!
C#使用zookeeper的更多相关文章
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- [译]ZOOKEEPER RECIPES-Leader Election
选主 使用ZooKeeper选主的一个简单方法是,在创建znode时使用Sequence和Ephemeral标志.主要思想是,使用一个znode,比如"/election",每个客 ...
- zookeeper源码分析之六session机制
zookeeper中session意味着一个物理连接,客户端连接服务器成功之后,会发送一个连接型请求,此时就会有session 产生. session由sessionTracker产生的,sessio ...
- zookeeper源码分析之五服务端(集群leader)处理请求流程
leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...
- zookeeper源码分析之四服务端(单机)处理请求流程
上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...
- zookeeper源码分析之三客户端发送请求流程
znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...
- zookeeper源码分析之二客户端启动
ZooKeeper Client Library提供了丰富直观的API供用户程序使用,下面是一些常用的API: create(path, data, flags): 创建一个ZNode, path是其 ...
- zookeeper源码分析之一服务端启动过程
zookeeper简介 zookeeper是为分布式应用提供分布式协作服务的开源软件.它提供了一组简单的原子操作,分布式应用可以基于这些原子操作来实现更高层次的同步服务,配置维护,组管理和命名.zoo ...
- zookeeper集群的搭建以及hadoop ha的相关配置
1.环境 centos7 hadoop2.6.5 zookeeper3.4.9 jdk1.8 master作为active主机,data1作为standby备用机,三台机器均作为数据节点,yarn资源 ...
- 如何编译Zookeeper源码
1. 安装Ant Ant下载地址:http://ant.apache.org/bindownload.cgi 解压即可. 2. 下载Zookeeper源码包 https://github.com/ap ...
随机推荐
- Mr. Kitayuta vs. Bamboos CodeForces - 505E (堆,二分答案)
大意: 给定$n$棵竹子, 每棵竹子初始$h_i$, 每天结束时长$a_i$, 共$m$天, 每天可以任选$k$棵竹子砍掉$p$, 若不足$p$则变为0, 求$m$天中竹子最大值的最小值 先二分答案转 ...
- C#下实现的基础K-MEANS多维聚类
资源下载 #本文PDF版下载 C#下实现的基础K-MEANS多维聚类PDF #本文代码下载 基于K-Means的成绩聚类程序 前言 最近由于上C # 课的时候,老师提到了-我们的课程成绩由几个部分组成 ...
- hdu6398 计算几何
不算严格的计算几何,就是各种分类 精度调好就能过,考虑三条边斜着放的所有情况即可 #include<bits/stdc++.h> #define LL long long #define ...
- 判断回文字符串(c,python)
回文字符串:一个字符串,不论是从左往右,还是从右往左,字符的顺序都是一样的(如abba,abcba等) 判断回文字符串比较简单,即用两个变量left,right模仿指针(一个指向第一个字符,一个指向最 ...
- dubbo provider如何对invoker进行export
如何把provider的invoker export出去:1)为原始对象加wrapper,生成invoker:2)给invoker加各种filter,启动监听服务:3)注册服务地址 以HelloSer ...
- dubbo的请求、响应对
dubbo中的请求和响应是如何关联起来的呢? 每一个请求和响应共用同一个id. public class DefaultFuture implements ResponseFuture { // in ...
- dubbo的超时重试
dubbo的超时分为服务端超时 SERVER_TIMEOUT 和客户端超时 CLIENT_TIMEOUT.本文讨论服务端超时的情形: 超时:consumer发送调用请求后,等待服务端的响应,若超过ti ...
- SQL基础分页存储过程(案例一)
--分页 存储过程 案例 -- 所执行的存储过程 create proc pageForUsers @currPage int, --当前页数 @pageSize int, --每页多少条记录 @co ...
- 纪念第一次ak。。。
1.MM的数学作业 [题目大意] 今天,MM在上数学课,数学课的主题是函数.讲完以后老师留了一个家庭作业,让同学们回家思考.题目如下: 定义一个函数,F(x)表示x转成二进制后,二进制中“1”的个数. ...
- ADO SQL delete 日期条件参数
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...