Как удостовериться, что asmx веб-сервис только называют однажды за один раз?

У меня есть asmx веб-сервис, которому нужно только позволить ответить 1 клиенту сразу.

В otherwords, если бы сервис становится названным клиентом A и сервером B вызовы, я хотел бы, чтобы B ожидал, пока A не закончен затем B, может быть обслужен.

Если это слишком сложно затем в вызовах абсолютного минимума от B, должен перестать работать с определяемой пользователем ошибкой в течение времени A, начинает сервис.

Причина состоит в том, что сервис полагается в большой степени на операции IO и сериализацию XML, таким образом, крайне важно, чтобы сервис не становился названным одновременно больше чем 1 клиентом.

Заранее спасибо

5
задан JL. 7 March 2010 в 18:52
поделиться

4 ответа

static object _LockObject = new object();

void WebServiceCall()
{
    lock(_LockObject)
    {
        // Do work...
    }
}

Создайте статический объект, для которого вы вызываете lock () . Оператор lock () не позволит другим вызовам выполнить код внутри, пока не завершится первое выполнение, получившее блокировку.

Обратите внимание, что в зависимости от ваших настроек тайм-аута B может завершиться ошибкой с тайм-аутом в зависимости от того, сколько времени потребуется для завершения A.

Обновление: Да, вы можете использовать класс Monitor вместо lock () . Вы можете использовать метод Monitor.TryEnter () , чтобы проверить, заблокирован ли объект уже или нет (например, если вы хотите вернуть ошибку вместо ожидания).

Дополнительные сведения:

Из http://msdn.microsoft.com/en-us/library/aa664735 (VS.71) .aspx :

Оператор блокировки формы

lock (x) ...

, где x - выражение ссылочного типа, в точности эквивалентно

System.Threading.Monitor.Enter(x);
try {
   ...
}
finally {
   System.Threading.Monitor.Exit(x);
}

From http://msdn.microsoft.com/en-us/library/de0542zz.aspx :

Используйте Enter, чтобы получить Monitor для объекта, переданного в качестве параметра. Если другой поток выполнил Enter для объекта, но еще не выполнил соответствующий Exit, текущий поток будет заблокирован до тех пор, пока другой поток не освободит объект.

Таким образом, код знает, что нужно блокировать, а не пропускать, просто намеренно. Вы можете пропустить, если хотите, используя метод Monitor.TryEnter ().

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

Я понимаю требование обрабатывать только один запрос за раз, но я не думаю, что разрешить только один запрос за раз - это решение.

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

Альтернативой является обслуживание каждого запроса по мере его поступления и помещение его в очередь для последующей обработки. Эта очередь может обрабатываться по одной задаче за раз (или в зависимости от загруженности вашего сервера).

Первоначальные заказчики могут быть уведомлены несколькими способами. Одним из способов может быть опрос о том, завершен ли исходный запрос или он все еще находится в очереди на обработку, возможно, с использованием сгенерированного маркера (например, GUID).

2
ответ дан 14 December 2019 в 04:35
поделиться

Я не знаю, почему вы хотите это сделать, но в любом случае это может быть допустимым сценарием. Попробуйте посмотреть, как диспетчер пакетов Linux APT получает блокировку:

Чтобы предотвратить появление нескольких экземпляров диспетчера пакетов, для того, чтобы диспетчер пакетов работал, ему необходимо заблокировать файл блокировки и записать в него PID.

Точно так же вы можете создать файл в корне виртуального хоста. Когда клиент подключен, заблокируйте этот файл, т. Е. Напишите что-нибудь в нем. Когда он закончится, сделайте файл пустым. Прежде чем пытаться заблокировать его, попробуйте посмотреть, есть ли что-нибудь внутри. Если да, то верните клиенту сообщение об ошибке.

0
ответ дан 14 December 2019 в 04:35
поделиться

Я не знаю, как это реализовано в .net, но я предполагаю, что вы хотите реализовать объект блокировки, который «принадлежит» запросу, когда он обслуживается и не может быть направлен более чем на один запрос за раз. В Java я мог бы синхронизировать какой-то глобальный объект.

Однако будьте осторожны, наблюдайте за обычными проблемами параллелизма ... скажем, для наивной реализации, один запрос проверяет блокировку и находит ее доступной, затем засыпает, а второй запрос проверяет блокировку и берет ее, затем первый запрос просыпается, думая, что блокировка свободна и случаются плохие вещи ). Также убедитесь, что вы обрабатываете случай, когда при обработке запроса происходит сбой, при котором блокировка остается на месте.

Поскольку шаблон использования создания несовместимой веб-системы воспринимается (конечно, в мире сервлетов Java) как плохая практика, я бы посоветовал вам вернуть ошибку в случае, если служба уже находится в используйте, а не блокируйте, поскольку может быть сложно оценить влияние блокировки.

2
ответ дан 14 December 2019 в 04:35
поделиться
Другие вопросы по тегам:

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