Возникла следующая проблема с сабжем: вызовы Validate выполняются последовательно независимо от параллельных вызовов со стороны многих клиентов. Т.е. подключилось скажем 1000 клиентов и каждый последовательно проходит валидацию. Это ооочень сильно бьет по производительности в случае параллельных вызовов методов службы от многих клиентов.
Это такой баг или чем-то обусловлено? Как победить? Как вообще можно хостить службу ожидающую высокой нагрузки?
У службы настроен ConcurrencyMode.
Я в p.s. исходного сообщения указал ссылку, где подробно описаны мытарства, там было проделано вообще все, что только можно. Стивен Чен из MSFT сначала откликнулся на вопрос, а потом позорно слился.
Здравствуйте, perekrestov, Вы писали:
P>но тогда вам прийдется добавить логику синхронизации в классе сервиса.
А что если поставить InstanceContextMode в Single...
Конечно, для уменьшения кол-ва проверок креденшиалзов можно использовать сессию, но там уже, определенно, не basicHttpBinding
Это существенно позволит вам снизить кол-во обращений вашего кастомного валидатора в базу
[ServiceContract(SessionMode = SessionMode.Required)] //Required будет давать вам "отлуп" в виде экзепшена, если будете использовать несоотв. биндинг (например, basicHttpBinding)public interface IMyContract
{
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, /*опционально, если вам нужно*/ ConcurrencyMode=ConcurrencyMode.Multiple)]
public class MyContract:IMyContract
{
}
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, perekrestov, Вы писали:
Да, и код валидатора в студию. Авось, вы там локами балуетесь
Re[4]: WCF: UserNamePasswordValidator concurrency
От:
Аноним
Дата:
21.04.11 12:57
Оценка:
Здравствуйте, perekrestov, Вы писали:
P>Да, и код валидатора в студию. Авось, вы там локами балуетесь
код валидатора
Thread.Sleep(1000);
никаких локов нигде вообще не в теле службы ни в коде валидатора. более того как только выключаю валидатор вызовы сразу становятся параллельными
Re[3]: WCF: UserNamePasswordValidator concurrency
От:
Аноним
Дата:
21.04.11 13:02
Оценка:
Здравствуйте, perekrestov, Вы писали:
P>А что если поставить InstanceContextMode в Single... P>Конечно, для уменьшения кол-ва проверок креденшиалзов можно использовать сессию, но там уже, определенно, не basicHttpBinding P>Это существенно позволит вам снизить кол-во обращений вашего кастомного валидатора в базу
это тоже было проделано — см. ссылку.
P>
P>[ServiceContract(SessionMode = SessionMode.Required)] //Required будет давать вам "отлуп" в виде экзепшена, если будете использовать несоотв. биндинг (например, basicHttpBinding)
P>public interface IMyContract
P>{
P>}
и это нам не поможет. речь идет о высоконагруженном сервере со многими клиентами - грубо сотни запросов в секунду, не с одного клиента, а с разных.
P>[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession, /*опционально, если вам нужно*/ ConcurrencyMode=ConcurrencyMode.Multiple)]
P>public class MyContract:IMyContract
P>{
P>}
P>
ну можно вообще обойтись без сессии в таком случае — использовать WSBinding — он устанавливает логическую сессию и производит аутентификацию единожды. но проблемы это не решает когда пользователи работают по схеме: подключился, вызвал метод-два, отключился.
Re: WCF: UserNamePasswordValidator concurrency
От:
Аноним
Дата:
21.04.11 13:23
Оценка:
Здравствуйте, Аноним, Вы писали:
честно говоря я не ожидал подобного — это просто хэдшот любому highload серверу на wcf. неужели никто не разрабатывает ничего серьезного (высоконагруженного) на wcf раз не наткнулся на такой нехилый bottlneck'и?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, perekrestov, Вы писали:
P>>Да, и код валидатора в студию. Авось, вы там локами балуетесь
А>код валидатора
А>
А>Thread.Sleep(1000);
А>
А>никаких локов нигде вообще не в теле службы ни в коде валидатора. более того как только выключаю валидатор вызовы сразу становятся параллельными
Log4Net appender, который вы используете не тормозит, параллельно "лоча" потоки?
Да, и стрейсить сервис не мешало бы. Было бы понятно, что там происходит.
+ Антонелло интересно высказался по поводу физических параметров сервера (кол-во ядер и т.п.).
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Аноним, Вы писали:
А>честно говоря я не ожидал подобного — это просто хэдшот любому highload серверу на wcf. неужели никто не разрабатывает ничего серьезного (высоконагруженного) на wcf раз не наткнулся на такой нехилый bottlneck'и?
Балансировка с WCF работает, но там есть серьезные ограничения на биндинги и бихейворы
Re[6]: WCF: UserNamePasswordValidator concurrency
От:
Аноним
Дата:
21.04.11 13:53
Оценка:
Здравствуйте, perekrestov, Вы писали:
P>Да, и стрейсить сервис не мешало бы. Было бы понятно, что там происходит.
делаю простой тест, создаю 30 каналов с разными credentials (итого разные фабрики каналов) и вызываю асинхронно метод. метод — пустой. настройки оптимальные (Concurrency) и т.д. Получаю следующую картину ответов: отправлено 30 запросов и через
30(!) секунд начинают приходить ответы с интервалом паузы в указанной Validate!
P>+ Антонелло интересно высказался по поводу физических параметров сервера (кол-во ядер и т.п.).
Антоннело высказал извиняюсь полный бред тупо набивая посты. Ему разжевали, что вызовы Validate выполняются последовательно в то время как методы службы параллельно, но считает уместным сумничать на тему занятых ядер...
Re[3]: WCF: UserNamePasswordValidator concurrency
От:
Аноним
Дата:
21.04.11 13:59
Оценка:
Здравствуйте, perekrestov, Вы писали:
P>Балансировка с WCF работает, но там есть серьезные ограничения на биндинги и бихейворы
балансировка ? throttling? да, работает, но распространяется только методы служб. а на PasswordValidator's сие как оказалось не рапространяется. итого полезность wcf я для себя на сегодня вижу только в решении следующем: подключилось дофига клиентов, прошли по очереди(!) аутентификацию и наконец-то заработали параллельно ну это очевидный баг, почему мелкософт так позорно слился в той теме мало того, что не пофиксив, так еще и не отписавшись. сразу скажу: автор той темы — не я, я наткнулся на сей баг вчера. гугля нашел только одну такую тему с подобной проблемой.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, perekrestov, Вы писали:
P>>Да, и стрейсить сервис не мешало бы. Было бы понятно, что там происходит. А>делаю простой тест, создаю 30 каналов с разными credentials (итого разные фабрики каналов) и вызываю асинхронно метод. метод — пустой. настройки оптимальные (Concurrency) и т.д. Получаю следующую картину ответов: отправлено 30 запросов и через А>30(!) секунд начинают приходить ответы с интервалом паузы в указанной Validate!
P>>+ Антонелло интересно высказался по поводу физических параметров сервера (кол-во ядер и т.п.). А>Антоннело высказал извиняюсь полный бред тупо набивая посты. Ему разжевали, что вызовы Validate выполняются последовательно в то время как методы службы параллельно, но считает уместным сумничать на тему занятых ядер...
Хм, да точно. Невнимательно прочитал. Сорри.
Остается только повторить тоже самое у себя на машине. А, все-таки, трейс не помешал бы.
Вероятно очередь запросов строится одним потоком и там же происходит аутентификация.
А WCF рантайм, в зависомости от настроек сервиса (InstanceContextMode, SessionMode, Concurency, Binding и прочего) выгребает реквесты с этой очереди.
Но это только догадки, нужно в литературу посмотреть, и, конечно, рефлектором.
Re[8]: WCF: UserNamePasswordValidator concurrency
От:
Аноним
Дата:
21.04.11 14:38
Оценка:
Здравствуйте, perekrestov, Вы писали:
Вобщем перебирая варианты обнаружил, что таки Validate выполняется параллельно — порциями по ~10. Откуда эта цифра и как на нее влиять пока не понял.
А>Вобщем перебирая варианты обнаружил, что таки Validate выполняется параллельно — порциями по ~10. Откуда эта цифра и как на нее влиять пока не понял.
А куда Вам больше?
Увеличение одновременно выполняемых потоков только увеличит накладные расходы на переключение контекстов, а быстрее выполнятся всё равно не будет, т.к. число физических процессоров ограничено.
Здравствуйте, rumatavz, Вы писали:
R>А куда Вам больше?
есть куда. во время выполнения запросов к БД проц фактически простаивает большую часть времени. создание параллельных запросов увеличивает пропускную сопсобность в разы.
R>Увеличение одновременно выполняемых потоков только увеличит накладные расходы на переключение контекстов, а быстрее выполнятся всё равно не будет, т.к. число физических процессоров ограничено.
не в кассу
з.ы. провел несколько раз еще простейшие тесты и таки выполняется все последовательно. в ветке мелкософта отписался если кому интересно
R>>А куда Вам больше? А>есть куда. во время выполнения запросов к БД проц фактически простаивает большую часть времени. создание параллельных запросов увеличивает пропускную сопсобность в разы.
Отсюда вывод — работать с базой асинхронно.
В случае с множеством потоков большая часть из них будет простаивать, а поток — не бесплатный ресурс.
Здравствуйте, rumatavz, Вы писали:
R>Отсюда вывод — работать с базой асинхронно.
как вы пришли к этому выводу? WCF вызывает метод Validate который должен выдать "результат". О какой асинхронности доступа к БД вы говорите? что она даст нам в этом случае?
R>В случае с множеством потоков большая часть из них будет простаивать, а поток — не бесплатный ресурс.
все эти банальности как бы общеизвестны.
раскройте тему применительно к топику
R>>Отсюда вывод — работать с базой асинхронно. А>как вы пришли к этому выводу? WCF вызывает метод Validate который должен выдать "результат". О какой асинхронности доступа к БД вы говорите? что она даст нам в этом случае?
Я имел ввиду, что если есть пул потоков, из которых выполняется одновременно выполняется только 10, то асинхронный вызов — в духе BeginRead позволил бы потоку вернуться в пул и обрабатывать другой вызов во время работы с БД(даже если WCF просто вызывает какой то метод, который выдаёт результат).
В данном случае признаю неуместность совета, т.к. даже если поток спит остальные запросы всё равно ожидают .
Здравствуйте, rumatavz, Вы писали:
R>Я имел ввиду, что если есть пул потоков, из которых выполняется одновременно выполняется только 10, то асинхронный вызов — в духе BeginRead позволил бы потоку вернуться в пул и обрабатывать другой вызов во время работы с БД(даже если WCF просто вызывает какой то метод, который выдаёт результат).
это понятно. проблема в том, что итого нет и 10 параллельных вызовов, есть последовательное выполнение. более того, я руками делал ThreadPool.SetMinThreads(350, 350), тротлинг тоже задан в такие значения, но все тщетно. судя по молчанию мелкософта — все очень плохо и баг имеет место быть. самое ужасное, что автор подобного топика на msdn создал тему пол года назад, а ответа все нет. они просто тупо тихо слились — не икомментировать, не исправлять