WebRequest 实现数据的即时抛转

  之前我们和另外一个系统进行数据交互的时候,采用的方式为:我们会把数据按照约定的格式存放在一个用于数据交互的数据表中,然后各自会有一个Job每隔几分钟到此Table中获取最新的数据(之所以采取此种交互方式,主要是两个系统分别在不同的网段,所以只能把数据先放在中间临时的大家都可以直接的DB中交互)。这种方式其实也可以很好的工作。但是会有一个问题:如果A系统的数据B系统马上要获取,由于job定时执行的缘故,此时不得不人工手动执行job,才能是数据立即抛转到B系统,也就是说在紧急情况下,此种做法还是会有一个时间延迟的问题存在。

  今天要说的是:采用Http WebRequest的方式,实现了一个所谓的Dispatch Service的基于Http的简单数据转发服务。使得A系统如果有数据更新,就即时的把数据抛给B系统,抛转的数据格式可以是File,也可以是String,Xml等等。

  基本架构说明:
  

WebRequest 实现数据的即时抛转_第1张图片  

 

  说明:
  1.从client端到Dispatch Server再到Target Client,都通过【msgid】串起来。如果Target 端想要Client端传递什么数据,只需协商一个MsgID,并在Dispatch Service端配置相关信息即可。

  2.server端有一个关键的xml配置档案,id即为msgid,同时配置此msgid的数据要server的哪个Handler执行,并把执行结果抛砖到哪个地址去!

  3.在server的xml配置档案中,也可以配置,client端传递的信息的处理方式:直接抛转;处理后再抛转;直接处理不做抛转。

  4.相关的数据抛转都采用WebRequest的方式进行,接收放利用HttpHandler方式进行处理;

  5.如果要在server端处理处理,可把执行处理的方法封装成Dll,而后在配置档案配置,待需要时动态呼叫执行。

 先看下Server端的config档案的定义:

代码
<? xml version="1.0" encoding="utf-8"  ?>
< DispatchServices >
  
< message  id ="TransferFTPFile"  type ="http"  filetype ="file"  onlysend ="Y" >
    
< source  from ="http://myserver/DispatchService/FileHandler.ashx"  to ="http://localhost/ReceiveDataHandler/FileHandler.ashx"   />
    
< dll  id =""  namespace =""  typename =""  methodname ="" />
    
< mailto > [email protected] </ mailto >
  
</ message >
  
< message  id ="TransferStringTest"  type ="http"  filetype ="str"  onlysend ="Y" >
    
< source  from ="http://myserver/DispatchService/StringHandler.ashx"  to ="http://localhost/ReceiveDataHandler/StringHandler.ashx"   />
    
< dll  id =""  namespace =""  typename =""  methodname ="" />
     
< mailto > [email protected] </ mailto >
  
</ message >
  
< message  id ="TransferXmlTest"  type ="http"  filetype ="xml"  onlysend ="Y" >
    
< source  from ="http://myserver/DispatchService/XMLHandler.ashx"  to ="http://localhost/ReceiveDataHandler/XmlHandler.ashx"   />
    
< dll  id =""  namespace =""  typename =""  methodname ="" />
    
< mailto > [email protected] </ mailto >
  
</ message >
  
< message  id ="TransferXmlTest"  type ="dll"  filetype ="xml"  onlysend ="N" >
    
< source  from ="http://myserver/DispatchService/XMLHandlerWithDll.ashx"  to ="http://localhost/ReceiveDataHandler/XmlHandler.ashx"   />
    
< dll  id =""  namespace =""  typename =""  methodname ="" />
    
< mailto > [email protected] </ mailto >
  
</ message >
</ DispatchServices >

数据发起方 Client端:

