| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java EE (J2EE) и Spring > JSP отдельная страничка - отдельный объект? |
| Автор: chief39 31.10.2005, 17:53 | ||
| Соббсно вопрос: Если я правильно понял.... jsp страничка(1.jsp) которая содержит всего лишь
компилируется в класс сервлета? И два запроса к этой страничке повлекут создание двух экзепляров этого класса? А если есть ещё и 2.jsp - то для неё будет создан ещё один класс сервлета и при обращении Васи, Пети и Коли к этой страничке будет создано 3 экземпляра этого класса? |
| Автор: KostenkoSergey 31.10.2005, 18:19 |
| Пул объектов есть... но, хочется верить, что зависимость не такая линейная Экземпляр будет создан для отдельного потока сервера. (их число настраивается) а так один объект может обработать запрос как от Васи так и от Пети .... ИМХО 3 экземпляра - в случае одновременного обращения. |
| Автор: chief39 31.10.2005, 18:45 |
| То есть для отдельного потока - отдельный объект... Если Вася, Петя и Коля коннектятся - для них(я так понимаю) создаются три потока... В каждом из них такой объект? Или один поток может обрабатывать запросы от всех троих? И когда уничтожится объект(пропадёт ссылка на него)? Неужели объект будет лежать после обращений Коли и ждать появления какого-нить Васи? |
| Автор: chief39 2.11.2005, 16:44 | ||
Мдя.... всё-таки один объект может целую ватагу процессов обслуживать.... Посему иногда полезно синхронизировать Не дочитал мануал |
| Автор: Souljah 2.11.2005, 18:50 |
| про потоки - обработчики читал про несколько потоков сервера в первый раз слышу где можно про это почитать и какой сервер имеется в виду? thnx in advance |
| Автор: Stampede 2.11.2005, 20:46 | ||
Про потоки сервера знать нужно обязательно, а не то тебя ждут "ужасные опасности и страшные приключения" (с) Сверчок. Если коротко, то для каждого входящего запроса создается новый поток (на самом деле может браться готовый из пула). Если три человека обратятся одновременно к одной странице JSP, то каждый стопудово получит по отдельному потоку. А вот экземпляров сервлета, который представляет данную страницу, скорее всего будет только один (зависит от реализации/настроек контейнера). Поэтому, когда пишешь код сервлета/JSP страницы, нужно четко осознавать, что хранить состояние в экземпляре класса может быть чревато. В качестве вводной (хотя и очень поверхностной) статьи по данному вопросу могу посоветовать вот это: http://www.javaworld.com/javaworld/jw-07-2004/jw-0712-threadsafe.html Успехов! |
| Автор: batigoal 2.11.2005, 21:29 | ||
Отличная статья. Если я все правильно понял, предлагаютсчя три варианта предотвращения ошибок из-за сервлетной многопоточности: 1. Избегать использования полей в классе сервлета, стараться обходиться локальными переменными, при необходимости - передавать их в виде аргументов; 2. Синхронизировать участки кода 3. Реализовывать интерфейс SingleThreadServlet, при этом контейнер сам позаботится о том, чтобы вызовы этого сервлета обрабатывались исключительно последовательно. Так? |
| Автор: Stampede 2.11.2005, 22:30 |
| Lamer George, я не случайно сделал оговорку, что рекомендую статью именно в качестве вводной - только чтобы получить представление о проблематике. Что касается практических рекомендаций, то тут, боюсь, все обстоит далеко не так просто. В первом приближении, конечно, можно воспользоваться теми предложениями, которые ты суммаризовал (summarized). Или суммировал? Вот тут http://forum.vingrad.ru/index.php?showtopic=68804 я предлагаю полностью сериализовать обслуживание всех запросов, как простую и надежную стратегию, которая начисто исключает возможность каких-либо сюрпризов конкурентного доступа. Если есть желание обсудить/поспорить - буду завсегда рад |
| Автор: batigoal 2.11.2005, 22:49 | ||||
Собственно, целью моего summary было именно желание узнать, какие же еще должны/могут использоваться стратегии защиты.
В смысле - выстроить их в строгую очередь? Но ведь это будет тот же самый SingleThreadServlet.
Что именно имеется в виду? В принципе, все конфликты не отловить. Например, у нас - человек заказывает услугу. Если он начнет ее заказывать в 12.00, а подтвердит заказ только в 12.10, то, теоретически, в эти десять минут может вклиниться админ, и удалить этот сервис. Блокировать возможность удаления услуги на эти 10 минут - неразумно. Как быть?.. (ситуация, конечно, редкая. В большинстве случаев операция помещается в одну транзакцию) |
| Автор: Stampede 2.11.2005, 23:36 | ||||
Нет, в общем случае это совершенно разные вещи, по двум причинам: 1. Объявление SingleThreadModel действует только на уровне отдельного класса сервлета. Поэтому к сервлету A будет выстраиваться своя очередь, а к сервлету B - своя. Что есть отнюдь не то же самое, что одна единственная очередь ко всем сервлетам, особенно, повторяю, в ситуации, когда разные сервлеты обращаются к базе данных. 2. Говоря об очереди к сервлету в SingleThreadModel, мы исходим из предположения, что контейнер держит только один экземпляр сервлета, что является весьма ненадежной посылкой. На самом деле режим SingleThreadModel всего лишь гарантирует, что если экземпляр класса выделен одному потоку для обработки запроса, то до окончания цикла обработки он не будет доступен другим потокам. Соответственно, для удовлетворения этого требования можно выстраивать запросы в очередь, а можно создать еще один экземпляр данного сервлета.
Сценарии, в которых предусматривается возможность того, что юзер будет долго ковырять в носу - это совершенно другая история. Причем абсолютно жизненная - как, например, в системах бронирования авиабилетов. Но там и подходы другие. Я же говорил о доступе к данным в рамках одной транзакции. |
| Автор: Stampede 3.11.2005, 02:26 | ||||
В порядке перенесения обсуждения из http://forum.vingrad.ru/index.php?showtopic=68804&unread=1&st=0& и дальнейшего развития темы:
Очень хорошо, я ждал подобного замечания. И у меня есть наготове ответ. Значит, предлагаете считать? Давайте. Вот есть такое волшебное число: 86400. Это количество секунд в сутках. От него и будем плясать. Предположим, у нас достаточно тормозной сервер и неудачно продуманная архитектура приложения, так что на обслуживание запроса уходит в среднем одна секунда (хинт: реально несложно сделать так, что будет работать раз в сто быстрее). Даже в этом случае мы сможем обслужить почти 80000+ запросов в сутки. На самом деле меньше, потому что максимальная пропускная способность будет соответствовать пиковой нагрузке, так что реально мы можем говорить о среднесуточном трафике, примерно вполовину меньшем - то есть 40000 хитов в сутки. Что такое, товарищи, 40000 хитов? Это очень неслабый трафик. В рунете таким трафиком могут похвастать буквально единицы ресурсов (мы ведь не конкурируем с поисковиками и новостными сайтами). Так вот, даже если мы планируем выйти на уровень, скажем, exler.ru или oper.ru, то мы все еще будем в состоянии справиться со свалившимся нам на голову наплывом посетителей - даже при очень скромных исходных посылках. А дальше - следите за ходом мысли. Если мы такие неглупые ребята, что смогли создать ресурс с такой неслабой посещаемостью, то я вас уверяю, у нас хватит тяму, чтобы: - отбить трафик в деньги, как минимум достаточные, чтобы оплатить приличный хостинг с хорошим железом; - сделать редизайн таким образом, чтобы все мослало на порядок быстрее; - и, таким образом, добиться производительности, позволяющей обслуживать 40000 * 100 = 4 миллиона хитов в сутки в среднем. А с пропускной способностью в четыре миллиона нам теперь не страшен даже буржуйский интернет. Вопросы есть? (хинт: должны быть |
| Автор: Souljah 3.11.2005, 11:26 | ||
а-а блин, ну это не интересно я думал, имеются в виду еще некие сакральные "серверные потоки" - вроде нескольких экземпляров сервера в контексте одного приложения. вот и стало интересно, какой же сервер так умеет |
| Автор: pvo 3.11.2005, 11:33 |
| Stampede, предлагаю пока отвлечься от секунд и хитов - я не спорю с тем, что приложение можно оптимизировать таким образом, чтобы при обслуживании каждого запроса оно не гоняло по сети толпу SELECT - ов к базе. Я зачастую тоже использую описанный метод синхронизации. Он действительно достаточно прост и эффективен, но все сильно зависит от конкретной задачи,на что я и пытался указать. Например, у нас было несколько заказов, в которых с базой работают ( r/w/d ) 2 и более разных независимых приложений (не только веб приложений). Независимых - написанных разными людьми в разное время на разных языках и с использованием разных идеологий (ситуация не сильно хорошая, но довольно распростаненная у крупных рос. заказчиков). При этом в одной транзакции происходило довольно сложное изменение данных .... В общем, в такой ситуации синхронизация методов не спасает. Другой затык может возникнуть при использовании одного кода для доступа к базе в разных приложениях, например при работе приложения в кластере (я имею в виду томкатовский кластер, в котором реплицируются сессии). Хочет, например, заказчик, чтобы была обеспечена отказоустойчивость ... |
| Автор: chief39 3.11.2005, 12:03 | ||
Сорри, голова совсем не варила, это я так потоки обозвал сгоряча Хм... Вообще-то я думал о том же о чём и Souljah размечтался - чтоб всегда "железно" экземпляр сервлета - на один поток. Честно говоря, jsp/servlets только пару дней назад ковырнул, посему возникло много ламерских вопросов которые стыдно задавать до окончательного прочтения какой-нить из открытых книг. Нннно... Один рвётся как крик души: ООП( суть и java тоже За то что, реализовав что-то ты можешь это спрятать и сказать что теперь оно работает так как надо. Представляешь себе объект такой маленькой улиткой у которой всё внутри по сценарию и только рожки реагируют на внешний мир. И ей плевать на то, что там у остальных улиток. И, кажется, лучше java такое никто не поддерживает(хотя я всего не знаю И тут возникает обида на сервлеты: Какого чёрта объект Петиного потока изменяет с Колиным потоком. Может он там какой-нить "ВИЧ" подхватит, а потом Петиному потоку расхлёбываться. Или я самой парадигмы не понял, и классы сервлетов - это лишь обёрточка, а вся логика и синхронизация ДОЛЖНЫ быть реализованы в других классах? И какое решение ПРЕДЛАГАЕТСЯ СОЗДАТЕЛЯМИ ТЕХНОЛОГИИ JSP/SERVLETS для этих целей? P.S. Позволю себе вклиниться в разговор умных людей - глядишь и научат |
| Автор: Souljah 3.11.2005, 13:02 | ||
точно! сервлеты - это всего лишь точки входа в ваше приложение. т.е. логики в них не должно быть (за исключением формирования объектов для jsp вьюшек) создатели технологии конкретного решения не предлагают, они просто предоставили вам ферймворк на эту тему дофига написано было. недавно читал cookbook из commons-command, там как раз решение для web описывается, стоит посмотреть |
| Автор: chief39 3.11.2005, 13:53 | ||
Вас из дас, и где это можно найти в нете? Или только бумажный вариант? |
| Автор: Souljah 3.11.2005, 14:15 |
| упс, перепутал. http://jakarta.apache.org/commons/chain/cookbook.html конечно |
| Автор: Stampede 3.11.2005, 19:39 | ||||
Я понимаю. тебя смутила вот эта фраза:
Увы, это просто товарищ не совсем удачно выразился. Так что чуда не произошло, никаких сакральных серверных потоков не обнаружилось. И слава богу! Еще всяких сакральных потоков нам только не хватало |
| Автор: Stampede 3.11.2005, 20:32 | ||||
Это просто чудо, что ты тоже так думаешь, потому что тотальная сериализация - это такая чудовищная крамола, что никто про это даже и заикаться не смеет. Я же хочу сказать, что большинство типичных аргументов против сериализации - суть бредни записных теоретиков. Вот, например, что нам пишет один дятел из jGuru (да еще эдак вальяжно, со снисходительной ухмылочкой... блин, так бы и заехал ему прямо в тупое самодовольное рыло): http://www.jguru.com/faq/view.jsp?EID=1041533
Баран, если у тебя нагрузка хронически превышает пропускную способность, то никакая, даже самая распрекрасная стратегия синхронизации тебя не спасет, и хорошего сна тебе не видать как своих ушей до тех пор, пока в твою баранью голову не прокрадется мысль, что надо таки что-то делать или с приложением, или с железом, или с кастомерами, а лучше всего - со своей карьерой. Например, переквалифицироваться в управдомы. Потому что если бы ты хоть чуть-чуть умел соображать, то легко прикинул бы хер к носу: хорошо, по какому-то невероятному совпаданию в некий момент к нам вдруг ломанулись в едином порыве 35 юзеров. Ну и фигли? Поставим их в очередь, каждого обслужим за 20 ms, и никто не уйдет обиженным. Самому последнему придется ждать - страшно подумать - целых 0.7 секунды. Тебя бы, дятла, в сибирскую тайгу да на диалап, да дать задание подготовить обзор сайтов на народ.ру Это про сериализацию. Про доступ из разных приложений цас отдельно напишу. |
| Автор: Stampede 3.11.2005, 21:07 | ||
Да, действительно, тема интранета у нас осталась нераскрытой. От себя добавлю, что это не просто "довольно распространенная у крупных рос. заказчиков", а самая обычная - и в крупных, и в мелких, и в российских, и в нероссийских конторах ситуация. Что делать в таких случаях - вот ты и расскажи, поделись опытом. Мне навскидку приходит в голову только блокировка на период транзакции всех таблиц, которые участвуют в отработке запроса. Вообще, ситуация, конечно, невеселая. Про кэширование данных в приложении можно сразу забыть. Какое уж тут кэширование - тут дай бог фантомных ридов не поймать. И то, если дедлок не случится В общем, тема тоже интересная |
| Автор: chief39 4.11.2005, 11:47 |
| Stampede, у меня вопросина появилась, задал в соседней теме. Если нетрудно, хотел бы выслушать твоё мнение и, желательно, совет. Особенно если он не будет касаться моей переквалификации |
| Автор: Stampede 4.11.2005, 13:44 | ||||
Готово.
Плюс за чувство юмора chief39, не стыдно не знать чего-то и пытаться искать ответы. Стыдно надувать щеки, корчить из себя эксперта и одарять неразумных перлами |
| Автор: chief39 4.11.2005, 13:50 | ||
Стараюсь... Стыдно что не дочитал и не углядел. Скоро ещё вопросов подкину. |
| Автор: pvo 5.11.2005, 12:33 | ||||
Собственно, так и делалось - синхронизация на уровне базы. Конечно, блокировались не целиком таблицы, а строки(мы использовали оракл). А для повышения скорости использовались хранимые процедуры - чтобы не гонять кучу select, update и прочего по сети. В некоторых случаях эти хранимые процедуры уже были, в некоторых приходилось их писать самим.
Один раз делали и кэширование в приложении в такой ситуации - на таблицы невесили триггеры, отправляющие сигналы об изменении данных при завершении транзации - в приложении эти сигналы ловили и обновляли кэш. |
| Автор: 3x3 20.9.2006, 02:50 | ||||||||
[QUOTE=Stampede,3.11.2005, 20:32]
Про барана вы это метко заметили. Только, извините, на барана вы сам как-то больше похожи. Во-первых, в случае веб-приложения показ странички это не обязательно один гет-запрос. Страница содержит, например изображения, которые генерируются персонализованно, или фреймы. Вполне вероятна ситуация, что один клик пользователя потянет за собой цепь гетов для формирования странички на его экране, и для каждого изволь проверить права доступа, вытряхнуть из базы нужные байты, что-нибудь с ними, не дай бог, сделать.. При не очень-то быстрой сети такие задержки добавляют дискомфорт пользователю, а остальные юзеры и вовсе лапу сосут пока первый высасывает данные. Во-вторых суточная нагрузка - это средняя температура по палате. Нужно ли объяснять, почему львиная доля запросов к сервису будет сосредоточена на интервале в несколько часов? Если это корпоративный сервер - в бизнес часы, иначе - в начале рабочего дня, в обед, в конце рабочего дня и вечерний пик? В третьих, и в самых важных, тут что-то говорили про крутое оборудование и т.п. А что толку с крутого оборудования, если у вас запросы СЕРИАЛИЗУЮТСЯ? Ну поставь ты хоть 24 процессора, хоть 32 - работать-то будет один. С Сериализацией запросов вы не в состоянии обеспечить загрузку оборудования, это заведомо немасштабируемое решение. Настройка приложения - это решение задачи максимальной утилизации имеющихся вычислительных ресурсов, а подход с сериализацией - это декларация своей профнепригодности. __________________ Автору треда: ну и пусть оно создаёт экземпляры классов на всякий запрос. Храните данные в сессии: <% javax.servlet.http.HttpSession s = request.getSession(); Integer i; syncronyzed(s){ i = (Integer)s.getAttribute("i"); if(i==null) i=0; s.setAttribute("i",i+1); } out.write("hello "+String.valueOf(i++)); %> Добавлено @ 03:03
А почему было не сделать обновление кеша по завершении транзакции? Если в приложении есть кеш - очевидно многие читают одно и то же, а изменения происходят намного реже. При изменении данных, каждый метод точно знает что он изменил, по этому перед коммитом сделанных изменений, он просто лочит кеш, делает коммит в базу, если ошибка - отпускает кеш, если нормально прошло - удаляет из кеша измененные записи и опять-таки отпускает кеш: первый, кто за измененными данными обратится, тот и будет их выкачивать. Ну и плюс механизм целостности предусмотреть: читатели должны вычитывать непротиворечивый набор данных, по оракловому же принципу, а писатели... С писателями oracle разберётся. Иначе зачем вам сервер приложений? |
| Автор: tux 20.9.2006, 04:51 |
| 3x3, неплохо, что поднял интересную тему из глубин веков, но вот про барана вспоминать точно не стоило. |
| Автор: 3x3 21.9.2006, 05:09 |
| Stampede, Я не собираюсь тратить на ваши глупости 6 часов, по этому скажу кратко о том, в чём я с вами согласен, а именно:
Вот абсолютно с вами в этом согласен по части применения в системах массового обслуживания Думайте сами - для чего служит сервер приложений и для чего - JSPшки. Возможно, в вашем воспалённом воображении приложения пишут графические дизайнеры, а JSP-шками приходится заниматься умудренным опытом человекам, которые очень хорошо понимают, что такое многопоточное программирование, но, как мне кажется, дело обстоит несколько иначе. Не говоря уже об остальной ерунде, которую вы там понаписали. PS Ответными оскорблениями я вас осыпать не стану поскольку у меня нет нужды поддерживать видимость собственной авторитетности ;) |
| Автор: Shaggie 9.10.2007, 08:54 | ||
| Внимательно перечитал обсуждение. И даже несколько раз. Но вопросы остались... 1) Сериализация запросов и обработка юзверей по очереди. Но разве сериализация - это не способ сохранения объекта в независимом от конкретного приложения состоянии? То есть подход, когда класс имплементит интерфейс java.io.Serializable (или java.io.Externalizable), и может быть сохранён вне программы. Каким образом это связано с входящей очередью пользователей? 2) Как сохранять пользователезависимые значения в JSP/сервлете? Прятать всё в сессию? Писать в кукисы? Каждый раз вызывать
если необходимо сравнить сохранённое значение с константой? Имхо изврат... Есть более человеческие способы работы с уникальными пользователю значениями? |
| Автор: Shurr 9.10.2007, 15:56 | ||
Shaggie
Во-первых, разделение зависит от области актуальности этих данных. Т.е., общие данные, относящиеся к клиент лежат в базе, данные, актуальные для данной сессии - в session, относящиеся к данной машине - в куках, к данному запросу - в локальных переменных, или в request если их надо перебросить в на другую страницу/сервлет в рамках этого запроса. Плюс, например, если объем данных большой - в сессии/куках их лучше не хранить. В таком случае, их можно сохранить в БД или где-нибудь в собственном хранилище, завязавшись на идентификатор сессии(или, соответственно, идентификатор, записанный в куках). При использовании такого механизма нужно не забывать про очистку этих данных из хранилища после их устаревания. |
| Автор: Shaggie 10.10.2007, 05:16 |
| Shurr, спасибо, общее направление понял, а в частностях как-нибудь сам выход найду. А про сериализацию кто может помочь прояснить момент? |
| Автор: Stampede 10.10.2007, 07:16 |
Да просто термин имеет несколько значений. Такое бывает сплошь и рядом. Сравни, например:
Сериализация объектов в некий выходной формат не имеет ничего общего с сериализацией (постановкой в очередь) входящих запросов. Так что все просто |
| Автор: am_sasa 10.10.2007, 09:39 | ||
|
| Автор: Fedrus 10.10.2007, 11:30 | ||||
Это скорее всего по тому что таймаут бывает разный. Вообще как я понемаю когда пользователь закончит работу с приложением ссесия останется открытой до завершения таймаута так зачем это время хранить большые объемы данных? |