.Net分布式异常报警系统-服务端Service

1. HandleService: 从Redis中获取异常信息, 入库并发送通知到相关责任人。 
2. HealthyCheckService: 对站点指定页面进行模拟访问, 如果请求成功或者返回的内容是约定的内容就表示正常, 否则就会产生一个异常信息, 并发送到http服务端。 
 
HandleService 的处理流程包括1. 从Redis中获取数据 2. 信息持久化到数据库 3. 更新DB中的状态 4 删除Redis中的数据
 public void Handle()
        {
            ThreadPool.SetMaxThreads(10, 40);   //设置线程
            while (true)
            {
                string errorEntityId = RedisHelper.DequeueItemFromList("ErrorEntityQueue");   //从Redis中获取数据
                if (!string.IsNullOrEmpty(errorEntityId))
                {
                    ThreadPool.QueueUserWorkItem(state =>
                    {
                        try
                        {
                            //0. 从Redis中获取数据
                            var errorEntityDto = RedisHelper.Get<ErrorEntityDto>(errorEntityId);
                            //1. 信息持久到DB, 方便后续查看,统计
                            ErrorEntity errorEntity = null;
                            errorEntity = Mapper.Map<ErrorEntity>(errorEntityDto);
                            errorEntity.NotifyStatus = 0; //未通知
                            _errorEntityBusiness.Insert(errorEntity, false);
                            //2. 通知到相关责任人
                            bool issuccess = Notity(errorEntityDto);
                            if (issuccess)
                            {
                                //3. 更新DB中的状态
                                _errorEntityBusiness.UpdateBySql(string.Format("set NotifyStatus = 1 where Id='{0}'", errorEntity.Id));
                            }
                            //4. 删除redis中的数据
                            RedisHelper.Del(errorEntityId);
                        }
                        catch (Exception exception)
                        {
                            LogHelper.Error("处理发生异常", exception);
                        }
                        //todo 这里应该以有个补救措施, 如果通知失败。 应该再另外一个job中对这些失败的通知重新发送。这里就不写了
                    }, errorEntityId);
                }
                else
                {
                    Thread.Sleep(5000); //如果没有取到数据,则暂停5s
                }
            }
        }  
View Code
关于第二步,发送通知, 因为我们会给每个网站配置一个Token , 在上传异常信息的时候, Token会随信息一起上传, 所以在这里, 我们可以根据Token来查找到对应的站点信息, 站点信息中包含有责任人信息, 所以我们就可以找到对应责任人。
 
主要逻辑就是迭代所有站点,并迭代该站点下所有的服务器, 对每个服务器通过模拟请求检查站点是否正常, 关于判断是否正常, 有两种方案,
1. 判断站点返回的http响应码是多少, 如果是200就表示正常。 
2. 判断站点返回的内容是什么, 如果是“OK"或者"success"就表示正常。 
对于第一种方案, 页面可以是一个普通的页面, 但是对于第二种情况, 我们需要新开发一个页面, 可以在这个页面内对所依赖服务或者环境的检测, 如果检测通过就返回“ok”表示正常。。 比如系统依赖数据库和A服务, 那在这个页面中就尝试连接和读取数据库信息和A服务, 注意这些检查操作都应该是“无影响”的, 比如对数据库的操作应该是select操作, 而不应该是insert 或者update操作。 
private  void Handle()
        {
            //获取所有的网站, 依次检查返回的是否为ok, 或者检查http.status=200
            IEnumerable<WebSite> webSites= _webSiteBusiness.GetList("select * from WebSite where Enable = 1");
            Parallel.ForEach(webSites, website =>
            {
                IEnumerable<WebServer> webServers =
                    _webServerBusiness.GetList(
                        (string.Format("select * from WebServer where Enable = 1 and WebId={0}", website.Id)));
                Parallel.ForEach(webServers, webserver =>
                {
                    //这里如果你仅仅想获取状态码, 可以调用 HttpHelper.GetHttpStatus方法
                   var responseText= HttpHelper.SendGetRequest("http://" + webserver.ServerIp + website.CheckUrl, website.Host, website.Host, 3000,
                        Encoding.UTF8);
                    if (responseText != "ok")
                    {
                        //站点出了异常,需要发送到服务端进行处理
                        ClientErrorEntity clientErrorEntity = new ClientErrorEntity();
                        clientErrorEntity.ExceptionMessage = website.WebName + "(" + "http://" + webserver.ServerIp + website.CheckUrl + ")" + "访问发生异常,异常信息如下:" + responseText;
                        clientErrorEntity.Ip = webserver.ServerIp;
                        clientErrorEntity.RequestUrl = "http://" + webserver.ServerIp + website.CheckUrl;
                        clientErrorEntity.Type = 1;
                        ClientErrorEntity.WebToken = website.WebToken;   //重新设置Token
                        SendErrorEntity.SendError(clientErrorEntity);
                    }
                });
            });
        }  
View Code
posted @ 2015-08-24 22:33  秋夜  阅读(619)  评论(0编辑  收藏  举报