• 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
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    jQuery实现选项联动轮播
    EasyUI datagrid 行编辑
    UEditor的使用
    jQuery Pagination分页插件的使用
    SQL Server论坛楼层计算触发器
    编写了一个简单的串口映射工具
    JS表单验证插件(支持Ajax验证)
    JS虚拟键盘
    JS数字键盘
    HTML的select控件美化
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/10273560.html
Copyright © 2020-2023  润新知