实战解析--项目的主要技术储备

1--通讯技术

    在上篇了展望了本项目的一个框架,我们也知道:如果这个项目的处理时间不能达到要求的话,则花哨的功能也不能逃过失败的定论。
    而通讯的关键在于数据处理枢纽的层数和处理中转的时间,数据枢纽下联数据采集器、上联高层数据枢纽或者监控台。数据的最长路经是:局房数据采集器-->县局数据枢纽-->市局数据枢纽-->省局数据枢纽-->监控台。则总共经历四次传送,则每次中转和处理的时间应该<2/4=500ms。
    目前.Net提供比较安全的远程处理机制和Web Service,我编写一个测试程序,发现在我配置比较高的机器上一次传送100条记录的数据包的处理时间平均在400ms,看来就比较危险了。
    以前我们的数据采集器连接的有智能设备;A/D单片机等,而上层的数据处理部分有跑在UNIX,所以稳妥地方式还是使用原生的socket保险些,但是这里就只能忽略了安全保证(考虑是在电信内网运行),当然传送时可以简单加密一下数据。
    下面是我定义的接口:
 1using System;
 2
 3namespace QPG.Net
 4{
 5    public delegate void StateChangedCallback(string text);
 6    public delegate void DataReceivedCallback(string text,int curSocketIndex);
 7
 8    public interface IMonitorChannel{
 9        event StateChangedCallback OnConnected;
10        event DataReceivedCallback OnReceived;
11        event StateChangedCallback OnDisconnect;
12
13        void open();
14        void close();
15
16        bool Opened {get;}
17    }

18
19    public interface IClientChannel:IMonitorChannel{
20        
21        void sendMsg(string msg);
22        
23    }

24
25    public interface IServerChannel:IClientChannel {
26        int Port{get;}
27    
28        void sendMsgToAll(string msg);
29        void sendMsgToClient(string msg, int clientNumber);
30    }

31
32}

IMonitorChannel---提供给观看者,只能收取数据,不能发送命令;
IClientChannel---主要用于监控台;
IServerChannel---主要用于数据枢纽,可以用来接收采集器的数据或者发布数据到数据订阅者

实现就很简单了,网上很多开源的Socket C#版。我就不贴了,有需要的可以邮件给我。

2--扩展技术
既然castle提供了那么强大的容器,那我就直接使用它得了。下图是传统的功能调用和基于数据队列处理的思路图,后者我已经在好几个大型项目中使用,比较容易维护和调试。



以下是所有规则处理器的祖先类:
namespace OpenMonitor.Services {
    
using System;
    
using System.Collections;

    
    
using OpenMonitor.Data;
    
using OpenMonitor.Utility;
    
using OpenMonitor;

    
using Castle.Model;
    
    
public class BaseService:IStartable {
    
    
        
protected string _serviceName="monitor.base_service";
        
protected    SiteConfigPacket _cfg;
            
        
protected IMessageQueue _mq;
        
private bool _Started = false;
        
private System.Timers.Timer _timer;
        
protected bool _Stopped=false;

        
private const int TIMER_INTRVAL=50;
        
        
        
public BaseService(string ServiceName,IMessageQueue mq,SiteConfigPacket cfg) {
            _serviceName
=ServiceName;
            _mq
=mq;
            _cfg
=cfg;
            _timer
=new System.Timers.Timer(TIMER_INTRVAL);
            
            _timer.Elapsed
+=new System.Timers.ElapsedEventHandler(timer_Elapsed);
    
        }

        
        
public virtual string ServiceName {
            
get{return _serviceName;}
        }

        
public virtual void Start() {
            
if(_Started==truereturn;
            DefaultLogger.INSTANCE.DEBUG(ServiceName
+" Started");
            _timer.Enabled
=true;
            _Started
=true;
        }


        
        
public  virtual void Stop() {
            _Stopped 
=  true;
            _timer.Enabled
=false;
            DefaultLogger.INSTANCE.DEBUG(ServiceName
+" Stoped");
        }

        
protected void ToNextRule(InfoData data,InfoConfig infocfg) {
            
string next=infocfg.getNextRule(_serviceName).Name;
            
if(next=="") next=ResultService.ServiceName;
            
this.addDataToQueue(next,data);
            
        }

        
public virtual void handle(object data) {
        }


        
protected void addDataToQueue(string sn,object data) {
            _mq.addDataToQueue(sn,data);
        }

        
protected void checkQueue() {
            
object obj=_mq.getDataFromQueue(_serviceName) ;
            
if(obj==nullreturn ;
            
try{
                handle(obj);
            }

            
catch(Exception e) {
                DefaultLogger.INSTANCE.ERROR(
this._serviceName+"("+obj.ToString()+")",e);
            }

            checkQueue();
        }

        
        
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
            checkQueue();
        }

        
    }

}

这里使用了castle的自动服务启动功能,所以容器创建后,内部的所有服务都会自动启动,并且每隔50ms对它负责的队列进行一次集中的扫荡处理。如果是多个处理器实例,那么处理的效果更佳。那也很简单,在配置文件里类似如下配置:
  <component id="linearity"
               type="OpenMonitor.Services.LinearityFormula,ExtendRule"
               lifestyle="Pooled" initialPoolSize="2" maxPoolSize="5" >           
  </component>

但是实际上多个和一个处理效果没有区别,第二个总会扑空的,你看出来了吗?且听我下回分解吧。

alex 11-24
 
posted @ 2005-11-24 18:03  成为-行动-拥有(BeDoHave)  阅读(2225)  评论(2编辑  收藏  举报