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 } } }
关于第二步,发送通知, 因为我们会给每个网站配置一个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); } }); }); }