다음을 통해 공유


송신 어댑터의 교환 패턴

BizTalk 메시징 엔진에서 송신 어댑터로 배달된 메시지는 네트워크를 통해 전송됩니다. 이러한 메시지는 단방향 또는 양방향 메시지 교환 패턴을 사용하여 송신될 수 있습니다. 이러한 양방향 메시지 교환 패턴을 처리하는 어댑터를 간청-응답 어댑터라고 합니다.

차단 전송 및 비차단 전송

메시징 엔진은 어댑터가 일괄 처리 인식인지 여부에 따라 IBTTransmitter.TransmitMessage 메서드 또는 IBTTransmitterBatch.TransmitMessage 메서드를 사용하여 송신 어댑터에 메시지를 전달합니다. 이 두 가지 버전의 메서드에는 어댑터가 메시지를 전송한 방법을 나타내는 부울 반환 값이 있습니다. 어댑터가 를 반환 true하는 경우 반환하기 전에 메시지를 완전히 보냈습니다. 이 경우 메시징 엔진은 어댑터를 대신하여 MessageBox 데이터베이스에서 메시지를 삭제합니다. 어댑터가 를 반환 false하면 메시지 전송을 시작하고 전송이 완료되기 전에 반환됩니다. 이 경우 어댑터는 해당 응용 프로그램 큐에서 메시지를 삭제할 뿐만 아니라 메시지 전송 재시도 또는 일시 중단이 필요한 전송 실패를 처리합니다.

어댑터 반환 false 은 비블로킹 호출입니다. 즉, TransmitMessage 구현 코드가 메시징 엔진의 호출 스레드를 차단하지 않습니다. 어댑터는 전송 준비가 된 메모리 내 큐에 메시지를 추가한 다음 이 값을 반환합니다. 어댑터는 메모리 내 큐를 지원하고 메시지를 전송한 다음 엔진에게 전송 결과를 알려 주는 고유한 스레드 풀을 포함해야 합니다.

메시징 엔진의 스레드는 일반적으로 네트워크를 통한 데이터 송신에 사용되는 스레드보다 CPU 제약을 많이 받습니다. 이러한 두 가지 유형의 스레드를 함께 사용하면 성능이 저하됩니다. 비차단 송신은 이러한 두 가지 유형의 스레드를 분리하며 차단 호출보다 뛰어난 성능을 보입니다.

다음 다이어그램은 I/O 작업의 제약을 받을 수 있는 어댑터 스레드 풀을 보여 줍니다. BizTalk Server 메시징 엔진의 스레드 풀이 CPU 처리의 제약을 더 많이 받습니다. 두 개의 서로 다른 스레드 풀을 유지하면서 동일한 유형의 스레드를 혼합하지 않으면 시스템이 보다 효율적으로 작동할 수 있습니다.

I/O 작업으로 바인딩되는 경향이 있는 어댑터의 스레드 풀을 보여 주는 다이어그램

성능 팁: 최상의 성능을 위해 송신 어댑터는 차단 해제 및 일괄 처리 인식이어야 합니다. BizTalk FILE 어댑터를 차단/비일괄 처리 인식에서 비차단/일괄 처리 인식으로 변경하면 성능이 세 배 향상됩니다.

문제 해결 팁: 전송을 차단하면 전체 호스트 instance 성능이 저하될 수 있습니다. 어댑터가 TransmitMessage 에서 과도한 차단을 수행하는 경우 엔진 스레드가 다른 어댑터에 메시지를 배달하지 못하게 합니다.

일괄 처리되지 않은 송신

일괄 처리를 인식하지 않는 어댑터는 비동기 송신 어댑터의 인터페이스에 설명된 대로 IBTTransmitter를 구현해야 합니다. 어댑터가 메시징 엔진을 전송해야 하는 각 메시지에 대해 IBTTransmitter.TransmitMessage를 호출합니다. 아래의 개체 상호 작용 다이어그램은 다음 단계로 구성된 메시지 전송에 대한 일반적인 접근 방법을 자세히 보여 줍니다.

  1. 엔진이 메시지를 어댑터에 배달합니다.

  2. 어댑터가 전송 준비가 된 메모리 내 큐에 메시지를 저장합니다.

  3. 어댑터 스레드 풀의 스레드가 큐에서 메시지를 해제하고 메시지 구성을 읽고 네트워크를 통해 메시지를 전송합니다.

  4. 어댑터가 엔진에서 새 일괄 처리를 받습니다.

  5. 어댑터는 일괄 처리에서 DeleteMessage 를 호출하여 방금 전송한 메시지를 전달합니다.

  6. 어댑터는 일괄 처리에서 Done 을 호출합니다.

  7. 엔진이 일괄 처리를 처리하고 응용 프로그램 큐에서 메시지를 삭제합니다.

  8. 엔진은 어댑터를 다시 호출하여 DeleteMessage 작업의 결과를 알립니다.

    애플리케이션 큐에서 단일 메시지를 삭제하는 어댑터를 보여 주는 이미지입니다.

    위의 개체 상호 작용 다이어그램은 응용 프로그램 큐에서 단일 메시지를 삭제하는 어댑터를 보여 줍니다. 어댑터가 한 번에 하나의 메시지에 대한 작업을 수행하는 것보다 메시지 작업을 일괄 처리하는 것이 이상적입니다.

