Beispiel #1
0
        private void ProcessRedisQueue(RedisNode node)
        {
            using var span = _tracer?.NewSpan($"Alarm:{nameof(RedisMessageQueue)}");

            // 所有队列
            var list = RedisMessageQueue.FindAllByRedisId(node.Id);

            foreach (var queue in list)
            {
                var groupName = !queue.Category.IsNullOrEmpty() ? queue.Category : node.Category;
                var webhook   = !queue.WebHook.IsNullOrEmpty() ? queue.WebHook : node.WebHook;

                // 判断告警
                if (queue.Enable && queue.MaxMessages > 0 && queue.Messages >= queue.MaxMessages && RobotHelper.CanAlarm(groupName, webhook))
                {
                    // 一定时间内不要重复报错,除非错误翻倍
                    var error2 = _cache.Get <Int32>("alarm:RedisMessageQueue:" + queue.Id);
                    if (error2 == 0 || queue.Messages > error2 * 2)
                    {
                        _cache.Set("alarm:RedisMessageQueue:" + queue.Id, queue.Messages, 5 * 60);

                        var msg = GetMarkdown(node, queue, true);
                        RobotHelper.SendAlarm(groupName, webhook, "消息队列告警", msg);
                    }
                }
            }
        }
Beispiel #2
0
        public void TraceNode(RedisNode node)
        {
            if (!_servers.TryGetValue(node.Id, out var rds))
            {
                _servers[node.Id] = rds = new FullRedis();
            }

            // 可能后面更新了服务器地址和密码
            rds.Server   = node.Server;
            rds.Password = node.Password;
            rds.Tracer   = DefaultTracer.Instance;

            //var inf = rds.GetInfo(true);
            var inf = rds.GetInfo(false);

            node.Fill(inf);
            node.SaveAsync();

            var data = new RedisData
            {
                RedisId = node.Id,
                Name    = node.Name,
            };
            var dbs = data.Fill(inf);

            data.Insert();

            // 扫描队列
            if (node.ScanQueue && dbs != null)
            {
                ScanQueue(node, dbs);
            }
        }
Beispiel #3
0
        private static String GetMarkdown(RedisNode node, RedisMessageQueue queue, Boolean includeTitle)
        {
            var sb = new StringBuilder();

            if (includeTitle)
            {
                sb.AppendLine($"### [{queue.Name}/{node}]消息队列告警");
            }
            sb.AppendLine($">**主题:**<font color=\"info\">{queue.Topic}</font>");
            sb.AppendLine($">**积压:**<font color=\"info\">{queue.Messages:n0} > {queue.MaxMessages:n0}</font>");
            sb.AppendLine($">**消费者:**<font color=\"info\">{queue.Consumers}</font>");
            sb.AppendLine($">**总消费:**<font color=\"info\">{queue.Total:n0}</font>");
            sb.AppendLine($">**服务器:**<font color=\"info\">{node.Server}</font>");

            var str = sb.ToString();

            if (str.Length > 2000)
            {
                str = str.Substring(0, 2000);
            }

            // 构造网址
            var url = Setting.Current.WebUrl;

            if (!url.IsNullOrEmpty())
            {
                url  = url.EnsureEnd("/") + "Nodes/RedisMessageQueue?redisId=" + queue.RedisId + "&q=" + queue.Name;
                str += Environment.NewLine + $"[更多信息]({url})";
            }

            return(str);
        }
Beispiel #4
0
        private void ScanQueue(RedisNode node, RedisDbEntry[] dbs)
        {
            var queues = RedisMessageQueue.FindAllByRedisId(node.Id);

            for (var i = 0; i < dbs.Length; i++)
            {
                if (dbs[i] == null)
                {
                    continue;
                }

                var rds2 = GetOrAdd(node, i);

                // keys个数太大不支持扫描
                if (rds2.Count < 10000)
                {
                    foreach (var item in rds2.Search("*:Status:*", 1000))
                    {
                        var ss    = item.Split(":");
                        var topic = ss.Take(ss.Length - 2).Join(":");
                        if (topic.IsNullOrEmpty())
                        {
                            continue;
                        }

                        var mq = queues.FirstOrDefault(e => e.Db == i && e.Topic == topic);
                        if (mq == null)
                        {
                            mq = new RedisMessageQueue
                            {
                                RedisId = node.Id,
                                Db      = i,
                                Topic   = topic,
                                Enable  = true,
                            };

                            queues.Add(mq);
                        }

                        mq.Enable = true;
                        if (mq.Name.IsNullOrEmpty())
                        {
                            mq.Name = node.Name;
                        }
                        if (mq.Category.IsNullOrEmpty())
                        {
                            mq.Category = node.Category;
                        }
                        if (mq.Type.IsNullOrEmpty())
                        {
                            mq.Type = topic.EndsWithIgnoreCase(":Delay") ? "Delay" : "Queue";
                        }

                        mq.SaveAsync();
                    }
                }
            }
        }
