Thrift 客户端 C# ---实现zookeeper监视(1)

来源:互联网 发布:大数据神经网络 编辑:程序博客网 时间:2024/05/29 05:01

干货---实现思路:RPC Thrift 服务端 注册服务端信息到zookeeper上。客户端从zookeeper获取服务端信息,并实现负载。
经验---注意事项。
Thrift服务端
使用ZooKeeperNet nugget包。
使用zookeeper的坑,
1、)没有zookeeper.open的方法。
2、)zookeeper 实例化【new ZooKeeper(connectstring, sessionTimeout, watcher);】后,连接CONNECTED并不是同步的。
zookeeper监视,使用一次后就失效。坑
1)、zookeeper 监视某个节点,无论增加删除等操作,一律都只有EventType.NodeChildrenChanged。
2)想检测某个末端节点,使用【_zookeeper.Exists方法即可】。
功能:
1)实现简单负载,轮询负载。随机负载。
2)实现从监视节点取出服务器节点信息。
3)长连接线程池未实现。可以去掉。
4)实现自动释放socket连接资源避免,线上出问题。
使用    public static Client GetSingleInstance(string rpcServicenamespace) 实列化,负载才能正常使用。
    public class Client : IDisposable    {        /// <summary>        /// 客户端池-根据不同业务自动选择对应业务客户端        /// </summary>        static Dictionary<string, Client> _clientPool = new Dictionary<string, Client>();        /// <summary>        ///客户端-TBufferedTransport        /// </summary>        internal Dictionary<string, TBufferedTransport> _tBufferedTransportPool = new Dictionary<string, TBufferedTransport>();        /// <summary>        /// zookeeper注册唯一标识        /// </summary>        private string _rpcServicenamespace = null;//"XXXX.XXXX.RegionCityRPC"        /// <summary>        /// 使用一个zookeeper客户端        /// </summary>        private static ZooKeeper _zookeeper = null;        /// <summary>        /// 多线程锁        /// </summary>        internal static object _look = new object();        /// <summary>        /// zookeeper-所有监视节点        /// </summary>        public IEnumerable<string> _nodeChildren = null;        /// <summary>        /// 轮询负载计数器        /// </summary>        private int CountLoadbalance = 0;                /// <summary>        /// 构造函数        /// </summary>        /// <param name="rpcServicenamespace"></param>        public Client(string rpcServicenamespace)        {            this._rpcServicenamespace = rpcServicenamespace;        }        /// <summary>        /// 获取一个唯一实例        /// </summary>        /// <param name="key"></param>        /// <returns></returns>        public static T GetSingleInstance<T>(Dictionary<string, T> dictionary, string key, T t) where T : class        {            if (!dictionary.Keys.Contains(key))            {                lock (_look)                {                    if (!dictionary.Keys.Contains(key))                    {                        TBufferedTransport tbufferedTransport = t as TBufferedTransport;                        //if (t != null)                        //{                        //    try                        //    {                        //        tbufferedTransport.Open();                        //    }                        //    catch (Exception e)                        //    {                        //        Console.WriteLine("初始化TBufferedTransport连接异常!");                        //    }                        //}                        dictionary.Add(key, t);                    }                }            }            return dictionary[key];        }        /// <summary>        /// 获取一个唯一实例        /// </summary>        /// <param name="rpcServicenamespace"></param>        /// <returns></returns>        public static Client GetSingleInstance(string rpcServicenamespace)        {            /*            if (!_clientPool.Keys.Contains(rpcServicenamespace))            {                lock (_look)                {                    if (!_clientPool.Keys.Contains(rpcServicenamespace))                    {                        _clientPool.Add(rpcServicenamespace, new Client(rpcServicenamespace));                    }                }            }            return _clientPool[rpcServicenamespace];             */            return GetSingleInstance<Client>(_clientPool, rpcServicenamespace, new Client(rpcServicenamespace));        }        //public void FilterTBufferedTransportPool(Client client)        //{        //    foreach (var item in client._tBufferedTransportPool)        //    {        //        item.Value.IsOpen        //    }        //}        /// <summary>        /// 获取baoxian/appSettings配置        /// </summary>        /// <returns></returns>        private static NameValueCollection GetConfig()        {            return (NameValueCollection)ConfigurationManager.GetSection("baoxian/appSettings");        }        /// <summary>        /// 初始化        /// </summary>        public void Init()        {            CreateZookeeperClient();        }        /// <summary>        /// 创建一个zookeeper客户端        /// </summary>        /// <returns></returns>        public ZooKeeper CreateZookeeperClient()        {            string connectstring = GetConfig()["ZookeeperConnectString"];// "192.168.1.3:2331            TimeSpan sessionTimeout = new TimeSpan(0, 0, 60);            var watcher = new ClientWatcher(_rpcServicenamespace);            if (_zookeeper == null)//单线程            {                lock (_look)                {                    if (_zookeeper == null)//多线程                    {                        _zookeeper = new ZooKeeper(connectstring, sessionTimeout, watcher);                        string path = string.Format(GetConfig()[_rpcServicenamespace], _rpcServicenamespace);//string.Format("/test/servicecenter-dev/services/{0}/providers", "YinXin.BaoXian.UserOrderCount");                        int count = 0;                        while (true)                        {                            Console.WriteLine("_zookeeper 重连次数:" + count);                            count++;                            System.Threading.Thread.Sleep(1000);//zookeeper的这个第三方有个坑。1、)没有zookeeper.open的方法。2、)zookeeper 实例化【new ZooKeeper(connectstring, sessionTimeout, watcher);】后,连接CONNECTED并不是同步的。                            if (_zookeeper.State == ZooKeeper.States.CONNECTED)                            {                                GetChildrenWatcher();//zookeeper监视,使用一次后就失效。坑1)、zookeeper 监视某个节点,无论增加删除等操作,一律都只有EventType.NodeChildrenChanged。2)想检测某个末端节点,使用【_zookeeper.Exists方法即可】。                                break;                            }                            if (count >= 60)//这里大于1分钟连接不上                            {                                Logs.WriteLogInfo("_zookeeper网络连接可能有问题!");                                Console.WriteLine("_zookeeper网络连接可能有问题!");                                break;                            }                        }                        /*                        watcher.WaitUntilConnected();                        while (true)                        {                            System.Threading.Thread.Sleep(5000);                            var tt = _zookeeper.GetChildren(path, watcher);                            var aa = tt + "333";                        }*/                    }                }            }            return _zookeeper;        }        /// <summary>        /// 客户端监视-想监视的节点        /// </summary>        public void GetChildrenWatcher()        {            string path = string.Format(GetConfig()[_rpcServicenamespace], _rpcServicenamespace);//string.Format("/test/servicecenter-dev/services/{0}/providers", "XXX.XXX.UserOrderCount");            //var watcher = new ClientWatcher();            IEnumerable<string> nodeChildren = null;            bool isError = false;            try            {                nodeChildren = _zookeeper.GetChildren(path, true);            }            catch (Exception e)            {                Console.WriteLine(e.StackTrace);                isError = true;            }            if (!isError)            {                lock (_look)                {                    _nodeChildren = nodeChildren;                }            }            if (nodeChildren == null)            {                return;            }            foreach (var item in nodeChildren)            {                _zookeeper.Exists(path + "/" + item, true);            }        }        /// <summary>        /// 随机        /// </summary>        /// <returns></returns>        public string Random()        {            IEnumerable<string> nodeChildren = null;            if (_nodeChildren != null)            {                lock (_look)                {                    nodeChildren = _nodeChildren;                }            }            Random random = new Random();            int count = nodeChildren.Count();            if (count == 0)            {                return "false";            }            int index = random.Next(0, nodeChildren.Count() - 1);            return nodeChildren.ToList()[index];        }        /// <summary>        /// 根据负载服务器生成TBufferedTransport        /// </summary>        /// <returns></returns>        public TBufferedTransport GetTSocket(string servers)        {            //string servers = thriftClient.Random();//随机负载            if (string.IsNullOrWhiteSpace(servers))            {                return null;            }            var list = servers.Split(':');            if (list.Count() == 2)            {                //var tbufferedTransport = GetSingleInstance<TBufferedTransport>(_tBufferedTransportPool, servers, new TBufferedTransport(new TSocket(list[0], int.Parse(list[1]))));                return GetSingleInstance<TBufferedTransport>(_tBufferedTransportPool, servers, new TBufferedTransport(new TSocket(list[0], int.Parse(list[1]))));            }            else            {                return null;            }        }        /// <summary>        /// 轮询        /// </summary>        /// <returns></returns>        public string Loadbalance()        {            int index = 0;            IEnumerable<string> nodeChildren = null;            if (_nodeChildren != null)            {                lock (_look)                {                    nodeChildren = _nodeChildren;                    CountLoadbalance++;                    CountLoadbalance = CountLoadbalance > _nodeChildren.Count() ? 1 : CountLoadbalance;                    index = CountLoadbalance;                }            }            if (index - 1 >= 0 && nodeChildren != null && nodeChildren.Count() != 0)            {                return nodeChildren.ToList()[index - 1];            }            else            {                Console.WriteLine("轮询--无节点");                Logs.WriteLogInfo("轮询--无节点");                return "轮询无节点";            }        }        /// <summary>        /// Dispose        /// </summary>        public void Dispose()        {            //关闭并销毁长连接            _zookeeper.Dispose();            foreach (var item in this._tBufferedTransportPool)            {                item.Value.Close();                item.Value.Dispose();            }            //throw new NotImplementedException();        }    }    /// <summary>    /// zookeeper 监测事件实现    /// </summary>    internal class ClientWatcher : IWatcher    {        private Client client;        //private readonly ManualResetEventSlim _connected = new ManualResetEventSlim(false);        //private WatchedEvent _event;        public ClientWatcher(string _rpcServicenamespace)        {            client = Client.GetSingleInstance(_rpcServicenamespace);        }        //public void WaitUntilConnected()        //{        //    _connected.Wait();        //    if (_event == null) throw new ApplicationException("bad state");        //    if (_event.State != KeeperState.SyncConnected)        //        throw new ApplicationException("cannot connect");        //}        /// <summary>        /// 实现Process监控事件        /// </summary>        /// <param name="event"></param>        public void Process(WatchedEvent @event)        {            //_event = @event;            switch (@event.State)            {                case KeeperState.Disconnected:                    break;                case KeeperState.Expired:                    break;                case KeeperState.NoSyncConnected:                    break;                case KeeperState.SyncConnected:                    //_connected.Set();                    break;                case KeeperState.Unknown:                    break;                default:                    break;            }            switch (@event.Type)            {                case EventType.NodeChildrenChanged:                    client.GetChildrenWatcher();//监测节点                    Console.Write(" EventType.NodeChildrenChanged");                    break;                case EventType.NodeCreated:                    Console.Write("EventType.NodeCreated:");                    break;                case EventType.NodeDataChanged:                    Console.Write("EventType.NodeDataChanged:");                    break;                case EventType.NodeDeleted:                    if (!string.IsNullOrWhiteSpace(@event.Path))                    {                        #region socket 长连接时使用,慎用                        string path = @event.Path.Substring(0, @event.Path.LastIndexOf('/'));                        string name = @event.Path.Substring(@event.Path.LastIndexOf('/') + 1);                        lock (Client._look)                        {                            client._tBufferedTransportPool[name].Close();                            client._tBufferedTransportPool[name].Dispose();                            client._tBufferedTransportPool.Remove(name);                        }                        #endregion                    }                    Console.Write("EventType.NodeDeleted:");                    break;                case EventType.None:                    Console.Write("EventType.None:");                    break;                default:                    break;            }        }    }

原创粉丝点击