일괄 처리된 송신

일괄 처리 인식 어댑터는 송신 어댑터에 대한 인터페이스에 설명된 대로 IBTBatchTransmitter 및 IBTTransmitterBatch를 구현해야 합니다. 엔진에 전송할 어댑터에 대한 메시지가 있는 경우 엔진은 IBTBatchTransmitter.GetBatch를 호출하여 어댑터에서 새 일괄 처리를 가져옵니다. 어댑터는 IBTTransmitterBatch를 구현하는 새 일괄 처리 개체를 반환합니다. 그런 다음, 엔진은 IBTTransmitterBatch.BeginBatch를 호출하여 일괄 처리를 시작합니다. 이 API에는 out 매개 변수가 있습니다. 이 매개 변수를 사용하면 어댑터가 일괄 처리에서 수락할 최대 메시지 수를 지정할 수 있습니다. 상황에 따라 어댑터가 DTC 트랜잭션을 반환할 수 있습니다. 그런 다음, 엔진은 IBTTransmitterBatch.TransmitMessage 를 한 번 호출하여 보내는 각 메시지를 일괄 처리에 추가합니다. 이 호출 횟수는 0보다 크지만 어댑터에서 표시되는 일괄 처리의 최대 크기보다 작거나 같습니다. 모든 메시지가 일괄 처리에 추가되면 어댑터는 IBTTransmitterBatch.Done을 호출합니다. 이 시점에서 어댑터는 일반적으로 일괄 처리에 있는 모든 메시지를 해당 메모리 내 큐에 배치합니다. 어댑터는 비일괄 처리 인식 어댑터의 경우처럼 고유 스레드 풀에 있는 스레드의 메시지를 전송합니다. 그러면 어댑터가 엔진에게 트랜잭션 결과를 알려줍니다.

다음의 개체 상호 작용 다이어그램은 일괄 처리 송신 어댑터에 의한 두 메시지의 전송을 보여 줍니다.

일괄 처리된 송신 어댑터에 의한 두 메시지 전송을 보여 주는 다이어그램.

전송 실패 처리

전송 실패 시 권장되는 지침이 아래 그림에서 설명되어 있습니다. 이는 권장 사항일 뿐이며 메시징 엔진에서 강제 실행되지는 않습니다. 타당한 이유가 있는 경우 이러한 지침과 다른 어댑터를 개발할 수 있지만 이 경우에는 주의해야 합니다. 예를 들어 일반적으로 어댑터는 항상 모든 재시도가 사용된 후에 메시지를 백업 전송으로 이동해야 합니다.

보다 일반적으로 전송은 구성된 것보다 더 많은 재시도를 사용해야 할 수 있습니다. 이는 다소 다르기는 하나 전송 계층의 복원력이 증가하고 있으므로 허용 가능하다고 간주됩니다. 일반적으로 메시징 엔진에 의해 노출되는 API는 어댑터에게 가능한 한 최대의 제어권을 제공하도록 디자인되었습니다. 이러한 제어권을 가지면 책임이 더 커집니다.

전송 오류를 처리하는 프로세스를 보여 주는 다이어그램

어댑터는 시스템 컨텍스트 속성 RetryCount를 확인하여 메시지에서 사용할 수 있는 재시도 횟수를 결정합니다. 어댑터는 재시도할 때마다 다시 제출 API를 한 번 호출하고 메시지를 다시 제출할 메시지를 전달합니다. 메시지와 함께 어댑터는 엔진이 메시지를 어댑터로 다시 배달해야 할 시점을 나타내는 타임스탬프를 전달합니다. 이 값은 일반적으로 현재 시간과 RetryInterval 값이어야 합니다. RetryInterval 은 단위가 분인 시스템 컨텍스트 속성입니다. 메시지 컨텍스트의 RetryCountRetryInterval 은 모두 송신 포트에 구성된 값입니다. 동일한 BizTalk 호스트의 인스턴스가 여러 컴퓨터에 배포된 확장 배포의 경우를 생각해 보십시오. 재시도 간격이 만료된 후에 메시지가 배달되는 경우 메시지는 실행되도록 구성된 아무 컴퓨터의 호스트 인스턴스에나 배달될 수 있습니다. 이러한 이유로 어댑터가 재시도에 사용될 메시지와 연결된 상태를 보관하지 말아야 합니다. 왜냐하면 어댑터의 동일 인스턴스가 나중에 전송을 수행할지 보장할 수 없기 때문입니다.

