2014-04-15 2 views
0

다른 도메인/호스트에 대해 6 개의 고유 URL을 받고, 반환 한 XML을 구문 분석하고 테이블에 삽입합니다. 각 서버를 동 기적으로 (한 번에 하나씩) 수행하는 것을 제외하면이 작업은 정상적으로 수행되었습니다. 동시에 6 대의 모든 서버에 연결할 필요가 있습니다.SSIS 스크립트 변환 - WebClient 비동기 작업 수행

Async 메서드를 사용하도록 WebClient 호출을 변경 한 다음 모든 WebClient 호출이 반환되었는지 확인하기 위해 while 문을 추가했지만 SetEndOfRowSet에 대한 호출이 있는지 여부에 관계없이 SSIS 패키지는 while 문 완료 후에 취소 된 것처럼 보입니다. 아닙니다. 모든 로그 옵션을 선택해도 SSIS 로깅에는 오류가 표시되지 않습니다. 출력 창에서 '취소됨'이라고 표시되며, 발생했을 때 팝업되는 간단한 콘솔 창이 있지만 나는 그것을 잡을 수 없습니다.

SSIS 패키지에 while 문이 없으면 패키지는 내 스크립트 변환 이후 계속되고 아무런 행도 출력되지 않습니다. 스크립트 변환은 SynchronousInputID에서 None으로 설정됩니다.

다음은 SSIS C# 스크립트 변환 코드입니다 :

/* Microsoft SQL Server Integration Services Script Component 
* Write scripts using Microsoft Visual C# 2008. 
* ScriptMain is the entry point class of the script.*/ 

using System; 
using System.Data; 
using Microsoft.SqlServer.Dts.Pipeline.Wrapper; 
using Microsoft.SqlServer.Dts.Runtime.Wrapper; 
using System.Net; 
using System.Diagnostics; 
using System.Xml; 

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute] 
public class ScriptMain : UserComponent 

{ 
    private int CountComplete = 0; 

public override void PreExecute() 
{ 
    base.PreExecute(); 
} 

public override void PostExecute() 
{ 
    base.PostExecute(); 
} 

public override void Input0_ProcessInput(Input0Buffer Buffer) 
{ 
    while(Buffer.NextRow()) 
    { 
     Input0_ProcessInputRow(Buffer); 
    } 

    if (Buffer.EndOfRowset()) 
    { 
     while (CountComplete < Variables.intRows) 
     { 
      System.Threading.Thread.Sleep(500); 
     } 
     Output0Buffer.SetEndOfRowset(); 
    } 
} 

public override void Input0_ProcessInputRow(Input0Buffer Row) 
{ 
    string DNS_NA = Row.DNSNA; 
    long SERVER = Convert.ToInt64(Row.SERSYSNR); 

    // Ignore server/certificate mismatch... 
    ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true; 

    // Declare variable that will hold the xml document received by the API 
    string xmlDoc = String.Empty; 

    // Get the URI from the variable 
    string url = @"https://" + DNS_NA + Variables.strURLSuffix; 

    // Time the request... 
    Stopwatch timer = Stopwatch.StartNew(); 
    //Create a Web Client 
    WebClient client = new WebClient(); 
    client.DownloadStringCompleted += (sender, e) => 
    { 
     timer.Stop(); 
     processRow(e.Result, SERVER, Convert.ToInt32(timer.ElapsedMilliseconds), Convert.ToInt32(Row.UPTIMQY), Output0Buffer); 
     CountComplete += 1; 
    }; 
    Uri uri = new Uri(url); 
    client.DownloadStringAsync(uri); 
} 

private void processRow(string xmlDoc, long SERVER, int FRAPI_TIME, int PRE_UPTIME, Output0Buffer buffer) 
{ 
    try 
    { 
     XmlDocument xDoc = new XmlDocument(); 

     xDoc.LoadXml(xmlDoc); 

     bool NORESPONSE = false; // If we made it this far, we got a response, right? 
     short CPU = Convert.ToInt16(xDoc.SelectSingleNode("//server").ChildNodes[1].InnerText); 
     int TOT_MEM = Convert.ToInt32(xDoc.SelectSingleNode("//server").ChildNodes[2].InnerText)/(1024 * 1024); 
     int USE_MEM = Convert.ToInt32(xDoc.SelectSingleNode("//server").ChildNodes[3].InnerText)/(1024 * 1024); 
     int UPTIME = Convert.ToInt32(xDoc.SelectSingleNode("//server").ChildNodes[4].InnerText)/1000/60; 
     short REQUESTS = Convert.ToInt16(xDoc.SelectSingleNode("//server").ChildNodes[5].InnerText); 
     bool RESET = (UPTIME < PRE_UPTIME) ? true : false; 


     foreach (XmlNode xNode in xDoc.SelectNodes("//server/detail/request")) 
     { 
      buffer.AddRow(); 
      buffer.SERSYSNR = SERVER; 
      buffer.CPUUSEQY = CPU; 
      buffer.TOTMEMQY = TOT_MEM; 
      buffer.USEMEMQY = USE_MEM; 
      buffer.UPTIMQY = UPTIME; 
      buffer.REQCNTQY = REQUESTS; 
      buffer.REQMSQY = FRAPI_TIME; 
      buffer.SERNONRSPIR = NORESPONSE; 
      buffer.SERRSTIR = RESET; 
      buffer.REQSYSNR = Convert.ToInt32(xNode.ChildNodes[0].InnerText); 
      buffer.REQIPTE = xNode.ChildNodes[1].InnerText; 
      buffer.REQURLTE = xNode.ChildNodes[2].InnerText; 
      buffer.REQRUNTMQY = Convert.ToInt32(xNode.ChildNodes[3].InnerText); 

     } 
    } 
    catch 
    { 
     // Hopefully we didn't throw an exception inside the foreach where a row has already been added... 
     buffer.AddRow(); 
     buffer.SERSYSNR = SERVER; 
     buffer.SERNONRSPIR = true; 
    } 

} 

    // public override void CreateNewOutputRows() 
    // { 
     /* 
      Add rows by calling the AddRow method on the member variable named "<Output Name>Buffer". 
      For example, call MyOutputBuffer.AddRow() if your output was named "MyOutput". 
     */ 
    //} 

} 

내가 다음 UNION ALL 그들을 DNS_NA에 조건부 분할을 사용하여 스크립트 구성 요소의 X 번호를 만들 수 있지만, 각 시간은 새로운 서버가 추가됩니다 목록에서 SSIS 패키지를 편집해야합니다. 이상적이지 않습니다.

답변

0

관련 연결 버그 리포트 : 스크립트 작업의 https://connect.microsoft.com/SQLServer/feedback/details/367692/ssis-detects-end-of-data-flow-components-in-the-wrong-way

분할 (6)에 수 일을 유일한 해결책이었다. 스레드 설정으로 전환하고 DownloadString을 호출하여 DownloadStringSync를 사용할 때 SSIS 충돌을 수정했습니다. 나는 약간을 위해 저를 곤란하게 한 결과를 가공 할 때 나가 Output0Buffer를 잠글 ㄴ다는 것을 확인해야했다. ProcessInputBuffer에서 Buffer.EndOfRowSet()을 확인한 후 Thread.Join()을 호출하여 스레드를 저장하고 루핑하는 목록을 사용하여 끝냈습니다.

그러나 모든 솔루션이 완료 될 때까지는 솔루션이 계속 전달하지 못합니다. 이는 하나의 서버가 장시간 실행 된 경우 모든 결과가 반환 될 때까지 결과가 데이터베이스에 저장되지 않았 음을 의미합니다.

관련 문제