由于项目中有2个使用netTcpBinding的wcf服务经常出现无法提供服务的问题,一直找原因也找不到导致影响严重,更换InstanceContextMode和ConcurrencyMode配置也不好使,出现问题后用户反馈,然后我这边在赶紧重启服务就好了,为此先写个小工具实现自动监控服务端程序是否正常如果不正常则实现自动重新启动服务程序功能,这方法只能治标不治本,对wcf了解的朋友可以给出些调试意见。
程序使用devexpress的chartcontrol控件事实滚动界面,看图:
折线图每次显示50个点,然后动态删除和新增点保持50个点,然后每次访问接口判断是否可以访问,以及是否访问超时,如果达到设置的次数则,直接执行外部程序实现重启wcf目的,然后等待一会后继续监控:
加载配置,启动任务:
1 private void FrmMain_Load(object sender, EventArgs e) 2 { 3 DataBaseTaskScanningMessage = new EventWaitHandle(false, EventResetMode.AutoReset); 4 p1 = this.chartControl1.Series[0].Points; 5 p2 = this.chartControl1.Series[1].Points; 6 7 _appFilePath = ReportInfo.Monitor.m.Default._appFilePath; 8 _pointCount = m.Default._pointCount; 9 _taskTimeSpan = m.Default._taskTimeSpan; 10 _timeOutSpan = m.Default._timeOutSpan; 11 _ntsdPath = m.Default._ntsdPath; 12 13 Run(); 14 } 15 16 private void Run() 17 { 18 errorCount = 0; 19 20 t = new Thread(() => 21 { 22 try 23 { 24 ShowMess("Run......"); 25 taskWait = ThreadPool.UnsafeRegisterWaitForSingleObject(DataBaseTaskScanningMessage, (x, e) => RunSc(), null, _taskTimeSpan, true); 26 this.btn_start.Invoke((MethodInvoker)(() => 27 { 28 this.btn_start.Enabled = false; 29 this.btn_stop.Enabled = true; 30 })); 31 32 } 33 catch (Exception ex) 34 { 35 ShowMess("服务启动异常:" + ex.ToString()); 36 Log.LogService.LogError(string.Format("服务启动异常:{0}!", ex.ToString()), "btn_start_Click"); 37 38 39 this.btn_start.Invoke((MethodInvoker)(() => 40 { 41 this.btn_start.Enabled = true; 42 this.btn_stop.Enabled = false; 43 })); 44 } 45 }); 46 t.IsBackground = true; 47 t.Start(); 48 }
核心任务,超过3次则放置一个rest.txt文件,当服务端读取到这个文件存在时就会自杀然后重生,这是为了解决当服务端是通过任务计划system权限执行时,监控程序无权限结束进程的问题:
1 #region 定时任务 2 3 public static WaitHandle DataBaseTaskScanningMessage { get; private set; } 4 private static RegisteredWaitHandle taskWait; 5 6 public void RunSc() 7 { 8 try 9 { 10 string dt = DateTime.Now.ToString("mm-ss"); 11 Stopwatch sw = new Stopwatch(); 12 sw.Start(); 13 bool state = (new IMServerAgent()).ConnectionTest(); 14 sw.Stop(); 15 16 ShowMess(string.Format("执行接口:{0} 结果:{1} 用时:{2}", "Message", state ? "成功" : "=失败=====", sw.ElapsedMilliseconds), !state); 17 18 if (sw.ElapsedMilliseconds > _timeOutSpan) 19 state = false; 20 21 22 if (p1.Count > _pointCount) 23 p1.RemoveAt(0); 24 p1.Add(new DevExpress.XtraCharts.SeriesPoint(dt, sw.ElapsedMilliseconds)); 25 26 sw.Restart(); 27 bool state2 = (new ClientLogInfoAgent()).AddErrorLog("RunSc", "Monitor"); 28 sw.Stop(); 29 30 31 ShowMess(string.Format("执行接口:{0} 结果:{1} 用时:{2}", "Log ", state2 ? "成功" : "=失败======", sw.ElapsedMilliseconds), !state); 32 33 if (sw.ElapsedMilliseconds > _timeOutSpan) 34 state2 = false; 35 36 if (p2.Count > _pointCount) 37 p2.RemoveAt(0); 38 p2.Add(new DevExpress.XtraCharts.SeriesPoint(dt, sw.ElapsedMilliseconds)); 39 40 41 #region 判读是否出现异常 42 43 if (!state || !state2) 44 Interlocked.Increment(ref errorCount); 45 else 46 Interlocked.Exchange(ref errorCount, 0); 47 48 if (errorCount >= 3) 49 { 50 Interlocked.Exchange(ref errorCount, 0); 51 //异常重启服务 52 if (File.Exists(_appFilePath)) 53 { 54 ShowMess("rest......", true); 55 56 57 string path = @"D:\ReportServer\WebHelp\rest.txt"; 58 if (!System.IO.File.Exists(path)) 59 { 60 if (!System.IO.Directory.Exists(Path.GetDirectoryName(path))) 61 System.IO.Directory.CreateDirectory(Path.GetDirectoryName(path)); 62 System.IO.File.WriteAllText(path, DateTime.Now.ToString()); 63 } 64 65 System.Diagnostics.Process.Start(_appFilePath); 66 67 System.Threading.Thread.Sleep(5 * 1000); 68 int wCount = 0; 69 while (Process.GetProcessesByName("ReportInfo.IMServer").Count() == 0) 70 { 71 wCount++; 72 if (wCount > 100) 73 break; 74 System.Threading.Thread.Sleep(1000); 75 } 76 77 } 78 } 79 80 #endregion 81 82 83 84 } 85 catch (Exception ex) 86 { 87 p1.Clear(); 88 p2.Clear(); 89 ShowMess("RunSc异常:" + ex.ToString()); 90 } 91 finally 92 { 93 taskWait = ThreadPool.UnsafeRegisterWaitForSingleObject(DataBaseTaskScanningMessage, (x, e) => RunSc(), null, _taskTimeSpan, true); 94 } 95 } 96 97 #endregion
毕竟不能根本解决问题,只能起到当有问题时第一时间发现,让用户感觉不到问题的存在。