어댑터는 재시도 횟수가 0보다 작거나 같을 경우에만 백업 전송으로 메시지를 이동하려고 해야 합니다. 포트에 대해 구성된 백업 전송이 없는 경우 메시지를 백업 전송으로 이동하려는 시도가 실패합니다. 이 경우 메시지는 일시 중단되어야 합니다.

다음 코드 조각은 메시지 컨텍스트에서 재시도 횟수 및 간격을 결정하는 방법과 이후에 백업 전송으로 재전송하거나 이동하는 방법을 보여 줍니다.

using Microsoft.XLANGs.BaseTypes;  
using Microsoft.BizTalk.Message.Interop;  
using Microsoft.BizTalk.TransportProxy.Interop;  
 …  
// RetryCount and RetyInterval are system context properties...  
private static readonly PropertyBase RetryCountProperty =   
 new BTS.RetryCount();  
private static readonly PropertyBase RetryIntervalProperty =   
 new BTS.RetryInterval();  

public void HandleRetry(IBaseMessage msg, IBTTransportBatch batch)  
{  
int retryCount = 0;  
int retryInterval = 0;  

// Get the RetryCount and RetryInterval off the msg ctx...  
 GetMessageRetryState(msg, out retryCount, out retryInterval);  

// If we have retries available resubmit, else move to   
 // backup transport...  
 if ( retryCount > 0 )  
batch.Resubmit(  
 msg, DateTime.Now.AddMinutes(retryInterval));  
else  
batch.MoveToNextTransport(msg);  
}  

public void GetMessageRetryState(  
 IBaseMessage msg,   
 out int retryCount,   
 out int retryInterval )  
{  
retryCount = 0;  
retryInterval = 0;  

object obj =  msg.Context.Read(  
RetryCountProperty.Name.Name,    
RetryCountProperty.Name.Namespace);   

if ( null != obj )  
retryCount = (int)obj;  

obj =  msg.Context.Read(  
RetryIntervalProperty.Name.Name,    
RetryIntervalProperty.Name.Namespace);   

if ( null != obj )  
retryInterval = (int)obj;  
}  

TransmitMessage에서 예외 throw

어댑터가 API IBTTransmitter.TransmitMessage, IBTTransmitterBatch.TransmitMessage, IBTTransmitterBatch.Done에서 예외를 throw하는 경우 엔진은 관련 메시지의 전송을 전송 오류로 처리하고 어댑터 오류를 처리하는 방법에 자세히 설명된 대로 메시지에 대한 적절한 작업을 수행합니다.

일괄 처리 인식 송신 어댑터의 경우 TransmitMessage API에 대한 예외를 throw하면 전체 일괄 처리가 삭제되며 해당 일괄 처리의 모든 메시지에 대해 기본 전송 실패 작업이 수행됩니다.

간청-응답

일반적으로 양방향 송신 어댑터는 단방향 전송과 양방향 전송을 모두 지원합니다. 송신 어댑터는 메시지 컨텍스트에서 IsSolicitResponse 시스템 컨텍스트 속성을 검사하여 메시지를 단방향 또는 양방향 전송으로 전송해야 하는지 여부를 결정합니다.

다음 코드 조각에서 이를 보여 줍니다.

private bool portIsTwoWay = false;  
private static readonly PropertyBase IsSolicitResponseProperty= new BTS.IsSolicitResponse();  

...  

 // Port is one way or two way...  
 object obj =  this.message.Context.Read(  
 IsSolicitResponseProperty.Name.Name,    
 IsSolicitResponseProperty.Name.Namespace);   

if ( null != obj )  
 this.portIsTwoWay = (bool)obj;  

