好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

企业应用微型Windows服务架构

企业应用微型Windows服务架构

企业应用微型Windows服务架构

 

背景:质量检测集团企业内部有N多系统,这些系统之间有关联性并相互协作,很多业务需要Windows服务大显身手

举例:客户通过网站下定单 > 企业内部收到客户快递的样品在实验室系统登记 > 实验室系统检测 > 实验室系统出具检测报告 > 客户通过浏览器查看报告

运用Windows服务进行:

报告文件同步 对客户的短信、邮件通知 对内部工作人员进行短信、邮件通知 进行分公司内网与公共服务器数据同步

  ……

以上只是一个例子,实际情况要复杂的多,很多个服务放在一起运行、维护很不方便,混乱不堪,如何通过一种巧妙的方式进行管理、部署、监控,让管理人员可操作性更强呢?博主写了一个小程序来达到上面的要求,请大家指点一二。

技术点:

XML读写 多线程 反射 Windows服务安装卸载脚本

思路:

windows服务项目是一个装载服务的容器,它负责配置并调用功能组件 提供一个统一的编程接口,使后续所有的功能组件都需要实现这个接口方便服务容器去调用 植入功能组件:实现以上接口并单独做自己的事情,与其他功能组件互不相干 放到Windows服务容器,配置组件信息(执行间隔,程序集名称,类名等)

以上模式有点像一个多媒体播放器程序,自身提供了解析mp3,mp4,wma,rmvb等格式的功能

播放器就是一个装载容器,解析媒体文件格式的组件就相当于插件

当有一种新的媒体格式比如(flv)诞生后,开发者们可以实现播放器提供的接口并解析这种(flv)媒体文件,然后通过配置文件添加到播放器目录即可

当播放器要播放flv的文件,就会去加载解析flv的组件

每一种对媒体格式的解析组件互不影响,这符合松耦合、工厂模式的设计思想

废话说到这里,贴代码:

接口:

 1   public   interface   IRun
  2       {
  3           void   Run();
  4      }

配置文件Config.xml,配置程序集的执行时间间隔,程序集名称,类名

  1   <?  xml version="1.0" encoding="utf-8"   ?> 
  2   <  Configuration  > 
  3     <!-- 
  4     assembly:程序集名称
   5     class:类名
   6     method:固定Run(),默认为Run,对应类需要实现接口IRun并实现Run()
   7     --> 
  8     <  AssemblyConfig  > 
  9         <  Assembly   Interval  ="30000"   Assembly  ="FCL.Monitor"   Class  ="Monitor"   /> 
 10         <  Assembly   Interval  ="30000"   Assembly  ="FCL.Monitor"   Class  ="Monitor_Vancl"   /> 
 11         <  Assembly   Interval  ="30000"   Assembly  ="FCL.Monitor"   Class  ="CreateNotify"   /> 
 12         <  Assembly   Interval  ="30000"   Assembly  ="FCL.Monitor"   Class  ="CreateNotify_Vancl"   /> 
 13         <  Assembly   Interval  ="1000"   Assembly  ="FCL.Email"   Class  ="SendEmail"   /> 
 14     </  AssemblyConfig  > 
 15   </  Configuration  > 

容器加载后需要构造的实体类

  1       public   class   AssemblyInfo
   2       {
   3           ///   <summary> 
  4           ///   执行间隔
   5           ///   </summary> 
  6           public   int  Interval {  get ;  set  ; }
   7  
  8           ///   <summary> 
  9           ///   程序集名称
  10           ///   </summary> 
 11           public   string  AssemblyName {  get ;  set  ; }
  12           ///   <summary> 
 13           ///   类名
  14           ///   </summary> 
 15           public   string  ClassName {  get ;  set  ; }
  16           ///   <summary> 
 17           ///   方法名
  18           ///   </summary> 
 19           public   readonly   string  MethodName =  "  Run  "  ;
  20      }

服务启动需要加载已经配置的程序集

  1           ///   <summary> 
  2           ///   服务启动
   3           ///   </summary> 
  4           ///   <param name="args"></param> 
  5           protected   override   void  OnStart( string  [] args)
   6           {
   7              Log.log.Info(DateTime.Now +  "   服务启动  "  );
   8  
  9               //  读取xml配置 
 10              DataSet ds =  new   DataSet();
  11              ds.ReadXml(Path.Combine(AppDomain.CurrentDomain.BaseDirectory,  "  Config.xml  "  ));
  12              DataTable dt = ds.Tables[ 1  ];
  13              List<AssemblyInfo> assemblyInfoList =  new  List<AssemblyInfo> ();
  14               AssemblyInfo assemblyInfo;
  15               foreach  (DataRow row  in   dt.Rows)
  16               {
  17                  assemblyInfo =  new   AssemblyInfo();
  18                  assemblyInfo.AssemblyName = row[ "  Assembly  "  ].ToString();
  19                  assemblyInfo.ClassName = row[ "  Class  "  ].ToString();
  20                  assemblyInfo.Interval = Convert.ToInt32(row[ "  Interval  "  ]);
  21                   assemblyInfoList.Add(assemblyInfo);
  22  
 23                   Log.log.Info(DateTime.Now
  24                         +  "   程序集名称:  "  +  assemblyInfo.AssemblyName
  25                         +  "  ,类名:  "  +  assemblyInfo.ClassName
  26                         +  "  ,执行间隔:  "  +  assemblyInfo.Interval);
  27               }
  28  
 29               //  加载XML程序集配置 
 30               ExcuteAssembly.ExcuteListAssembly(assemblyInfoList);
  31          }


以及相关用线程、反射执行程序集

     public   class   ExcuteAssembly
    {
          ///   <summary> 
         ///   执行批量程序集
          ///   </summary> 
         ///   <param name="assemblyList">  程序集集合  </param> 
         public   static   void  ExcuteListAssembly(List<AssemblyInfo>  assemblyList)
        {
              try  
            {
                Thread thread;
                  foreach  (AssemblyInfo item  in   assemblyList)
                {
                    thread  =  new  Thread( new   ParameterizedThreadStart(ExcuteSingleAssembly));
                    thread.IsBackground  =  true  ;
                    thread.Start(item);
                }
            }
              catch   (Exception ex)
            {
                Log.log.Error(DateTime.Now  +  "   创建多个线程时:   "  +  ex.Message);
            }
        }

          ///   <summary> 
         ///   执行单个程序集
          ///   </summary> 
         ///   <param name="obj">  程序集  </param> 
         public   static   void  ExcuteSingleAssembly( object   obj)
        {
              while  ( true  )
            {
                  try  
                {
                    AssemblyInfo assembly  = obj  as   AssemblyInfo;
                    Thread.Sleep(assembly.Interval);

                    Log.log.Debug(  "  ExcuteSingleAssembly:  "  + (assembly  as   AssemblyInfo).AssemblyName);
                      if  (assembly !=  null  && assembly  is   AssemblyInfo)
                    {
                        Assembly a  =  Assembly.Load(assembly.AssemblyName);
                          //  Type规则:命名空间名称=程序集名 
                        Type type = a.GetType(assembly.AssemblyName +  "  .  "  +  assembly.ClassName);
                        Log.log.Debug(  "  Type:  "  +  type.ToString());
                        IRun run  =  (IRun)Activator.CreateInstance(type);
                        MethodInfo method  =  type.GetMethod(assembly.MethodName);
                        Log.log.Debug(  "  MethodInfo:  "  +  method.ToString());
                        BindingFlags flags  = BindingFlags.Public |  BindingFlags.Instance;
                        method.Invoke(run, flags, Type.DefaultBinder,   null ,  null  );
                    }
                }
                  catch   (Exception ex)
                {
                    Log.log.Error(DateTime.Now  +  "   执行程序集时出错:   "  +  ex.Message);
                }
            }
        }
    } 

以上就是服务容器的核心代码,下面贴一个组件代码

  1       ///   <summary> 
  2       ///   监测ERP数据库的单据状态,并生成消息日志
   3       ///   </summary> 
  4       public   class   Monitor : IRun
   5       {
   6           public   void   Run()
   7           {
   8               new   DAL.Sys_ApplyFormNotifyLog().CreateNotify();
   9           }
  10      }

关于服务的安装运行卸载也写了批处理

安装:

 echo 清理原有服务项. . .
 %SystemRoot%\Microsoft.NET\Framework\v4. 0.30319 \installutil / U FCL.WinService.exe
echo 清理完毕,开始安装后台服务. . .
 %SystemRoot%\Microsoft.NET\Framework\v4. 0.30319  \installutil FCL.WinService.exe
echo 服务安装完毕
pause 

启动:

 echo 启动服务. . .
net start FCLService
pause 

停止:

 echo 停止服务. . .
net stop FCLService
pause 

到此结束,程序里有很多需要改进之处,使程序更加灵活、稳定、强壮,请大家多多指点。

 

 

 

标签:  windows服务 ,  反射

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于企业应用微型Windows服务架构的详细内容...

  阅读:40次