Beispiel #5
0
        protected override IEnumerable <RedisData> Search(Pager p)
        {
            PageSetting.EnableAdd = false;

            var redisId = p["redisId"].ToInt(-1);

            var start = p["dtStart"].ToDateTime();
            var end   = p["dtEnd"].ToDateTime();

            if (redisId > 0)
            {
                // 最近10小时
                if (p.PageSize == 20 && redisId > 0)
                {
                    p.PageSize = 24 * 60;
                }

                PageSetting.EnableNavbar = false;
            }

            if (p.Sort.IsNullOrEmpty())
            {
                p.OrderBy = _.Id.Desc();
            }

            var list = RedisData.Search(redisId, start, end, p["Q"], p);

            if (list.Count > 0)
            {
                // 绘制日期曲线图
                var node = RedisNode.FindById(redisId);
                if (redisId >= 0 && node != null)
                {
                    var list2 = list.OrderBy(e => e.Id).ToList();

                    var chart = new ECharts
                    {
                        Title = new ChartTitle {
                            Text = node.Name
                        },
                        Height = 400,
                    };
                    chart.SetX(list2, _.CreateTime, e => e.CreateTime.ToString("HH:mm"));
                    chart.SetY("指标");
                    chart.AddLine(list2, _.Speed, null, true);
                    chart.Add(list2, _.InputKbps);
                    chart.Add(list2, _.OutputKbps);
                    chart.Add(list2, _.ConnectedClients);
                    chart.Add(list2, _.UsedMemory);
                    chart.Add(list2, _.Keys);
                    chart.SetTooltip();
                    ViewBag.Charts = new[] { chart };
                }
            }

            return(list);
        }
Beispiel #6
0
        private void ProcessRedisNode(RedisNode node)
        {
            if (node == null || !node.Enable || node.WebHook.IsNullOrEmpty())
            {
                return;
            }

            ProcessRedisData(node);
            ProcessRedisQueue(node);
        }
        /// <summary>
        /// Returns the node for the given id.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public override Node GetNode(long id)
        {
            string    nodeKey   = PrimitiveExtensions.BuildNodeRedisKey(id);
            RedisNode redisNode = _clientNode.GetValue(nodeKey);
            Node      node      = null;

            if (redisNode != null)
            {
                node = PrimitiveExtensions.ConvertFrom(redisNode);
            }
            return(node);
        }
Beispiel #8
0
		//public event Action<PooledSocket> SocketConnected;

		/// <summary>
		/// This will start the pool: initializes the nodelocator, warms up the socket pools, etc.
		/// </summary>
		public void Start()
		{
			// initialize the server list
			foreach (IEndPointConfiguration ip in _configuration.Servers)
			{
				var node = new RedisNode(ip, _configuration.SocketPool, Authenticator);

				_workingServers.Add(node);
			}

			// initializes the locator
			RebuildIndexes();
		}
Beispiel #9
0
        private FullRedis GetOrAdd(RedisNode node, Int32 db)
        {
            var key = $"{node.Id}-{db}";

            if (!_servers2.TryGetValue(key, out var rds))
            {
                _servers2[key] = rds = new FullRedis();
            }

            rds.Server   = node.Server;
            rds.Password = node.Password;
            rds.Db       = db;

            return(rds);
        }
Beispiel #10
0
        private static String GetMarkdown(RedisNode node, RedisData data, String title, IList <Action <StringBuilder> > actions)
        {
            var sb = new StringBuilder();

            if (!title.IsNullOrEmpty())
            {
                sb.AppendLine($"### [{node}]{title}");
            }
            sb.AppendLine($">**分类:**<font color=\"info\">{node.Category}</font>");
            sb.AppendLine($">**版本:**<font color=\"info\">{node.Version}</font>");
            sb.AppendLine($">**已用内存:**<font color=\"info\">{data.UsedMemory:n0}</font>");
            sb.AppendLine($">**内存容量:**<font color=\"info\">{node.MaxMemory:n0}</font>");
            sb.AppendLine($">**连接数:**<font color=\"info\">{data.ConnectedClients:n0}</font>");
            sb.AppendLine($">**服务器:**<font color=\"info\">{node.Server}</font>");

            //var rate = node.MaxMemory == 0 ? 0 : (data.UsedMemory * 100 / node.MaxMemory);
            //if (rate >= node.AlarmMemoryRate && node.AlarmMemoryRate > 0)
            //{
            //    sb.AppendLine($">**内存告警:**<font color=\"info\">{data.UsedMemory}/{node.MaxMemory} >= {node.AlarmMemoryRate:p0}</font>");
            //}

            //if (node.AlarmConnections > 0 && data.ConnectedClients >= node.AlarmConnections)
            //{
            //    sb.AppendLine($">**连接告警:**<font color=\"info\">{data.ConnectedClients:n0} >= {node.AlarmConnections:n0}</font>");
            //}
            foreach (var item in actions)
            {
                item(sb);
            }

            var str = sb.ToString();

            if (str.Length > 2000)
            {
                str = str.Substring(0, 2000);
            }

            // 构造网址
            var url = Setting.Current.WebUrl;

            if (!url.IsNullOrEmpty())
            {
                url  = url.EnsureEnd("/") + "Nodes/RedisNode?id=" + node.Id;
                str += Environment.NewLine + $"[更多信息]({url})";
            }

            return(str);
        }
