Создание одиночного ChannelFactory <T>и повторное использование для клиентских подключений - PullRequest
10 голосов
/ 11 февраля 2010

В нашей среде SharePoint / ASP.NET у нас есть ряд классов для извлечения данных, которые все происходят из общего интерфейса. Мне было поручено создать средство извлечения данных, которое могло бы удаленно взаимодействовать с другими фермами SharePoint с помощью WCF. В настоящий момент он реализован таким образом, что в статическом конструкторе создается синглтон ChannelFactory<T>, который затем используется каждым экземпляром удаленного средства извлечения данных для создания отдельного экземпляра прокси. Я подумал, что это будет хорошо работать, потому что тогда экземпляр ChannelFactory создается только один раз в домене приложения, и его создание гарантированно поточно-ориентированное . Мой код выглядит примерно так:

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));
    }
}

У меня вопрос, это хороший дизайн? Я понял, что после создания ChannelFactory мне не нужно беспокоиться о безопасности потоков, потому что я просто использую его для вызова CreateChannel(), но я ошибаюсь? Меняет ли это состояние или делает что-то необычное за кулисами, что может вызвать проблемы с многопоточностью? Кроме того, мне нужно поместить куда-нибудь код (статический финализатор?), Который вручную удаляет ChannelFactory, или я могу предположить, что всякий раз, когда IIS перезагружается, он выполняет всю работу по очистке для меня?

Похожие: Стратегии повторного использования ChannelFactory

Ответы [ 3 ]

3 голосов
/ 15 февраля 2010

С точки зрения «хорошо ли это синглтон-дизайн», ваша реализация синглтона в порядке. Он потокобезопасен, а ChannelFactory<T> также потокобезопасен.

Вам также не нужно беспокоиться об очистке ресурса. Если предположить, что ChannelFactory<T> соответствует рекомендациям Microsoft по реализации IDisposable , то у вас не возникнет проблем с утечкой данных. Когда домен приложения будет разрушен, будет создана сборка мусора, и все будет очищено в этот момент. Финализатор на ChannelFactory<T> выполнит очистку, которую обычно делают при вызове Dispose.

Однако с точки зрения «должен ли я кэшировать ChannelFactory<T>» трудно сказать, потому что вы не указываете, в какой версии .NET вы находитесь. Однако в статье, на которую вы указываете, указано, что если вы используете .NET 3.0 с пакетом обновления 1 (SP1) или более поздней версии, вам действительно не нужно этого делать, вы можете создавать свои прокси-серверы (предполагая, что они получены из ClientBase<T>), где вам это нужно в код клиента, а не через фабричный шаблон, подобный этому.

0 голосов
/ 01 октября 2010

I эта статья , Дэниел Воган поддерживает кэширование каналов в объекте менеджера Singleton, но никогда не кэширует ChannelFactory. Мы использовали этот подход без проблем до сих пор ...

Преимущества этого:

"Когда канал переходит в состояние сбоя, он удаляется из кэша и воссоздается при следующем запросе ..."

  • Согласование безопасности выполняется только один раз.
  • Предотвращает необходимость явного закрытия канала при каждом использовании.
  • Мы можем добавить дополнительные функции инициализации.
  • Мы можем потерпеть неудачу рано, если прокси не может связаться с сервером.
0 голосов
/ 15 февраля 2010

Пока ваш "синглтон" просто возвращает вновь созданные каналы, вам не нужно беспокоиться о безопасности потоков. Вы всегда можете добавить ключевое слово volatile в статическое объявление, если хотите, чтобы предотвратить любые оптимизации компилятора, которые могут подорвать вас, но я не думаю, что в этом случае это необходимо.

Просто попробуйте задать себе вопросы о долгосрочной гибкости. Например, что если позже вы решили добавить какое-то состояние в этот метод CreateChannel? Возможно, он будет делать что-то вроде создания до 10 каналов, а затем начнет их повторно использовать. Не могли бы вы легко изменить свой синглтон, чтобы сделать это?

Ваш ответ, вероятно, да, но что если вы затем масштабируете вертикально на несколько серверов? Синглтона может быть недостаточно. Вам понадобится какой-нибудь способ поделиться состоянием между экземплярами / серверами (например, база данных, распределенный кеш); это может быть трудно сделать в статическом контексте, в зависимости от того, как вы решили поделиться состоянием.

...