LINUX.ORG.RU

Выделение ресурсов для сессий


0

1

В моем текущем проекте, для каждой сессии выделяется ресурс. В контексте проекта ресурс, это просто уникальная директория, но количество этих директорий ограничено, так как это просто хоумы для работы экземпляра программы, которая связывается с комплектом оборудования, которое ограничено и на каждую сессию выделяется один комплект целиком. Вобщем объяснять долго, можно просто сказать, что каждая сессия закрепляется за директорией, создавать которые от фонаря я не могу. Вот их 30 штук и все тут.

Это ко всему прочему мой второй сайт, так что делайте на это скидку, если я вдруг начну нести ахинею.

Управление сессиями свое. Все пишется на Tcl через cgi.

Как работает управление сессиями сейчас:

Клиент обращаестя к cgi скрипте на tcl. Скрипт создает индентификатор сессии и на сервере сохраняет файл имя которого ID сессии и в этот файл записывате номер выделенной для этой сессии директории (пока файл пуст, так как директория ещё не выделена). Клиенту скрипт отсылает сгенерированую пустую страницу уже с id (он передается всегда через GET) сессии которая авторефрешится и соответсвенно браузер клиента выполняет запрос уже содержащий id - на этом этапе отрабатывает другой скрипт который уже выделяет ресурс (директорию). Делается это так - скрипт проверяет не записано ли уже имя директории в файл сессии которая требует выделения ресурса, если нет, то выделяет ресурс и вписывает его в файл сессии, а в саму дерикторию кладет файл inuse в который вписывается id сессии, которая использует этот ресурс.

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

Вобщем-то вопрос - как бороться с этим флудом?

★★★★★

а cgi и tcl - обязательно? =)

занятость ресурса хранить в оперативной памяти (хз как уж у вас на tcl это делается). Писаться будет не мгновенно, но быстрее. Если сильно нужны файлы - можно потом пост-фактум сливать содержимое оперативки в файлы.

соединения обрабытывать одним процессом. Тогда можно делать либо последовательные запросы (максимум 30 сессий - не так много, чтобы разводить адову асинхронность) либо использовать синхронизацию типа «барьер». Если все же нужна обработка несколькими процессами, можно отдать ее этим процессам, но коннекты получать одним процессом

обрабатывать сессии (на уровне работы с вебом, а не твои) встроенными средствами веб-сервера

stevejobs ★★★★☆
()

имхо, корень зла в том, что http используется не по назначению. Веб - это statless, а вся малость что в нем stateful - иллюзия и гемор. Если кто-то дергает страницу, нельзя предполагать, что тем самым он искаропкипереведет твою систему в какое-то состояние. Нужно или отказываться от состояний, или придумать какой-то надежный симулятор для них. Твоя «проблема» на самом деле не проблема, всё правильно они делают =)

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

Ну как без cgi это решить я не знаю - там много чего нужно на сервере выполнять. Tcl не обязательно, но в нем я неплохо ориентируюсь, а в PHP - нет. Получается, что написать можно бы было без cgi на php, но разве там я не получу тех же проблем, когда PHP скрипт, начнет запускать bash скрипты и бинарники, работа которых необходима?

Да нет - файло не нужно, но сейчас я поправде говоря юзал файлы в tmpfs - не думаю что можно значительно выиграть по скорости ещё что-то.

Как обрабатывать сессии встроенными средствами сервера, я пока не знаю - дайте хоть наводку - куда копать.

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от stevejobs

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

Suntechnic ★★★★★
() автор топика

Не помню, как в php и не знаю как в tcl, а в perl, например, можно использовать sysopen для эксклюзивного открытия файла. Так вот. Твой первый скрипт пусть генерирует id, но не создаёт пустой файл. Файл пусть создаёт второй скрипт при помощи sysopen с O_WRONLY | O_EXCL | O_CREAT и сразу пишет туда номер рабочей директории. Остальные попробуют потом этот файл создать, а он уже есть - облом, выход, все счастливы. Или я что-то не понял?

SOmni ★★
()
Ответ на: комментарий от Suntechnic

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

Емнип, пых хранит сессии точно так же как у тебя, в файлах. Поэтому хз, не выйдет ли то же самое, я в пыхе не силен ;)

А чо, у тебя пользователи могут получить доступ к оборудованию вот просто так, без всяких логинов и паролей? Попробуй свою методику, но на этот раз с логином и паролем, мб всё окажется в шоколаде.

На жабке я бы сделал так: есть синглтон, в котором хранится состояние всех 30 доступных ресурсов. Чел логинится на сайт, долбится в тот синглтон и спрашивает: есть ли у него свободные ресурсы. Если свободный ресурс есть, возвращается его номер, если нету - null. Сей номерок сохраняется у пользователя в сессии. Когда сессия протухает или убивается, ресурс отпускается на волю.