代码
private   void  Send( string  fileName,  string  msgid,  byte [] byteArray)
        {
            
string  uri  =   " http://myserver/DispatchService/ServerUriHandler.ashx " ;

            WebRequest request 
=  WebRequest.Create(uri);
            request.Method 
=   " POST " ;

            request.ContentType 
=   " application/x-www-form-urlencoded " ;
            request.Headers.Add(
" filename " , Convert.ToBase64String(Encoding.UTF8.GetBytes(fileName)));
            request.Headers.Add(
" msgid " , Convert.ToBase64String(Encoding.UTF8.GetBytes(msgid)));

            request.ContentLength 
=  byteArray.Length;

            Stream dataStream 
=  request.GetRequestStream();

            dataStream.Write(byteArray, 
0 , byteArray.Length);

            WebResponse response 
=  request.GetResponse();

            dataStream 
=  response.GetResponseStream();

            StreamReader reader 
=   new  StreamReader(dataStream);

            dataStream.Close();
            reader.Close();
            response.Close();
        }


 说明:Client发送msgid,Data[](不管是文件还是字串,全部转为byte[]),filename(如果是文件的话)给Server特定URI.

      Server端:

代码
namespace  DispatchService
{
    
///   <summary>
    
///  Summary description for $codebehindclassname$
    
///   </summary>
    [WebService(Namespace  =   " http://tempuri.org/ " )]
    [WebServiceBinding(ConformsTo 
=  WsiProfiles.BasicProfile1_1)]
    
public   class  FileHandler : IHttpHandler
    {
        
public   void  ProcessRequest(HttpContext context)
        {
            context.Response.ContentType 
=   " text/plain " ;

            Stream stream 
=  context.Request.InputStream;
            
if  (stream  ==   null   ||  stream.Length  <=   0 )
            {
                context.Response.Write(
" 没有获得有效的信息 " );
                
return ;
            }

            
string  fileName  =  Encoding.UTF8.GetString(Convert.FromBase64String(context.Request.Headers[ " filename " ]));
            
string  msgid  =  Encoding.UTF8.GetString(Convert.FromBase64String(context.Request.Headers[ " msgid " ]));

            
byte [] data  =   new   byte [stream.Length];
            stream.Read(data, 
0 , Convert.ToInt32(stream.Length));

            
string  guid  =  Guid.NewGuid().ToString();

            IFileHandler dal 
=   new  FileTransfer();

            
// 本地存储
             string  responseCode  =  dal.ExecuteReveive(data, guid, fileName, msgid);

            
// 返回执行结果
            context.Response.Write(responseCode);

            
// 异步转发 
             object [] obj  =   new   object [] { data, guid };
            Thread thread 
=   new  Thread( new  ParameterizedThreadStart(dal.ExecuteSend));
            thread.Start(obj);
        }

        
public   bool  IsReusable
        {
            
get
            {
                
return   false ;
            }
        }
    }
}

说明:server端拿到数据后首先在server备份,备份成功后开始转发。可以看到在server端有几个不同的handler,分别处理不同的数据类型:file,string ,xml.

代码
public    interface  IFileHandler
    {
        
///   <summary>
        
///  接收调用端传递过来的信息
        
///   </summary>
        
///   <param name="context"> 传递的信息 </param>
        
///   <param name="guid"> guid 要和ExecuteSend的guid一致 </param>
        
///   <returns></returns>
        string  ExecuteReveive( byte [] data,  string  guid,  string  fileName, string  msgid);
       
void  ExecuteSend( object  obj);
    }

 FileTransfer的处理:

