2009-09-11 7 views
1

필자가 작성한 작은 WCF 호스팅 엔진을 사용하면 .config 파일을 기반으로 ServiceHosts를 동적으로 만들 수 있습니다. 일반적인 아이디어는 모든 서비스를 오프라인 상태로 만들 필요없이 런타임에 기존 서비스를 제거하고 새로운 서비스를 추가 할 수있게하는 것입니다.ServiceHost의 주소가 충돌 할 때 주소가 일치합니다.

나는 그것이 소리가 나는 것처럼 쉽지 않을 수 있음을 나타내는 문제 단위 테스트를 실시했습니다. 특정 엔드 포인트에 대해 하나의 ServiceHost 만 존재할 수있는 것처럼 보입니다 (단일 ServiceHost에 서비스에 대한 여러 개의 다른 엔드 포인트가있을 수 있음). 이는 정상적인 문제는 아니지만 서비스를 재구성해야 할 경우 원본 ServiceHost를 종료해도 해당 끝점 주소에 대한 등록이 실제로 중단되지는 않습니다. (같은 엔드 포인트가 사용됨을 의미) 같은 서비스, 다른 ServiceHost를 만들려고하면 다음과 같은 예외와 함께 실패합니다

System.InvalidOperationException: The ChannelDispatcher at 'net.pipe://localhost/' with contract(s) '"ITestService"' is unable to open its IChannelListener. ---> 
System.InvalidOperationException: A registration already exists for URI 'net.pipe://localhost/'. 

는 사실은 단위 테스트 중에 오류가 발생하고있다. 이 테스트는 ServiceHosts와 호스팅 엔진을 최대한 인간적으로 가능한 한 많이 종료하는 하나의 유닛을 사용합니다. 그런 다음 다른 테스트를 위해 동일한 ServiceHost를 다시 만들려고하는 호스팅 엔진의 다른 인스턴스를 만듭니다. 두 번째 테스트는 위의 오류가 발생했습니다. 나는 ServiceHost.Close()가 호출 될 때 서비스 호스트를 실제로 파괴하지 않는다고 추측하고있다 ... 그래서 여전히 메모리에 매달리고있다. GC가 이전 서비스 호스트를 정리하고 있는지 여부를 알 수 없습니다. 문제는 처음에 발생한 후 사라지지 않고 계속 유지됩니다 (최선을 다해 결정할 수 있었던 것처럼 ... 지금까지 약 30 분을 기다렸습니다.)

다음과 같이는 system.serviceModel에 대한 나의 구성 파일은 다음과 같습니다

<system.serviceModel> 
    <services> 
     <service name="Campus.Core.ServiceModel.TestServiceStub"> 
     <endpoint   
      address="net.pipe://localhost"   
      binding="netNamedPipeBinding"   
      contract="Campus.Core.ServiceModel.ITestService" 
     /> 
     </service> 
    </services> 
    </system.serviceModel> 
+0

동일한 문제가 발생합니다. 이후로 문제를 해결할 수 있었습니까? – Elan

+0

1 년 전에이 문제가 발생했습니다. 더 이상 코드가 없지만 코드를 통해 프로그래밍 방식으로 서비스를 호스팅 할 수있는 방법을 발견하여 단위 테스트를 실행할 때 포트를 변경할 수있었습니다. 나는 당신을 어떤 식 으로든 돕기를 바랍니다. –

답변

3

다른 사람이이 문제에 부딪혔을 때를 대비하여이 질문에 대한 답을 제공하십시오. 이 문제의 원인은 다음과 같이 두 가지로 밝혀졌습니다.

1) 단원 테스트 중에 예외가 발생하면 ServiceHost를 닫기 전에 일반적으로 테스트중인 코드가 중단됩니다. 이로 인해 ServiceHost는 특정 끝점에 바인딩됩니다. 이로 인해 동일한 코드가 실행되는 모든 후속 테스트가 실패하게되었습니다. SubSpec과 xUnit을 사용하여 BDD를 수행 할 때 단일 테스트 케이스 (BDD 측면에서 우려)는 테스트 당 단일 어설 션을 수행했으며 단일 테스트 케이스는 최대 12 개 이상의 어설 션을 포함 할 수있었습니다.

2) MEX 종점에주의하십시오. MEX 엔드 포인트는 서비스 당 한 번만 존재할 수 있습니다. 처음에는 http 및 net.tcp mex 끝점을 만들었습니다. 그러나 두 번째로 시작된 MEX 엔드 포인트의 인스턴스가 예외를 던질 때 문제가 발생했습니다. 일반적으로 MEX 엔드 포인트를 사용하는 경우 물리적 인 인프라 문제가없는 한 HTTP가 가장 유용한 프로토콜입니다.

일반적으로 ServiceHost에 대해 Close() 메서드를 호출하면 이전에 끝점에 바인딩 된 모든 주소를 다시 사용할 수 있으므로 해당 바인딩을 완전히 바인딩 해제 할 수 있습니다. 때로는 클로저가 시간이 걸릴 수 있으며 드물 긴하지만 예외가 발생할 수 있습니다. SubSpec을 사용하여 BDD를 수행하고 테스트 당 단일 어설 션 규칙에 따라 ServiceHosts 클로저를 방지하는 한 테스트에서 throw 된 예외로 인해 모든 후속 테스트가 실패합니다.

1

한 대답은 서비스 호스트의 URL에 하나 개를 위로 회전 할 때마다 GUID를 추가하고, 공장 방법을 사용하는 것입니다 둘 다 ServiceHost 인스턴스를 회전시키고 클라이언트 측 채널을 반환하므로 클라이언트가 사용할 URL을 알 수 있습니다.

IDesign의의 InProcFactory 샘플이 방법을 사용하기 때문에있는 그대로 당신이 그것을 사용할 수 있습니다 : 당신이 순서 IDesign의 사이트에 등록해야합니다

http://www.idesign.net/idesign/DesktopDefault.aspx?tabindex=5&tabid=11

참고 샘플을 다운로드, 그리고 그들은 당신에게 훈련과 그런 것에 관한 가끔 발표를 보낼 것입니다. 그러나 너무 많이는 아닙니다.

+0

URL은 명시 적으로 정의되어 있으므로 자동 생성 될 수 없습니다. 우리는 우리 URL을 버전 관리 전략의 일부로 사용합니다. 우리의 서비스는 .NET뿐 아니라 여러 플랫폼에서 사용되기 때문에 항상 클라이언트를 제어 할 수있는 것은 아닙니다. :( – jrista