stevejobs ★★★★☆
()
Ответ на: комментарий от stevejobs

Я знаю про session_start в PHP, спасибо. И это я храню сессию так же как пых - собственно там идею и подцепил. ;)

Да - могут получать без пароля доступ - там весь цимис в том, что вошел на сайт и сразу же начал работу.

Про синглтон я не понял. Что это такое вообще?

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от SOmni

Слишком маленький разрыв между запросами. Сейчас думаю кстати и в направлении - вставить в каждый скрипт случайную задержку временную в начало.

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic

> И это я храню сессию так же как пых - собственно там идею и подцепил. ;)

а как борется с твоей проблемой пых? В нем всё работает, или такая же ботва, как у тебя?

что вошел на сайт и сразу же начал работу.


есть предположение, что если вход на страницу будет связан с отправкой формы, то опера не будет пытаться переотправить форму 100500 раз. Логин и пароль - хороший предлог для отправки формы, но можно еще какую-нить отмазку придумать ;)

Про синглтон я не понял. Что это такое вообще?


http://ru.wikipedia.org/wiki/%D0%9E%D0%B4%D0%B8%D0%BD%D0%BE%D1%87%D0%BA%D0%B0...

синглтон — это класс, у которого есть гарантированно только один экземпляр и только одна общая для всех точка доступа.

На практике, из какой бы сессии, с какого бы урла, в какой бы момент времени ты ни позвал массив ресурсов, это будет всегда один и тот же массив ресурсов.

Файловая система у тебя в каком-то смысле тоже синглтон. Но синглтон как объект языка позволяет 1) хранить данные в оперативке, т.е. иметь гораздо более быстрый доступ к ним 2) использовать «всю мощь языка» (и его библиотек) для организации доступа к данным. Например, в жабке достаточно навесить на ресурс ключевое слово synchronized чтобы обеспечить гарантированный последовательный доступ.

(есть каноничная книжка Java Cuncurrency in Practice, полезная имхо и для других технологий. К сожалению, чтобы ее асилить в первый раз, жаву знать таки обязательно)

stevejobs ★★★★☆
()
Ответ на: комментарий от SOmni
#!/bin/sh
# guestbook.cgi
# Implement a simple guestbook page.
# The set of visitors is kept in a simple database.
# The newguest.cgi script will update the database.
# \
exec tclsh "$0" ${1+"$@"};

# здесь мы просто входим и создаем сессию


# Рабочая директория
set workfdr [ file dirname $argv0 ];
# папка со скриптами
append tclfolder "$workfdr" {/tclscripts};
# подгружаем константы
source "$tclfolder/setconstants.tcl"
# выполняем начальную задержку
# случайную с продолжительностью от 0 до 800ms и шагом 10ms
after [expr "(int(rand() * 80))*10"];
# получаем ip
set IP $::env(REMOTE_ADDR)
append ssfile "$ssfolder" {/} $IP;
# назавем файл айпишником клиента, чтобы все экземпляры обращались к одному
# файлу
# если файл уже есть то нужно выйти.
if { [file exists "$ssfile"] } {exit}; # выйдем если файл есть

# генерируем индентификатор сессии
set SIN [expr "(int(rand() * 899999 + 100000))"];
# создаем файл сессии
# открываем его только на запись, создавая новый, но только если его ещё нет
# и выходим если возникла ошибка открытия (файл существует)
if { [catch {
	set sfd [open "$ssfile" "WRONLY CREAT EXCL"]}] } {exit};
# С этого места должен работать только один экземпляр -
# остальные должны обламаться и молча умереть.
puts $sfd X; # указатель того, что ресрс еще не выделен для этой сессии
close $sfd;
# теперь переименовываем файл после ожидания, достаточного,
# что бы его увидели все экземляры под именем==IP
after 1000;
file rename "$ssfile" "$ssfolder/$SIN";
# сессия открыта
# генерируем страницу выделения ресурсов
set pf [open "$htmlfolder/entry.html" r];
puts [string map "%SIN% $SIN" [read $pf]];
close $pf;

и все равно оно умудряется создать 5 сессий...

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic

Черт, я ССЗБ...

Прошу у всех прощения - запросы отрабатываются строго последовательно.

Дело в том, что маркером того, что ресурс не был выделен был просто символ X и проверялось равенство ему, но в файл это записывалось командной puts $sfd X;, в то время когда должно было быть puts -nonewline $sfd X; и все бы было хорошо, но перепутанные != и == приводили к тому, что у меня никогда не было == X, но вместо невыделения ресурса он выделялся...

Теперь задача становится тривиальной - нужно только привязать генерацию сессии к IP а после генерации отвязать IP от сессии.

Сорри... Мне стыдно.

Suntechnic ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.