zoukankan      html  css  js  c++  java
  • windows服务插件利器-新生命组件XAgent使用心得

    1.简单介绍

    XAgent为大石头带领下的新生命团队自己开发的一个.Net下的常用的Windows服务管理组件利器,通过在控制台中简单的输入1,2,3,4,5等数字可以实现一步安装、卸载WindowsService以及单步调试和循环调试、服务停止,重启、运行,用起来很方便。看效果(具体使用方法可以去XAgent官网查看):

    2.当前使用场景介绍及实现

    我的这个项目下面有很多控制台应用程序需要运行,平时部署很麻烦,不方便管理。我的想法是把这些程序以插件的形式放到一个应用程序中运行管理。这里写了一个Ijob接口。看代码:

    Ijob相关代码

     1   /// <summary>工作接口</summary>
     2     public interface IJob
     3     {
     4         /// <summary>
     5         /// 工作组件顺序
     6         /// </summary>
     7         int Sort { get; set; }
     8 
     9         /// <summary>
    10         /// 间隔时间
    11         /// </summary>
    12         int JobInterval { get; set; }
    13 
    14         /// <summary>启动</summary>
    15         /// <returns></returns>
    16         bool Start();
    17 
    18         /// <summary>停止</summary>
    19         /// <returns></returns>
    20         bool Stop();
    21 
    22         /// <summary>工作</summary>
    23         bool Work();
    24 
    25         //void WriteLog(string format, params object[] args);
    26     }
    27 
    28     /// <summary>基础工作组件</summary>
    29     public class Job : IJob
    30     {
    31         ///// <summary>
    32         ///// 是否执行
    33         ///// </summary>
    34         //public bool IsExcute { get; set; }
    35 
    36         public Job()
    37         {
    38             Sort = 0;
    39             DisplayName = "基础工作组件";
    40             JobInterval = 60; //默认60秒
    41             //IsExcute = true;//默认执行
    42         }
    43 
    44         /// <summary>工作组件名</summary>
    45         public virtual string DisplayName { get; set; }
    46 
    47         /// <summary>工作组件顺序</summary>
    48         public virtual int Sort { get; set; }
    49 
    50         /// <summary>
    51         /// 时间间隔
    52         /// </summary>
    53         public int JobInterval { get; set; }
    54 
    55         /// <summary>启动</summary>
    56         public virtual bool Start()
    57         {
    58             WriteLog("开始工作");
    59             return false;
    60         }
    61 
    62         /// <summary>停止</summary>
    63         /// <returns></returns>
    64         public virtual bool Stop()
    65         {
    66             WriteLog("停止工作");
    67             return false;
    68         }
    69 
    70         /// <summary>工作</summary>
    71         public virtual bool Work()
    72         {
    73             WriteLog("正在运行");
    74             return false;
    75         }
    76 
    77         public virtual void WriteLog(string format, params object[] args)
    78         {
    79             //XTrace.WriteLine("[" + this.GetType() + "] [" + DisplayName + "]  " + format, args);
    80             XTrace.WriteLine("[" + DisplayName + "]  " + format, args);
    81         }
    View Code
     1  public static class JobHelper
     2     {
     3         static readonly List<Type> _hasInited = new List<Type>();
     4 
     5         private static List<IJob> op_cache = new List<IJob>();
     6 
     7         /// <summary>所有工作组件</summary>
     8         public static List<IJob> Works
     9         {
    10             get
    11             {
    12                 var list = LoadWork();
    13                 foreach (var item in list)
    14                 {
    15                     EnsureInit(item);
    16                 }
    17                 op_cache = op_cache.OrderBy(j => j.Sort).ToList();
    18                 return op_cache;
    19             }
    20         }
    21 
    22         /// <summary>确保实体类已经执行完静态构造函数,因为那里实在是太容易导致死锁了</summary>
    23         /// <param name="type">类型</param>
    24         internal static void EnsureInit(Type type)
    25         {
    26             if (_hasInited.Contains(type)) return;
    27             // 先实例化,在锁里面添加到列表但不实例化,避免实体类的实例化过程中访问CreateOperate导致死锁产生
    28             var item = type.CreateInstance();
    29             lock (_hasInited)
    30                 // 如果这里锁定_hasInited,还是有可能死锁,因为可能实体类A的静态构造函数中可能导致调用另一个实体类的EnsureInit
    31                 // 其实我们这里加锁的目的,本来就是为了避免重复添加同一个type而已
    32                 //lock ("_hasInited" + type.FullName)
    33             {
    34                 if (_hasInited.Contains(type)) return;
    35 
    36 
    37                 if (op_cache.Contains(item as IJob)) return;
    38                 op_cache.Add(item as IJob);
    39 
    40 
    41                 //type.CreateInstance();
    42                 _hasInited.Add(type);
    43             }
    44         }
    45 
    46         /// <summary>列出所有工作接口</summary>
    47         /// <returns></returns>
    48         public static List<Type> LoadWork()
    49         {
    50             return typeof (IJob).GetAllSubclasses(true).ToList();
    51         }
    52     }
    View Code

    确保所有的工作组件继承Job类,重写其中的方法,将一些需要配置的属性做成xml进行管理。废话不说看代码:

    这是其中一个工作插件

     1    public HourStatisticsWork()
     2         {
     3          
     4 
     5             DisplayName = "小时统计组件";
     6             Sort = 2;
     7 
     8             if (WorkSetting.Current.HourStatisticsEnable)
     9             {
    10                 JobInterval = WorkSetting.Current.HourStatisticsInterval;
    11             }
    12             else
    13             {
    14                 JobInterval = -1; //禁用此组件
    15             }
    16         }
    17 
    18         public override bool Work()
    19         {
    20             StartWork();
    21             return base.Work();
    22         }
    23         public override bool Stop()
    24         {
    25             if (_HourTimer != null)
    26             {
    27                 _HourTimer.Dispose();
    28             }
    29             return base.Stop();
    30         }
    31         public void StartWork()
    32         {
    33             try
    34             {
    35               // Console.WriteLine("当前时间{0}",DateTime.Now);
    36                 //var time = WorkSetting.Current.HourStatisticsInterval;
    37                 //// 定时器一分钟后启动
    38                 //if (_HourTimer == null)
    39                 //    _HourTimer = new TimerX(obj =>
    40                 //    {
    41 
    42 
    43                 //        StartWork();
    44                 //    }, null, 3 * 1000, time);
    45                 DateTime dt = DateTime.Now.AddHours(-1);
    46                 cyStatistics(dt);
    47                 sccStatistics(dt);
    48                 ccStatistics(dt);
    49                 jcStatistics(dt);
    50                 mfStatistics(dt);
    51                 vcStatistics(dt);
    52                 vbStatistics(dt);
    53                 pulStatistics(dt);
    54                 icStatistics(dt);
    55                 rhcStatistics(dt);
    56                 dtrStatistics(dt);
    57 
    58                 MotorLoadStatistics(dt);
    59                 TimeStatistics(dt);
    60                 Container.Info("[HourStatisticsWork]Hour Statistics");
    61             }
    62             catch (Exception ex)
    63             {
    64                 Container.Error($"[HourStatisticsWork]{ex.Message}");
    65             }
    66 
    67         }
    View Code

    相关配置项

     1  [DisplayName("运行参数设置")]
     2     [XmlConfigFile(@"ConfigWorkSetting.config", 15000)]
     3     public class WorkSetting : XmlConfig<WorkSetting>
     4     {
     5         //private String _LastTool;
     6         ///// <summary>最后一个使用的工具</summary>
     7         //[DisplayName("最后一个使用的工具")]
     8         //public String LastTool { get { return _LastTool; } set { _LastTool = value; } }
     9 
    10         protected override void OnNew()
    11         {
    12             SystemName = "物联网监控系统";
    13             LastUpdateTime = new DateTime(2017, 1, 1);
    14 
    15             RabbitMqResolveEnable = true;
    16             RabbitMqResolveInterval = 1;//默认1s
    17             HourStatisticsEnable = true;
    18             HourStatisticsInterval = 30*60;//默认30min
    19 
    20             DayStatisticsEnable = true;
    21             DayStatisticsInterval = 12 * 60*60;//默认12个小时
    22 
    23             EnableViewServiceLog = false;
    24         }
    25 
    26         #region 队列解析
    27 
    28         [Description("启用队列解析")]
    29         public bool RabbitMqResolveEnable { get; set; }
    30         [Description("队列解析间隔时间,单位:秒")]
    31         public int RabbitMqResolveInterval { get; set; }
    32 
    33         #endregion 
    34 
    35         #region 小时统计
    36 
    37         [Description("启用小时统计")]
    38         public bool HourStatisticsEnable { get; set; }
    39         [Description("小时统计间隔时间,单位:秒")]
    40         public int HourStatisticsInterval { get; set; }
    41         #endregion
    42 
    43         #region 自然日统计
    44 
    45         [Description("启用自然日统计")]
    46         public bool DayStatisticsEnable { get; set; }
    47         [Description("自然日统计间隔时间,单位:秒")]
    48         public int DayStatisticsInterval { get; set; }
    49         #endregion 
    50 
    51         #region 异常通知
    52 
    53         [Description("启用异常通知")]
    54         public bool ExceptionNotifyEnable { get; set; }
    55 
    56         [Description("异常通知级别")]
    57         public int ExceptionNotifyLevel { get; set; }
    58 
    59         #endregion 异常通知
    60 
    61         #region 系统
    62 
    63         /// <summary>
    64         ///     系统名称
    65         /// </summary>
    66         [Description("系统名称")]
    67         public String SystemName { get; set; }
    68 
    69         /// <summary>最后更新时间</summary>
    70         [Description("最后更新时间")]
    71         public DateTime LastUpdateTime { get; set; }
    72 
    73         #endregion 系统
    74 
    75         #region Windows  Service
    76 
    77         /// <summary>服务名</summary>
    78         [Description("服务名")]
    79         public String ServiceName { get; set; }
    80 
    81         /// <summary>显示名</summary>
    82         [Description("显示名")]
    83         public String DisplayName { get; set; }
    84 
    85         /// <summary>服务描述</summary>
    86         [Description("服务描述")]
    87         public String Description { get; set; }
    88 
    89         /// <summary>查看服务运行日志</summary>
    90         [Description("查看服务运行日志")]
    91         public bool EnableViewServiceLog { get; set; }
    92 
    93         #endregion Windows  Service
    94     }
    View Code

    一切准备好后,开始生成项目并运行,效果如下:

    3.发现问题

    看起来一切运行正常,但是等到我讲xml文件中的HourStatisticsEnable设置成false时,发现只有第一个队列解析的服务在运行。第三个自然日统计的服务没有运行。这时我注意到,原来是插件运行的先后顺序影响的,即Sort属性。本质上还是JobInterval控制了改插件是否运行。可能XAgent的源代码有些小问题,我没有继续深入到源代码中去查找解决,而是直接通过xml配置文件的Enable判断该组件是否运行。

    代码如下:

     1   public HourStatisticsWork()
     2         {
     3          
     4             if (WorkSetting.Current.HourStatisticsEnable)
     5             {
     6                 DisplayName = "小时统计组件";
     7                 Sort = 2;
     8                 JobInterval = WorkSetting.Current.HourStatisticsInterval;
     9             }
    10             else
    11             {
    12                 //JobInterval = -1; //禁用此组件
    13             }
    14         }
    15 
    16         public override bool Work()
    17         {
    18             if (WorkSetting.Current.HourStatisticsEnable)
    19             {
    20                 StartWork();
    21             }
    22             return base.Work();
    23         }
    24         public override bool Stop()
    25         {
    26             if (_HourTimer != null)
    27             {
    28                 _HourTimer.Dispose();
    29             }
    30             return base.Stop();
    31         }
    32         public void StartWork()
    33         {//todo}
    View Code

    另外,该IJob接口借鉴了我曾经的领导的想法。

    供大家学习,如有不正不妥之处请大家指正。谢谢!

    需要源码的或者帮助的联系我QQ:694666781

  • 相关阅读:
    LuaJIT 之 FFI
    rtmp时间戳问题导致的丢帧,帧率显示错误
    c# 调用 c++的 dll 中关于 char*传入传出参数
    “Microsoft”中不存在类型或命名空间名称“Office”(是否缺少程序集引用?)
    udp,select超时和recvfrom收不到数据原因
    rtmpdump应用在window中
    Win7下安装openssl
    debug模式不报错,release模式报错
    qt 断点无效
    http协议 c++ 接收
  • 原文地址:https://www.cnblogs.com/gbat/p/6375086.html
Copyright © 2011-2022 走看看