Будет ли мой WCF-сервис масштабироваться с использованием синглтона? - PullRequest
0 голосов
/ 26 сентября 2011

Мое веб-приложение ASP .Net C # позволяет пользователям отправлять файлы из своей учетной записи на моем сервере на любой удаленный сервер с использованием FTP. Я реализовал сервис WCF, чтобы сделать это. Служба создает экземпляр класса для каждого пользователя, который порождает рабочий поток, который выполняет операции FTP на сервере. Клиент отправляет команду службе, служба находит рабочий поток, назначенный клиенту, и запускает команды FTP. Затем клиент каждые две секунды опрашивает службу, чтобы получить статус операции FTP. Когда клиент отправляет команду «отключить», класс и рабочий поток, выполняющие операции FTP, уничтожаются.

Рабочий поток FTP должен сохраняться между запросами клиента, поскольку обработка FTP может занять много времени. Итак, мне нужен был способ, чтобы клиент всегда получал один и тот же экземпляр класса FTP между вызовами службы. Я реализовал этот сервис как синглтон, таким образом:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class UserFtpService : IUserFtpService
{
    private SortedDictionary<string, UserFTPConnection> _clients = new SortedDictionary<string, UserFTPConnection>();

    ...
}

Где "UserFTPConnection" - это класс, содержащий рабочий поток, а имя учетной записи пользователя используется для индексации в словаре.

У меня такой вопрос: в книгах, которые я читал о WCF, экземпляр синглтона называется «врагом масштабируемости». И я понимаю, почему это так. Есть ли лучший способ убедиться, что клиент получает один и тот же экземпляр UserFTPConnection между запросами к службе WCF, кроме использования синглтона?

Ответы [ 2 ]

2 голосов
/ 26 сентября 2011

На самом деле, здесь ваша первая проблема заключается в синхронизации доступа к этому статическому объекту.Dictionary<TKey, TValue> не является потокобезопасным, поэтому вы должны убедиться, что к нему одновременно обращается только один поток.Таким образом, вы должны обернуть каждый доступ к этому словарю в lock, при условии, конечно, что у вас есть методы, которые пишут, и другие, которые читают.Если вы только собираетесь читать, вам не нужно синхронизироваться.Поскольку синглтон является врагом масштабируемости, это действительно преувеличенное утверждение и довольно бессмысленное без определенного сценария.Это действительно будет зависеть от точного сценария и реализации.В вашем примере вы только показали словарь =>, поэтому все, что мы можем сказать, это то, что вам нужно убедиться, что ни один поток не читает из этого словаря, в то время как другой пишет, и что ни один поток не пишет в этот словарь, в то время как другой поток читает.

Например, в .NET 4.0 вы можете использовать класс ConcurrentDictionary<TKey, TValue>, который является потокобезопасным в подобных ситуациях.

Одно можно сказать наверняка: в то время как синглтоншаблон может или не может быть врагом масштабируемости в зависимости от конкретной реализации, шаблон синглтона является главным врагом тестируемости юнитов в изоляции.

1 голос
/ 27 сентября 2011

Если вы собираетесь использовать синглтон, я бы рекомендовал также установить ConcurrencyMode в ConcurrencyMode.Multiple. Например ...

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class UserFtpService : IUserFtpService
{
}

Если вы этого не сделаете, ваш WCF-сервис будет одноэлементным, но разрешит доступ только одному потоку за раз, что, безусловно, повлияет на производительность. Конечно, вам нужно будет обеспечить безопасность потоков коллекций (как в ранее упомянутом ответе).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...