企业应用微型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://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于企业应用微型Windows服务架构的详细内容...