Beispiel #11
0
        /// <summary>
        /// Converts the given node to a redis node.
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public static RedisNode ConvertTo(Node node)
        {
            RedisNode redisNode = new RedisNode();

            redisNode.Id          = node.Id.Value;
            redisNode.Latitude    = node.Latitude.Value;
            redisNode.Longitude   = node.Longitude.Value;
            redisNode.ChangeSetId = node.ChangeSetId;
            redisNode.TimeStamp   = node.TimeStamp;
            redisNode.UserId      = node.UserId;
            redisNode.UserName    = node.UserName;
            redisNode.Version     = node.Version;
            redisNode.Visible     = node.Visible;
            redisNode.Tags        = PrimitiveExtensions.ConvertTo(node.Tags);

            return(redisNode);
        }
Beispiel #12
0
        /// <summary>
        /// Converts the given node from a redis node.
        /// </summary>
        /// <param name="redisNode"></param>
        /// <returns></returns>
        public static Node ConvertFrom(RedisNode redisNode)
        {
            Node node = new Node();

            node.Id          = redisNode.Id.Value;
            node.Latitude    = redisNode.Latitude.Value;
            node.Longitude   = redisNode.Longitude.Value;
            node.ChangeSetId = redisNode.ChangeSetId;
            node.TimeStamp   = redisNode.TimeStamp;
            node.UserId      = redisNode.UserId;
            node.UserName    = redisNode.UserName;
            node.Version     = redisNode.Version;
            node.Visible     = redisNode.Visible;
            node.Tags        = PrimitiveExtensions.ConvertFrom(redisNode.Tags);

            return(node);
        }
Beispiel #13
0
        private void DoTraceNode(Object state)
        {
            var list = RedisNode.FindAllWithCache();

            foreach (var item in list)
            {
                if (item.Enable)
                {
                    // 捕获异常,不要影响后续操作
                    var key    = $"DoTraceNode:{item.Id}";
                    var errors = _cache.Get <Int64>(key);
                    if (errors < 5)
                    {
                        try
                        {
                            TraceNode(item);

                            _cache.Remove(key);
                        }
                        catch (Exception ex)
                        {
                            errors = _cache.Increment(key, 1);
                            if (errors <= 1)
                            {
                                _cache.SetExpire(key, TimeSpan.FromMinutes(10));
                            }

                            XTrace.WriteException(ex);
                        }
                    }
                    else
                    {
                        item.Enable = false;
                        item.SaveAsync();

                        _cache.Remove(key);
                    }
                }
            }
        }
Beispiel #14
0
        private void DoAlarm(Object state)
        {
            while (_bag.TryTake(out var appId))
            {
                //Process(appId);
            }

            // 应用告警
            var list = AppTracer.FindAllWithCache();

            foreach (var item in list)
            {
                ProcessAppTracer(item);
            }

            // 节点告警
            var nodes = Node.FindAllWithCache();

            foreach (var item in nodes)
            {
                ProcessNode(item);
            }

            // Redis告警
            var rnodes = RedisNode.FindAllWithCache();

            foreach (var item in rnodes)
            {
                ProcessRedisNode(item);
            }

            if (Period > 0)
            {
                _timer.Period = Period * 1000;
            }
        }
