服务器性能监控+邮件发送
客户端代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.ServiceProcess; using System.Text; using System.Threading; using System.Management; using System.Configuration; using System.Net; using System.IO; namespace MON.WS { public partial class Service : ServiceBase { //by 刘晓伦 //post 11.9 //卸载服务 //installutil /u F:\XLFX-2\XLFX\MON.WS\bin\debug\MON.WS.EXE //安装服务 //installutil F:\XLFX-2\XLFX\MON.WS\bin\debug\MON.WS.EXE object threadObj; Thread jobThread; Dictionary< string , PerformanceCounter> dicCounter; Dictionary< string , ManagementObject> dicDisk; public Service() { InitializeComponent(); } /// <summary> /// 服务启动 /// </summary> /// <param name="args"></param> protected override void OnStart( string [] args) { threadObj = new object (); dicCounter = new Dictionary< string , PerformanceCounter>(); dicDisk = new Dictionary< string , ManagementObject>(); jobThread = new Thread( new ThreadStart(Job)); jobThread.IsBackground = true ; jobThread.Start(); } /// <summary> /// 服务停止 /// </summary> protected override void OnStop() { if (jobThread.IsAlive) { jobThread.Abort(); jobThread.Join(); } foreach ( var obj in dicCounter.Values) { obj.Dispose(); } foreach ( var obj in dicDisk.Values) { obj.Dispose(); } dicDisk.Clear(); dicCounter.Clear(); } /// <summary> /// 监控线程 /// </summary> void Job() { while ( true ) { lock (threadObj) { //监控开始 try { var obj = new MONServiceClient.MONService(); var hn = Dns.GetHostName(); var ips = GetIpv4Address(hn); if (ips.Count < 1) { obj.Dispose(); Thread.Sleep(60000); //如果服务器出错,那么就每分钟去检查一次 WriteLog( "一个IPV4的地址也没有得到" ); continue ; } DataSet ds = GetConfigDS(hn,ips,obj); if (ds == null ) { obj.Dispose(); Thread.Sleep(60000); WriteLog( "请检查WEBService和全局变量设置" ); continue ; } int sleepTime; try { sleepTime = Convert.ToInt32(ds.Tables[0].Rows[0][ "LOG_CIRC" ]) * 1000; //毫秒 } catch { sleepTime = 60000; } if (sleepTime < 1) { sleepTime = 60000; } Thread.Sleep(sleepTime); if (ds.Tables[1].Rows[0][ "S_ISWATCH" ].ToString() == "0" ) { //监控开关->关闭 obj.Dispose(); continue ; } var arr = getWatchValue(ds).ToArray(); obj.UpdateServerStatus(arr); obj.Dispose(); } catch (Exception ex) { WriteLog(ex.Message); } //监控结束 } } } /// <summary> /// 获取配置信息 /// </summary> /// <param name="ips"></param> /// <returns></returns> DataSet GetConfigDS( string hn,List<IPAddress> ips,MONServiceClient.MONService obj) { DataSet ds; try { if (ips.Count > 1) { ds = obj.GetMachineConfig(hn, ips[0].ToString(), ips[1].ToString()); } else { ds = obj.GetMachineConfig(hn, ips[0].ToString(), "" ); } } catch { ds = null ; } return ds; } /// <summary> /// 获取性能数组 /// </summary> /// <param name="ds"></param> /// <returns></returns> List< string > getWatchValue(DataSet ds) { var result = new List< string >(); result.Add(ds.Tables[1].Rows[0][ "LIST_ID" ].ToString()); result.Add(GetValue(ds.Tables[1].Rows[0][ "S_CPU" ].ToString()).ToString( "F2" )); result.Add(GetDiskValue(ds.Tables[1].Rows[0][ "S_DISK_APP" ].ToString()).ToString( "F2" )); result.Add(GetDiskValue(System.Environment.SystemDirectory.Substring(0, 2)).ToString( "F2" )); result.Add(GetValue(ds.Tables[1].Rows[0][ "S_MEMORY" ].ToString()).ToString( "F2" )); result.Add(GetValue(ds.Tables[1].Rows[0][ "S_FLOW_IN" ].ToString()).ToString( "F2" )); result.Add(GetValue(ds.Tables[1].Rows[0][ "S_FLOW_OUT" ].ToString()).ToString( "F2" )); result.Add(GetValue(ds.Tables[1].Rows[0][ "S_WEB_PORT" ].ToString()).ToString( "F2" )); result.Add(GetValue(ds.Tables[1].Rows[0][ "S_SQL_CONNECT" ].ToString()).ToString( "F2" )); result.Add(ds.Tables[1].Rows[0][ "CAMP_ID" ].ToString()); result.Add(ds.Tables[1].Rows[0][ "CICODE" ].ToString()); result.Add(ds.Tables[1].Rows[0][ "S_KIND" ].ToString()); return result; } /// <summary> /// 获取IPV4的地址 /// </summary> /// <param name="hn"></param> /// <returns></returns> List<IPAddress> GetIpv4Address( string hn) { var result = new List<IPAddress>(); var ips = Dns.GetHostAddresses(hn); foreach ( var ip in ips) { if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) { result.Add(ip); } } return result; } /// <summary> /// 获取性能计数器的值 /// </summary> /// <param name="configStr"></param> /// <returns></returns> double GetValue( string configStr) { try { if (!dicCounter.ContainsKey(configStr)) { var arr = configStr.Split( '#' ); var pc = new PerformanceCounter(); pc.CategoryName = arr[0]; pc.CounterName = arr[1]; pc.InstanceName = arr[2]; dicCounter.Add(configStr, pc); } return dicCounter[configStr].NextValue(); } catch (Exception ex) { WriteLog( string .Format( "计数器取值错误:{0}{1}{2}" , configStr, Environment.NewLine, ex.Message)); return -1; } } /// <summary> /// 获取磁盘信息的值 /// </summary> /// <param name="key"></param> /// <returns></returns> double GetDiskValue( string key) { try { if (!dicDisk.ContainsKey(key)) { ManagementObject DiskInfo = new ManagementObject( string .Format( "win32_logicaldisk.deviceid=\"{0}\"" , key)); dicDisk.Add(key, DiskInfo); } dicDisk[key].Get(); var s = Convert.ToDouble(dicDisk[key][ "Size" ]); var l = Convert.ToDouble(dicDisk[key][ "FreeSpace" ]); var d = (s - l) / s * 100; return d; } catch (Exception ex) { WriteLog( string .Format( "获取磁盘信息值错误:{0}{1}{2}" , key, Environment.NewLine, ex.Message)); return -1; } } /// <summary> /// 写本地日志 /// </summary> /// <param name="text"></param> void WriteLog( string text) { try { var logDic = ConfigurationManager.AppSettings[ "LogDic" ]; int logDays; try { logDays = Convert.ToInt32(ConfigurationManager.AppSettings[ "LogDays" ]); } catch { logDays = 7; } if (logDays < 1) { logDays = 7; } var fs = LogFileMon(logDic, logDays); StreamWriter writer = new StreamWriter(fs); writer.WriteLine(DateTime.Now.ToString()); writer.WriteLine(text); writer.WriteLine( "-----------------------------------------------------------" ); writer.Flush(); writer.Close(); fs.Close(); } catch { //写日志出错就没办法了 } } /// <summary> /// 维护日志文件 /// </summary> /// <param name="logDic"></param> /// <param name="days"></param> FileStream LogFileMon( string logDic, int dayCount) { DirectoryInfo di = new DirectoryInfo(logDic); //如果日志文件夹不存在则创建日志文件夹; if (!di.Exists) { di.Create(); } //当前应保存的日志数据 List< string > days = new List< string >(); for ( var i = 0; i < dayCount; i++) { var d = DateTime.Now.AddDays(0 - i).ToString( "yyyy-MM-dd" ); days.Add( string .Format( "{0}.log" , d)); } //删除没用的历史数据 foreach ( var f in di.GetFiles()) { if (!days.Contains(f.Name)) { f.Delete(); } } //返回当前日志文件的数据流 var fileName = Path.Combine(logDic, days[0]); var fs = File.Open(fileName, FileMode.Append,FileAccess.Write); return fs; } } } |
服务端代码
Imports System.Web.Services Imports System.Web.Services.Protocols Imports System.ComponentModel Imports System.Threading Imports System.Collections.Generic Imports System.Text ' 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 ' <System.Web.Script.Services.ScriptService()> _ <System.Web.Services.WebService( Namespace := "http://tempuri.org/" )> _ <System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _ <ToolboxItem( False )> _ Public Class MONService Inherits System.Web.Services.WebService <WebMethod()> _ Public Function GetMachineConfig( ByVal HostName As String , ByVal IP1 As String , ByVal IP2 As String ) As DataSet Dim sqlda As New data_source.WebTao. Public .SqlServerData Try Dim sSQL As String = "select * from mon_server_list " & _ " where S_HOSTNAME ='" & HostName & "' and IP1 = '" & IP1 & "' and IP2 = '" & IP2 & "'" Dim dt As DataTable = sqlda.GetMytable(sSQL) If dt.Rows.Count < 1 Then sqlda.runSql( "insert into mon_server_list (S_HOSTNAME,IP1,IP2,S_ISWATCH,CICODE,S_NAME,CAMP_ID,S_KIND,STATUS) values ('" & HostName & "','" & IP1 & "','" & IP2 & "',0,'待确定','待确定',-1,0,0)" ) dt = sqlda.GetMytable(sSQL) sqlda.runSql( "INSERT INTO [MON_INFO] ([LIST_ID],[S_CPU],[S_DISK_APP],[S_DISK_SYS],[S_MEMORY],[S_FLOW_IN],[S_FLOW_OUT],[S_WEB_PORT],[S_SQL_CONNECT],[IN_TIME]) VALUES (" & dt.Rows(0)( "LIST_ID" ).ToString() & ",-1,-1,-1,-1,-1,-1,-1,-1,'" & Now.ToString() & "') " ) End If Dim result As DataSet = sqlda.GetMyDataSet( "select * from MON_PARAMETER" ) result.Tables.Add(dt) Return result Catch ex As Exception Return Nothing End Try End Function <WebMethod()> _ Public Function UpdateServerStatus( ByVal ParamArray ValueArr() As String ) Dim sqlda As New data_source.WebTao. Public .SqlServerData Try Dim sSQL As String = "UPDATE [MON_INFO] " & _ " SET " & _ " [S_CPU] = " & ValueArr(1) & _ " ,[S_DISK_APP] = " & ValueArr(2) & _ " ,[S_DISK_SYS] = " & ValueArr(3) & _ " ,[S_MEMORY] = " & ValueArr(4) & _ " ,[S_FLOW_IN] = " & ValueArr(5) & _ " ,[S_FLOW_OUT] = " & ValueArr(6) & _ " ,[S_WEB_PORT] = " & ValueArr(7) & _ " ,[S_SQL_CONNECT] = " & ValueArr(8) & _ " ,[IN_TIME] = '" & Now.ToString() & "'" & _ " WHERE LIST_ID = " & ValueArr(0) sqlda.runSql(sSQL) '没有策略 If ValueArr(9).Trim() = "-1" Or String .IsNullOrEmpty(ValueArr(9).Trim()) Then Return 0 End If '找到策略 sSQL = "select * from MON_CAMPAIGN_LIST where CAMP_ID = " & ValueArr(9) Dim dt As DataTable = sqlda.GetMytable(sSQL) Dim Dic As New Dictionary(Of String , String ) Dic.Add( "S_PRIORITY" , dt.Rows(0)( "S_PRIORITY" ).ToString()) Dic.Add( "S_ACTION" , dt.Rows(0)( "S_ACTION" ).ToString()) '验证策略 sSQL = "select count(*) from MON_INFO where 1=1 and " & dt.Rows(0)( "S_NAME" ).ToString & " and LIST_ID = " & ValueArr(0) Dim FLAG = CType (sqlda.myExecuteScalar(sSQL), Integer ) '没有超标 If FLAG < 1 Then Return 0 End If '是否到了下一个轮训间隔 sSQL = "select TOP 1 * from [MON_MAIL] WHERE list_id = " & ValueArr(0) & " ORDER BY S_SENDTIME DESC " dt = sqlda.GetMytable(sSQL) Dim ts As TimeSpan = TimeSpan.MaxValue If dt.Rows.Count > 0 Then Dim thatTime As DateTime = CType (dt.Rows(0)( "S_SENDTIME" ), DateTime) ts = DateTime.Now.Subtract(thatTime) End If sSQL = "select * from MON_PARAMETER" dt = sqlda.GetMytable(sSQL) Dim circ As Integer = CType (dt.Rows(0)( "MAIL_CIRC" ), Integer ) If ts.TotalSeconds < circ Then Return 0 End If '异步发信 Dic.Add( "S_TITLE" , dt.Rows(0)( "S_TITLE" ).ToString()) Dic.Add( "MAIL_SMTP_SERVER" , dt.Rows(0)( "MAIL_SMTP_SERVER" ).ToString()) Dic.Add( "MAIL_ACCOUNT" , dt.Rows(0)( "MAIL_ACCOUNT" ).ToString()) Dic.Add( "MAIL_PASSWORD" , dt.Rows(0)( "MAIL_PASSWORD" ).ToString()) Dic.Add( "MAIL_FROM" , dt.Rows(0)( "MAIL_FROM" ).ToString()) Dic.Add( "MAIL_ADDRESS" , dt.Rows(0)( "MAIL_ADDRESS" ).ToString()) Dim sout As Double Dim sin As Double Try sin = Convert.ToDouble(ValueArr(5)) / 1024.0 sout = Convert.ToDouble(ValueArr(6)) / 1024.0 Catch ex As Exception sin = -1 sout = -1 End Try Dim sb As New StringBuilder() sb.AppendFormat( "CPU使用率:{0}%<br />" , ValueArr(1)) sb.AppendFormat( "内存使用率:{0}%<br />" , ValueArr(4)) sb.AppendFormat( "系统磁盘使用率:{0}%<br />" , ValueArr(3)) sb.AppendFormat( "文件磁盘使用率:{0}%<br />" , ValueArr(2)) sb.AppendFormat( "网络下行流量IN:{0}KB/S<br />" , sin.ToString()) sb.AppendFormat( "网络上行流量OUT:{0}KB/S<br />" , sout.ToString()) sb.AppendFormat( "网站连接数:{0}<br />" , ValueArr(7)) sb.AppendFormat( "数据库连接数:{0}<br />" , ValueArr(8)) Dim subject As String = String .Format( "人力运营管理系统监控告警:{0}{1}" , ValueArr(10), IIf(ValueArr(11) = "0" , "WEB服务器" , "数据库服务器" )) Dim body As String = String .Format( "{0}<br />{1}<br />{2}<br />{3}<br />{4}" , DateTime.Now.ToString(), Dic( "S_PRIORITY" ), Dic( "S_TITLE" ), sb.ToString(), Dic( "S_ACTION" )) 'TODO:oracle不支持~select @@identity sSQL = "INSERT INTO [MON_MAIL] ([LIST_ID] ,[S_SOURCE] ,[S_CONTENT] ,[S_ACTION] ,[S_PRIORITY] ,[S_ADDRESS] ,[STATUS] ,[S_SENDTIME]) VALUES " & _ "(" & ValueArr(0) & ",'" & Dic( "S_TITLE" ) & "','" & sb.ToString() & "','" & Dic( "S_ACTION" ) & "','" & Dic( "S_PRIORITY" ) & "','" & dt.Rows(0)( "MAIL_ADDRESS" ).ToString() & "',0,'" & DateTime.Now.ToString() & "');select @@identity" Dim index As Integer = CType (sqlda.myExecuteScalar(sSQL), Integer ) Dic.Add( "SUBJECT" , subject) Dic.Add( "BODY" , body) Dic.Add( "INDEX" , index) Dic.Add( "CONSTR" , sqlda.GetMyConnStr()) ThreadPool.QueueUserWorkItem( AddressOf SendMail, Dic) Catch ex As Exception End Try End Function Function SendMail( ByVal setting As Object ) As Integer Try Dim Dic As Dictionary(Of String , String ) = CType (setting, Dictionary(Of String , String )) Dim iSmtpSetting As New PublicFunction.SmtpSetting iSmtpSetting.SmtpServer = Dic( "MAIL_SMTP_SERVER" ) iSmtpSetting.SystemEmailAccount = Dic( "MAIL_ACCOUNT" ) iSmtpSetting.SystemEmailAccountPassword = Dic( "MAIL_PASSWORD" ) iSmtpSetting.SmtpAuthenticationType = 1 Dim result As Boolean = PublicFunction.Mail.SendMail(iSmtpSetting, Dic( "MAIL_FROM" ), Dic( "MAIL_ADDRESS" ), Dic( "SUBJECT" ), Dic( "BODY" ), True , System.Web.Mail.MailPriority.High, System.Text.Encoding.UTF8, New String () {}) Dim val As Integer = IIf(result, 1, 2) Dim sqlda As New data_source.WebTao. Public .SqlServerData(Dic( "CONSTR" )) sqlda.runSql( "update MON_MAIL set STATUS = " & val & " where MAIL_ID = " & Dic( "INDEX" )) Catch ex As Exception End Try End Function End Class |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统