WebRequest 实现数据的即时抛转

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

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

  基本架构说明:
  

  

 

  说明:
  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>jiaxin606@163.com</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>jiaxin606@163.com</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>jiaxin606@163.com</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>jiaxin606@163.com</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[0as byte[];
            
string guid = resultObj[1as 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端的数据即时抛转。

posted on 2009-12-15 22:58  easy2Dev  阅读(498)  评论(0编辑  收藏  举报

导航