간청-응답 전송 중에 어댑터는 간청 메시지를 전송합니다. 이를 완료한 후에 어댑터는 관련된 응답을 전송하고 메시징 엔진에게 MessageBox 데이터베이스에서 원본 간청 메시지를 삭제할 것을 지시합니다. 응용 프로그램 큐에서 메시지를 삭제하는 작업은 응답 메시지의 전송과 동일한 전송 프록시 일괄 처리에서 수행되어야 합니다. 이렇게 하면 응답에 대한 삭제 및 전송의 원자성이 보장됩니다. 완전한 원자성을 위해 어댑터는 DTC 트랜잭션을 사용하여 트랜잭션 인식 리소스로의 간청 메시지 전송, 응답 메시지 전송, 간청 메시지 삭제 등이 모두 동일한 DTC 트랜잭션 컨텍스트에 있도록 해야 합니다. 이 경우에도 비차단 송신을 사용하여 간청 메시지가 전송되는 것이 좋습니다.

다음 코드 조각은 양방향 송신의 주요 측면에 대해 설명합니다. 엔진이 IBTTransmitter.TransmitMessage 를 호출하면 어댑터는 메모리 내 큐에 전송될 메시지를 큐에 추가합니다. 어댑터가 반환 false 되어 비블로킹 송신을 수행하고 있음을 나타냅니다. 어댑터의 스레드 풀(WorkerThreadThunk)은 메모리 내 큐를 처리하고 메시지를 큐에서 제거하여 도우미 메서드에 전달합니다. 이 메서드는 간청 메시지를 보내고 응답 메시지를 받습니다. 이 도우미 메서드의 구현은 이 항목에서 다루지 않습니다. 응답 메시지는 엔진으로 전송되고 간청 메시지는 응용 프로그램 큐에서 삭제됩니다.

using System.Collections;  
using Microsoft.XLANGs.BaseTypes;  
using Microsoft.BizTalk.Message.Interop;  
using Microsoft.BizTalk.TransportProxy.Interop;  

     static private Queue _transmitQueue = new Queue();  
  static private IBTTransportProxy _transportProxy = null;   
// IBTTransmitter...  
 public bool TransmitMessage(IBaseMessage msg)  
{  
// Add message to the transmit queue...  
lock(_transmitQueue.SyncRoot)  
 {  
_transmitQueue.Enqueue(msg);  
 }  

 return false;  
}  

 // Threadpool worker thread...   
private void WorkerThreadThunk()  
{  
try  
{  
 IBaseMessage solicitMsg = null;  

 lock(_transmitQueue.SyncRoot)  
 {  
 solicitMsg =   
 (IBaseMessage)_transmitQueue.Dequeue();  
}  

 IBaseMessage responseMsg = SendSolicitResponse(   
 solicitMsg );  
Callback cb = new Callback();  

IBTTransportBatch batch = _transportProxy.GetBatch(  
 cb, null);  
batch.SubmitResponseMessage( solicitMsg, responseMsg );  
batch.DeleteMessage( solicitMsg );  
batch.Done(null);  
}  
catch(Exception)  
{  
// Handle failure....  
}  
}  

static private IBaseMessage SendSolicitResponse(  
 IBaseMessage solicitMsg )  
{  
// Helper method to send solicit message and receive   
 // response message...  
IBaseMessage responseMsg = null;  
return responseMsg;  
}  

동적 송신

동적 송신 포트에는 연결된 어댑터 구성이 없습니다. 대신 동적 송신 포트는 어댑터가 동적 포트에서 메시지를 전송하는 데 필요로 하는 모든 기본 속성에 대해 핸들러 구성을 사용합니다. 예를 들면 HTTP 어댑터는 프록시를 사용하고 자격 증명을 제공해야 할 수 있습니다. 사용자 이름, 암호 및 포트는 런타임에 어댑터가 캐시하는 핸들러 구성에서 지정될 수 있습니다.

엔진이 동적 메시지를 전송할 전송을 확인하려면 아웃바운드TransportLocation 에 어댑터의 별칭이 접두사로 지정됩니다. 어댑터는 설치 시 BizTalk Server 하나 이상의 별칭을 등록할 수 있습니다. 엔진은 런타임에 OutboundTransportLocation을 구문 분석하여 일치 항목을 찾습니다. 어댑터는 앞에 별칭을 추가하거나 사용하지 않고 OutboundTransportLocation 을 처리해야 합니다. 다음 표는 즉시 사용 가능한 BizTalk 어댑터에 대해 등록된 별칭의 일부 예를 보여 줍니다.

어댑터 별칭 어댑터 OutboundTransportLocation 예
HTTP:// HTTP http://www. MyCompany.com/bar
HTTPS:// HTTP https://www. MyCompany.com/bar
mailto: SMTP mailto:A.User@MyCompany.com
FILE:// FILE FILE://C:\ MyCompany \%MessageID%.xml