10

W naszym środowisku SharePoint/ASP.NET mamy szereg klas pobierania danych, które wszystkie pochodzą ze wspólnego interfejsu. Zostałem przydzielony do zadania stworzenia programu do pobierania danych, który mógłby zdalnie komunikować się z innymi farmami SharePoint za pomocą WCF. Sposób, w jaki mam to zaimplementowane w tej chwili, to singleton ChannelFactory<T> jest tworzony w statycznym konstruktorze, a następnie ponownie wykorzystywany przez każdą instancję zdalnego pobierania danych w celu utworzenia indywidualnej instancji proxy. Pomyślałem, że to zadziała dobrze, ponieważ wtedy ChannelFactory zostanie tylko raz utworzone w domenie aplikacji, a jego utworzenie to guaranteed to be thread-safe. Mój kod wygląda mniej więcej tak:Tworzenie singleton ChannelFactory <T> i ponowne używanie dla połączeń klienta

public class RemoteDataRetriever : IDataRetriever 
{ 
    protected static readonly ChannelFactory<IRemoteDataProvider> 
     RequestChannelFactory; 

    protected IRemoteDataProvider _channel; 

    static RemoteDataRetriever() 
    { 
     WSHttpBinding binding = new WSHttpBinding(
      SecurityMode.TransportWithMessageCredential, true); 

     binding.Security.Transport.ClientCredentialType = 
      HttpClientCredentialType.None; 

     binding.Security.Message.ClientCredentialType = 
      MessageCredentialType.Windows; 

     RequestChannelFactory = 
      new ChannelFactory<IRemoteDataProvider>(binding); 
    } 

    public RemoteDataRetriever(string endpointAddress) 
    { 
     _channel = RemoteDataRetriever.RequestChannelFactory. 
      CreateChannel(new EndpointAddress(endpointAddress)); 
    } 
} 

Moje pytanie brzmi: czy to dobry projekt? Pomyślałem, że po utworzeniu ChannelFactory nie muszę się martwić o bezpieczeństwo wątków, ponieważ używam go tylko do wywoływania CreateChannel(), ale czy się mylę? Czy zmienia się stan, czy w inny sposób wykonuje coś za kulisami, które może powodować problemy z wątkami? Dodatkowo, czy muszę umieścić gdzieś kod (static finalizer?), Który ręcznie unieszkodliwia ChannelFactory, czy mogę założyć, że ilekroć IIS zostanie ponownie uruchomiony, wykona dla mnie wszystkie prace porządkowe?

pokrewne: ChannelFactory Reuse Strategies

Odpowiedz

3

Od "to jest ten singleton design good", twoja implementacja z Singleton jest w porządku. Jest bezpieczny dla wątków i ChannelFactory<T> jest również bezpieczny dla wątków.

Nie musisz też martwić się oczyszczaniem zasobów. Zakładając, że ChannelFactory<T> podąża za Microsoft's guidelines for implementing IDisposable, nie będziesz mieć problemu z jakimś wyciekiem. Gdy domena aplikacji zostanie zerwana, zostanie utworzona kolekcja śmieci, a w tym momencie wszystko zostanie wyczyszczone. Finalizator pod numerem ChannelFactory<T> wykona porządek, który normalnie wykonasz w wywołaniu Dispose.

Jednak z punktu widzenia "powinienem buforować widok ChannelFactory<T>", trudno powiedzieć, ponieważ nie wskazuje się wersji .NET, w której się znajdujesz. Jednak wskazany artykuł wskazuje, że jeśli używasz dodatku .NET 3.0 SP1 lub nowszego, naprawdę nie musisz tego robić, możesz utworzyć swoje serwery proxy (zakładając, że pochodzą one z ClientBase<T>), gdzie jest to potrzebne w kodzie klienta , a nie przez taki wzór fabryczny.

+0

Znalazłem artykuł o das blonde, który wydaje się wskazywać to samo - http://www.dasblonde.net/PermaLink.aspx?guid=c7922cb4-26d4-408b-b029-cfadd75ff954. Jednak słowa "generowane dla ciebie" odstraszają mnie na całą ClientBase . Mimo wszystko, myślę, że jesteś na dobrej drodze. –

+0

Podczas badania innego problemu z funkcją WCF odkryłem dobry powód, by faworyzować ChannelFactory nad ClientBase - http://stackoverflow.com/questions/2252747/what-is-system-servicemodel-diagnostics-callbackexception-and-why-cant -i-handle –

+0

@Repo Man: Jeśli wolisz, ale ponowne pakowanie wyjątków nie jest najlepszą praktyką, chyba że masz ku temu dobry powód. W przypadku błędów tego typu w WCF, nie uważam, że kwalifikuje się do ponownego pakowania wyjątków. – casperOne

0

Dopóki „singleton” jest po prostu powrocie nowo wybudowane kanały, nie musisz się martwić o bezpieczeństwo wątków. Zawsze możesz rzucić niestabilne słowo kluczowe na deklarację statyczną, jeśli lubisz, aby zapobiec optymalizacji kompilacji, które mogłyby cię podkopać, ale nie sądzę, że jest to konieczne w tym przypadku.

Po prostu spróbuj zadać sobie pytanie na temat długoterminowej elastyczności. Na przykład, co jeśli później zdecydujesz się dodać jakiś stan do tej metody CreateChannel? Być może mogłoby to stworzyć coś w stylu do 10 kanałów, a następnie zacząć je ponownie używać. Czy możesz łatwo zmodyfikować swój singleton, aby to zrobić?

Twoja odpowiedź brzmi prawdopodobnie tak, ale co, jeśli następnie skalujesz pionowo do wielu serwerów? Singleton może nie wystarczyć. Potrzebny byłby sposób udostępniania stanu między instancjami/serwerami (np. Baza danych, rozproszona pamięć podręczna); to może być trudne w statycznym kontekście, w zależności od tego, jak zdecydowałeś się udostępnić stan.

0

I this article, Daniel Vaughan zaleca buforowanie kanałów w obiekcie zarządzającym Singleton, ale nigdy buforowanie ChannelFactory. Do tej pory stosowaliśmy to podejście bez żadnych problemów ...

The korzyści z takich działań są:

„Gdy kanał wchodzi do zarzucić stan jest usuwany z pamięci podręcznej i odtworzone gdy jest następny wniosek ...”

  • Bezpieczeństwo negocjacja jest tylko wykonywane raz.
  • Unika konieczności bezpośredniego zamknięcia kanału przy każdym użyciu.
  • Możemy dodać dodatkową funkcjonalność inicjalizacji.
  • Możemy wcześnie przestać działać, jeśli serwer proxy nie może się połączyć z serwerem.
+1

Wiem, że jest stary .. ale czy to nie skutecznie również cache ChannelFactory? Od zwolnienia Fabryki zamyka kanały. – Tracker1