2012-10-01 6 views
1

실버 라이트 애플리케이션에서 사용하고있는 자체 호스팅 WCF 서비스가 있습니다. IDictionary 개체에 사용자 guid 목록을 저장하려고합니다. 사용자가 서비스에 접근 할 때마다 사용자의 datetime을 업데이트하므로 어떤 사용자가 활성 "세션"을 갖고 있는지 추적 할 수 있습니다. 문제는 내가 서비스를 때릴 때마다 목록이 비어 있다는 것입니다. 각 비누 요청에 값을 드롭하는 것으로 보입니까?자체 호스팅 wcf 서비스에 상태가 있습니까?

여러 서비스 요청에서 사용할 수있는 자체 호스팅 서비스에 정보를 저장할 수 있습니까?

미리 감사드립니다.

+1

사용자 목록과 같은 영구 정보가 영구 저장소 (예 : 데이터베이스)에 속합니다. –

+0

자체 호스팅 (콘솔 앱, Windows 서비스 등)은 어떻게됩니까? –

답변

1

InstanceContextMode을 변경해야합니다. 당신은 당신의 WCF 클래스에 다음 컴파일러 지시문을 추가하면됩니다 :

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] 

이 종류의 싱글로 WCF 서비스를 실행합니다. WCF Instance Context Mode

그리고 나서 싱글 톤 개체로 서비스 호스트를 구성해야합니다.

다른 사람들이 당신이 어떻게 작동하는지 또는 경우에 익숙하지 않다면이 "결과"를 초래할 수 정중이 언급 한 것처럼
  private ServiceHost serviceHost; 

      if (serviceHost != null) 
       serviceHost.Close(); 

      if (log.IsInfoEnabled) 
       log.Info("Starting WCF service host for endpoint: " + ConfiguredWCFEndpoint); 

      // Create our service instance, and add create a new service host from it 
      ServiceLayer.TagWCFService service = new ServiceLayer.TagWCFService(ApplicationName, 
       ApplicationDescription, 
       SiteId, 
       ConfiguredUpdateRateMilliseconds); 

      serviceHost = new ServiceHost(service, new Uri(ConfiguredWCFEndpoint)); 

      // Open the ServiceHostBase to create listeners and start listening for messages. 
      serviceHost.Open(); 

그것은 아니에요 : 여기 비슷한 일을하고있어 작업 예제 코드는 특정 용도에 알 맞습니다.

+2

이것은 ** ** ** ** 모발 모금 ** 결과를 가지고 있습니다 - 모든 요청을 순차적으로 성공적으로 연계했는지 (예 : 실적이 ** 큰 시간 빠지게 될 것임) WCF 서비스 클래스의 코드는 완전히 ** re-entrant **이며 thread-safe입니다 ** - 고급 프로그래머조차도 달성하기 쉬운 쉬운 작업이 아닙니다! 가능하다면 싱글 톤을 피하십시오! –

+0

나는 그 속성을 추가하려고 시도했으나 요청 사이의 사전 내에서 데이터를 유지하지 못했습니다. 추가해야 할 사항이 있습니까? – spyter

+0

ServiceHost 개체를 만들면 사용자가 만든 Singleton 개체 (사용자가 만든 WCF 클래스 개체)에 개체를 전달합니다. 나는 이것을 보여줄 답을 편집했다. – landoncz

2

인스턴스별로 제공됩니다. 즉, 기본적으로 세션 없음입니다. 서비스 계약이 System.ServiceModel.SessionMode.Required에 System.ServiceModel.ServiceContractAttribute.SessionMode 속성을 설정하면

this

에서 살펴보고, 그 계약은 말하고 그 모든 통화 (즉, 은 호출을 지원하는 기본 메시지 교환)은 동일한 대화의 일부 여야합니다.

2

요청 사이에 물건을 저장해야하는 경우 이러한 요청이 들어올 때 해당 요청을 저장하기 위해 적절한 잠금 기능이있는 정적 사전을 만들거나이 정보를 데이터베이스 (또는 다른 외부 저장소)에 저장하고 각 메소드 호출에 존재하는지 확인하십시오. 그 이유는 모든 클라이언트 요청에서 서비스 클래스가 인스턴스화되기 때문입니다.

사용자가 서비스에 접근 할 때 이미 사용자 datetime을 업데이트하고 있으므로이 사용자가 datetime 필드와 비교하여 활성 사용자인지 여부를 확인하는 것이 좋습니다. 이것은 모든 호출에 대해 정확하다는 장점이 있습니다 (사전이 서비스가 다시 시작되면 사전과 db가 동기화되지 않을 수 있습니다). 데이터베이스에는 동시성을 처리 할 수있는 메커니즘이 이미 있으므로 싱글 톤 객체에 대한 자체 잠금 솔루션을 롤링하는 대신 데이터 저장소에 복잡성을 가할 수 있습니다.

두 번째 솔루션이 빠르지 않다면 (그리고 앱을 프로파일 링하여 병목 현상이라고 판단한 경우), 다른 옵션은 데이터를 먼저 확인할 수 있도록 db 앞에서 일종의 캐시 솔루션을 사용하는 것입니다 DB에 가기 전에 메모리에 저장하십시오. 이 캐시 객체는 사전과 같이 정적 일 필요가 있으며 다른 멀티 스레드 응용 프로그램과 마찬가지로 잠그는 것과 관련된 함정이 있습니다.

EDIT :이 호스팅 된 WCF 서비스가 Silverlight 응용 프로그램의 사용자를위한 세션 저장소로 사용되고 데이터가 외부 데이터 저장소에 저장되지 않는 경우 해당 데이터가 활성 상태인지 추적하는 것이 미션 크리티컬. 이 데이터는 설명 된대로 정확하다고 보장 할 수 없습니다.

서비스에 결함이 있고 재부팅해야하는 경우 (자체 호스트이므로 오류가 발생한 이벤트를 모니터링하는 것이 좋습니다) 서비스 호스트를 처리하고 새 인스턴스를 인스턴스화해야합니다. Guid 데이터를 보관할 수있는 유일한 방법은 재시작 사이에 서비스로 리바운드되는 경우입니다 (호스트 응용 프로그램 자체가 다시 시작되지 않은 경우 다른 문제 임). 더 나은

private Dictionary<Guid,string> _session; 

Service service = new Service(_session); 
_serviceHost = new ServiceHost(service, GetUriMethodInHostApp()); 

는 외부에이를 저장하고 @marc_s에서 알 수 있듯이 조회를 수행하는 것입니다. 그런 다음이 복잡성은 사라집니다.

+0

사전을 정적으로 만들려고했지만 각 요청에 대해 여전히 데이터가 손실됩니다. 서비스에서 [ServiceBehavior (InstanceContextMode = InstanceContextMode.Single)]를 지정 했음에도 불구하고. – spyter

1

당신이 잠금 및 스레드 안전 특정 코드 무엇을 포함하지 않는 경우, 당신은 @marc_s처럼 MongoDB 또는 RavenDB

처럼 세션 데이터, 뭔가를 저장되는 NoSQL 데이터베이스를 사용할 수 있습니다, 나는를 사용하여 생각 싱글 톤 모드는 위험한 일이며, 스레드 안전 세션 메커니즘을 만드는데 신중해야합니다.

관련 문제