代码
namespace  DispatchService.DispatchLib
{
    
public   class  FileTransfer : IFileHandler
    {
        
///   <summary>
        
///  接收调用端传递过来的信息
        
///   </summary>
        
///   <param name="context"> 传递的信息 </param>
        
///   <param name="guid"> guid 要和ExecuteSend的guid一致 </param>
        
///   <returns></returns>
         public   string  ExecuteReveive( byte [] data,  string  guid,  string  fileName,  string  msgid)
        {
            
string  filePath  =   string .Empty;
            
string  returnInfo  =   " OK " ;
            
// 本地存储
             try
            {
                
string  base64Str  =  Encoding.UTF8.GetString(data);
                
byte [] origin  =  Convert.FromBase64String(base64Str);

                
// 本地Log存储路径
                 string  path  =  System.Configuration.ConfigurationManager.AppSettings[ " filepath " ].ToString();
                filePath 
=  path  +  DateTime.Now.ToString( " yyyyMMddHHmmss " +   " _ "   +  Path.GetFileName(fileName);
                File.WriteAllBytes(filePath, origin);
            }
            
catch  (Exception ex)
            {
                Common.WriteLog(
" Source: "   +  ex.GetBaseException().Source  +   " --Message: "   +  ex.GetBaseException().Message  + "  Guid: " + guid);
                Common.SendMail(
" 本地存储失败--GUID: "   +  guid  +   " ErrorMsg: "   +  ex.Message,msgid);
                returnInfo 
=   " Error: "   +  ex.Message  +   " \r\n filepath "   +  filePath;
            }
            
try
            {
                
// 备份本地存储
                Common.WriteLogInfo(filePath, guid, FileType.file.ToString(), msgid);
            }
            
catch  (Exception ex)
            {
                Common.WriteLog(
" Source: "   +  ex.GetBaseException().Source  +   " --Message: "   +  ex.GetBaseException().Message + "  Guid: " + guid);
                Common.SendMail(
" 备份文件本地存储的路径失败--GUID: "   +  guid  +   " ErrorMsg: "   +  ex.Message,msgid);
                returnInfo 
=  ex.Message;
            }

            GC.Collect();

            
return  returnInfo;
        }

        
///   <summary>
        
///  执行转发
        
///   </summary>
        
///   <param name="obj"> 要转发的信息 </param>
         public   void  ExecuteSend( object  obj)
        {
            
object [] resultObj  =  obj  as   object [];
            
byte [] byteArray  =  resultObj[ 0 as   byte [];
            
string  guid  =  resultObj[ 1 as   string ;
            
string  msgid = string .Empty;
            
try
            {
                Entity.BasicInfo info 
=  Common.GetExecuteType(guid);
                msgid 
=  info.MsdID;
                
string  type  =  info.Type;
                
string  fullName  =  ConfigurationManager.AppSettings[ " Dll " +   " \\ "   +  info.DllName;
                
if  (type  ==   " http " )
                {
                    
if  (info.OnlySend  !=   " Y " )
                    {
                        
// dll 处理后,得到要转发的byteArray
                        object  objInfo =  Common.ExecuteDllMethod(fullName, info.TypeName, info.MethodName,  new   string [] { });              
                    }
                    
string  uri  =  info.UriTo;
                    
string  fileName  =  info.FileName;
                    Common.BeginRequest(uri, byteArray, fileName, msgid);
                }
                
else   if  (type  ==   " dll "   &&  info.UriTo == "" )
                {
                    
// 动态呼叫Dll中的方法,对数据进行本地处理,不做转发动作
                    Common.ExecuteDllMethod(fullName, info.TypeName, info.MethodName,  new   string [] { });
                }
                
// 更改flag 
                Common.UpdateFlagForSend(guid);
            }
            
catch  (Exception ex)
            {
                Common.SendMail(
" 文件转发失败--GUID:\t "   +  guid  +   " ErrorMsg: "   +  ex.Message,msgid);
                Common.WriteLog(
" Source: "   +  ex.GetBaseException().Source  +   " \t "   +   " Message: "   +  ex.GetBaseException().Message + "  Guid: " + guid);
            }
            GC.Collect();
        }
    }
}

   在Server端的备份信息这里依然采取的Xml方式进行:文件记录文件路径,字串直接写入xml.每笔记录用Guid进行标记。在要查看抛转的log信息时,可读取这些档案,如果需要在Server端对数据重新抛转,就可以利用这些Guid查找唯一。
  Log_Info.xml

<? xml version="1.0" encoding="utf-8"  ?>
< log_info >
  
< message  guid ="wqsdjfsf0909sfsfs998"  filetype ="file"  msgid =""  hassend ="Y" >
    
< data > D:\ </ data >
  
</ message >
</ log_info >
 

  这样,架起来的Service,只要经过简单的配置就可以实现从Client端到Target端的数据即时抛转。

你可能感兴趣的:(request)