Создание одиночного элемента ChannelFactory <T> и многократное использование для соединений клиента

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

public class RemoteDataRetriever : IDataRetriever
{
    protected static readonly ChannelFactory
        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(binding);
    }

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

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

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

10
задан Community 23 May 2017 в 11:48
поделиться

2 ответа

Хорошо, ваша реализация синглтона в порядке. Это потокобезопасный, и ChannelFactory также потокобезопасный.

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

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

3
ответ дан 4 December 2019 в 04:21
поделиться

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

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

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

0
ответ дан 4 December 2019 в 04:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: