| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Ограничение количества соединений с базой |
| Автор: drkot 7.6.2014, 02:17 |
| Общие положения: - есть N нитей (N постоянно изменяется от 0 то тысяч) - каждая нить пишет в базу - для данной задачи выделено 10 соединений с базой Проблема: - идут отказы в обслуживании от базы Вопрос: как 1000 нитей заставить работать через 10 соединений с базой? Работа видится примерно так: 1) есть пул из 10 соединений 2) запрос свободного соединения из пула или ожидание пока освободится 3) работа с базой 4) возврат соединения в пул Собственно затруднение вызывает 2й пункт. PS: заставить работать через ОДНО соединение с базой проблем не вызывает, но это не эффективно. |
| Автор: PointerToNil 7.6.2014, 07:46 |
| WaitForMultipleObjects? |
| Автор: drkot 7.6.2014, 15:08 |
| и кого ждать? |
| Автор: PointerToNil 7.6.2014, 16:09 |
| CreateEvent / SetEvent / ResetEvent |
| Автор: drkot 7.6.2014, 17:12 |
| PointerToNil, Вы прямо таки "капитан очевидность" Вы говорите "ЧЕМ", а вопрос стоит "КАК".... Велосипед склепать не проблема, только нет гарантии что он поедет... Наверняка есть типовой алгоритм решения задачи, он и интересует. |
| Автор: PointerToNil 7.6.2014, 17:30 |
| drkot, вы из каких вариантов-то выбираете? огласите, плиз я просто не вижу тут ни вариантов, ни каких-то проблем или непонятностей кстати, насчет велосипедов - конечно, он возможен: массив из 10 булеанов - признаков "занято" по соединениям, попытка занять свободный нитью делается через InterlockedExchange (если вернул то же, что и положили - значит, кто-то успел раньше), а если перебор в цикле от 1 до 10 не обнаруживает свободного - небольшой sleep() и снова перебор вот это был бы велосипед, но я предложил специальные функции, которые долго изобретали, реализовывали и тестировали программисты компании microsoft, а другие старались и описывали их в msdn и толстых книгах |
| Автор: drkot 7.6.2014, 18:26 | ||
| PointerToNil, конкретный набор функций предполагает конкретное решение на их основе. Ваш набор:
предполагает что?... Ставить Event на каждое соединение и ждать их? Как минимум Eventы должны быть с автосбросом и есть ограничение на 64 соединения. Из явных проблем, о которых стоит упомянуть, это именование Eventов, так как при совпадении имен можем получить не предсказуемый эффект. Из не явных затруднена обработка и отслеживание упавших соединений и изменение их общего количества. Как по мне, - либо надо использовать один Event (который срабатывает при освобождение любого соединения) и оборачивать счетчик и прочее в критическую секцию - либо Semaphore (но как его прикрутить к данной задаче пока не понятно), возможно он и не применим тут... Главное чтобы не возникла проблема "узкого горлышка", а это уже конкретный алгоритм... В том же интерпретаторе PHP есть подобная реализация, да и не только в нем... |
| Автор: PointerToNil 7.6.2014, 19:07 |
| > Ставить Event на каждое соединение и ждать их? ну как бы ничего другого даже в голову не приходит > Как минимум Eventы должны быть с автосбросом какой "автосброс", зачем? > есть ограничение на 64 соединения. вы же сказали, что их всего 10 - к чему тут 64?? > Из явных проблем, о которых стоит упомянуть, это именование Eventов а зачем их именовать-то?? завели массив из 10 THandle/интегеров и сложили туда > затруднена обработка и отслеживание упавших соединений и изменение их общего количества как затруднена и по сравнению с чем? надеюсь, вы ведь сами обрабатываете эти падения? если оно упало во время занятости, так и восстанавливаться будет, сохраняя занятость если упало, будучи свободным, то займется, обнаружится факт падения и тоже будет восстанавливаться, будучи занятым > либо надо использовать один Event (который срабатывает при освобождение любого соединения) тогда вам все равно понадобится что-то типа массива из 10 булеанов для признаков занятости каждого конкретного соединения я предлагаю вместо них массив из 10 ивентов > либо Semaphore в семафоре есть счетчик, но вам-то не достаточно одного счетчика свободных или занятых соединений - вам нужны 10 отдельных признаков занятости/свободы для каждого конкретного из 10 соединений > Главное чтобы не возникла проблема "узкого горлышка" это обсуждайте с тем, кто вам ограничение в 10 соединений предписал - этого вполне может и мало оказаться но сделать транзакции нитей с БД как можно короче - возможно, в вашей компетенции вообще говоря, это уже работающую систему нужно профилировать на тему того, что насколько загружено и что является горлышком (сеть, процессор или диски и на каком из серверов - БД или веб и т.д.) и что нужно расширять (или будет видно, что все работает вполсилы из-за искусственных ограничений в софте) |
| Автор: drkot 7.6.2014, 20:01 |
а как Вы видите работу WaitForMultipleObjects на которой ждет 10 потоков без автосброса? нужно всегда думать о будущем хотел дальше отвечать, но передумал... нет желания комментировать глупости... |
| Автор: PointerToNil 7.6.2014, 20:15 |
| > а как Вы видите работу WaitForMultipleObjects на которой ждет 10 потоков без автосброса? как я представляю себе внутреннюю реализацию WaitForMultipleObjects? это точно стоит описывать? но, если что - таймаут в ней задается четвертым параметром - если вдруг он вам понадобится и, если что, можете еще завести специальный 11-й ивент для "аварийной сигнализации" (типа "кончай работу, пора обедать") > нужно всегда думать о будущем проблем с увеличением числа соединений не вижу никаких - ну, расширили динамический массив, завели новый ивент, аналогично и с уменьшением > хотел дальше отвечать, но передумал... нет желания комментировать глупости... правильно, за работу приниматься пора - там и разберетесь что к чему, даже метод тыка быстрее форумных дискуссий, я уж не говорю о rtfm |
| Автор: Sajtran 19.8.2014, 19:01 | ||
| Добрый день, коллеги Поделитесь наработками, что сделали самому пришлось решать похожую проблему мой код ниже, есть большие сомнения ...
|
| Автор: drkot 21.8.2014, 07:50 |
| Во первых событие должно быть с автосбросом. Во вторых не понятно какие объекты заняты, а какие свободны. Про странный цикл и смысл условия в нем я вообще молчу... все таки не смолчал... Но ход мыслей правильный. |
| Автор: Sajtran 23.8.2014, 19:50 | ||||||||
а разве у меня не автосброс?
и что в цикле не нравится, просто объект забирается, а потом возвращается function Lock(Timeout : Cardinal=0):TObj; - забирает procedure Unlock(const O:TObj); - отдаёт Добавлено через 3 минуты и 44 секунды Unlock правда ещё подправил немного
|
| Автор: PointerToNil 24.8.2014, 20:41 | ||
а у меня вот такой минимализм получился:
(чёта я подумал, зачем какие-то еще ивенты, если есть массив признаков занятости и все равно цикл по нему крутить) и "объектов пула" внутри нет - SRP! try_count может быть менее удобным, чем Timeout - это можно переделать |
| Автор: PointerToNil 24.8.2014, 23:49 |
| если 100500 потоков вызовут Event.WaitFor, то все они как бы "приостановятся". но ведь системный код (WaitForSingleObject), исполняющийся при этом в контексте каждого из потоков отдельно (т.е. в числе 100500 экземпляров), будет при этом что-то делать! есть веские подозрения, что таки крутить цикл (скорее всего, тоже со sleep-ом или подобным) - иных вариантов просто нет |
| Автор: drkot 25.8.2014, 14:11 |
есть еще прерывания. насколько понимаю логику системы... то сознается некая очередь потоков, и как минимум крутится один цикл, а скорее всего все висит на аппаратном прерывании таймера. Следовательно нулевое потребление ресурсов. |
| Автор: PointerToNil 25.8.2014, 14:59 | ||
(halt + аппаратное прерывание таймера - применимо только для того редчайшего случая, когда ВСЕ потоки вызовут sleep) |
| Автор: drkot 25.8.2014, 15:15 |
| PointerToNil, предлагаю сделать тест и посмотреть. Пул из 15 объектов и 50 потоков. После захвата объекта поток спит 100мс. в качестве оценочных параметров можно считать: среднее время ожидания захвата, количество захватов (каждым потоком), количество отказов в захвате. |
| Автор: Sajtran 28.8.2014, 07:47 | ||||||
спс, PointerToNil, ваша
заметил у себя фигню, ивенты просто не работали (не ждали :-() drkot, я не думаю что сильно стоит бояться FreeLock-код. Вот, например, зачем состояния хранить, если можно объект просто изъять вот подправка
вот так проверял
|