Beispiel #15
0
        /// <summary>
        /// Reads an osmGeo object from disk.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="type"></param>
        private OsmGeo Read(long id, OsmGeoType type)
        {
            switch (type)
            {
            case OsmGeoType.Node:
                string    nodeKey   = PrimitiveExtensions.BuildNodeRedisKey(id);
                RedisNode redisNode = _clientNode.GetValue(nodeKey);
                Node      node      = null;
                if (redisNode != null)
                {
                    node = PrimitiveExtensions.ConvertFrom(redisNode);
                }
                return(node);

            case OsmGeoType.Way:
                string   wayKey   = PrimitiveExtensions.BuildWayRedisKey(id);
                RedisWay redisWay = _clientWay.GetValue(wayKey);
                Way      way      = null;
                if (redisWay != null)
                {
                    way = PrimitiveExtensions.ConvertFrom(redisWay);
                }
                return(way);

            case OsmGeoType.Relation:
                string        relationKey   = PrimitiveExtensions.BuildRelationRedisKey(id);
                RedisRelation redisRelation = _clientRelation.GetValue(relationKey);
                Relation      relation      = null;
                if (redisRelation != null)
                {
                    relation = PrimitiveExtensions.ConvertFrom(redisRelation);
                }
                return(relation);
            }
            throw new ArgumentOutOfRangeException("type");
        }
Beispiel #16
0
        private void ProcessRedisData(RedisNode node)
        {
            if (!RobotHelper.CanAlarm(node.Category, node.WebHook))
            {
                return;
            }
            if (node.AlarmMemoryRate <= 0 || node.AlarmConnections == 0)
            {
                return;
            }

            // 最新数据
            var data = RedisData.FindLast(node.Id);

            if (data == null)
            {
                return;
            }

            using var span = _tracer?.NewSpan($"Alarm:{nameof(RedisNode)}");

            var actions = new List <Action <StringBuilder> >();

            // 内存告警
            var rate = data.UsedMemory * 100 / node.MaxMemory;

            if (rate >= node.AlarmMemoryRate)
            {
                // 一定时间内不要重复报错,除非错误翻倍
                var error2 = _cache.Get <Int32>("alarm:RedisMemory:" + node.Id);
                if (error2 == 0 || rate > error2 * 2)
                {
                    _cache.Set("alarm:RedisMemory:" + node.Id, rate, 5 * 60);

                    actions.Add(sb => sb.AppendLine($">**内存告警:**<font color=\"info\">{rate / 100:p0} >= {node.AlarmMemoryRate / 100:p0}</font>"));
                }
            }

            // 连接数告警
            var cs = data.ConnectedClients;

            if (node.AlarmConnections > 0 && cs >= node.AlarmConnections)
            {
                // 一定时间内不要重复报错,除非错误翻倍
                var error2 = _cache.Get <Int32>("alarm:RedisConnections:" + node.Id);
                if (error2 == 0 || cs > error2 * 2)
                {
                    _cache.Set("alarm:RedisConnections:" + node.Id, cs, 5 * 60);

                    actions.Add(sb => sb.AppendLine($">**连接数告警:**<font color=\"info\">{cs:n0} >= {node.AlarmConnections:n0}</font>"));
                }
            }

            // 速度告警
            var speed = data.Speed;

            if (node.AlarmSpeed > 0 && speed >= node.AlarmSpeed)
            {
                // 一定时间内不要重复报错,除非错误翻倍
                var error2 = _cache.Get <Int32>("alarm:RedisSpeed:" + node.Id);
                if (error2 == 0 || speed > error2 * 2)
                {
                    _cache.Set("alarm:RedisSpeed:" + node.Id, speed, 5 * 60);

                    actions.Add(sb => sb.AppendLine($">**速度告警:**<font color=\"info\">{speed:n0} >= {node.AlarmSpeed:n0}</font>"));
                }
            }

            // 入流量告警
            var input = data.InputKbps;

            if (node.AlarmInputKbps > 0 && input >= node.AlarmInputKbps)
            {
                // 一定时间内不要重复报错,除非错误翻倍
                var error2 = _cache.Get <Int32>("alarm:RedisInputKbps:" + node.Id);
                if (error2 == 0 || input > error2 * 2)
                {
                    _cache.Set("alarm:RedisInputKbps:" + node.Id, input, 5 * 60);

                    actions.Add(sb => sb.AppendLine($">**入流量告警:**<font color=\"info\">{input:n0} >= {node.AlarmInputKbps:n0}</font>"));
                }
            }

            // 出流量告警
            var output = data.OutputKbps;

            if (node.AlarmOutputKbps > 0 && output >= node.AlarmOutputKbps)
            {
                // 一定时间内不要重复报错,除非错误翻倍
                var error2 = _cache.Get <Int32>("alarm:RedisOutputKbps:" + node.Id);
                if (error2 == 0 || output > error2 * 2)
                {
                    _cache.Set("alarm:RedisOutputKbps:" + node.Id, output, 5 * 60);

                    actions.Add(sb => sb.AppendLine($">**出流量告警:**<font color=\"info\">{output:n0} >= {node.AlarmOutputKbps:n0}</font>"));
                }
            }

            if (actions.Count > 0)
            {
                var msg = GetMarkdown(node, data, "Redis告警", actions);
                RobotHelper.SendAlarm(node.Category, node.WebHook, "Redis告警", msg);
            }
        }