суббота, 24 сентября 2016 г.

Как я докатился до возни с cookies между доменами или исповедь [s]рукож...[/s] программиста в отделе управления бизнес-процессами

Предыстория.


Давным-давно, уже, действительно, кроме шуток, давно на работе, работая местным сисодминчегом имелась у меня привычечка, когда делать было нечего, писать на php, ну одминчег, он ведь, чем меньше появляется у пользователя, тем лучше работает. Ну вот, и у меня сначала времени совсем не было, а потом было столько, что я, буквально, изнывал от ничегонеделания на работе. Тогдашечки игрался я в одну mmorpg, с названием muonline. Ну слово за слово, дело за дело, написал я обвязку для этой игры, разобрался в работе сервера с бд. понятно, что не совсем лицензионного. Ну и выложил свою поделку в интернеты. Со временем, скилл моего хобби рос, как и обязка, и... я сменил работу :). В общем, понадобился на новом месте кусочек моего хобби, а точнее, опыт в костылепке на php. Ну и началась
разработка ERP системы, с наработками из обвязки му. Скиллы снова начали расти и появился движок mwce - MuWebCloneEngine заместо MuWebClone сайта. И стал тот движок развиваться дальше. На работе ERP система росла-росла, даже с учетом оптимизаций, улучшений в скорости работы и ресурсопотребляемости, настало время, когда ей стало тесно на 1 сервере. На тот момент, в ней были все основные возможности ERP - управление проектами, документооборот, почта, интерактивная система событий для каждого пользователя оной.

Надвигающаяся буря.


Так вот, первые признаки ахтунга пришли когда система начала слегка рандомно подтормаживать и апача(на которой оно все крутилось) захотел умереть, но не мог, так как его родительский процесс постоянно реанимировал зависший вглухую child-процесс, что вызывало лютый... конец нормальной работы сервера. Первый шаг был простой - с апачей было решено попрощаться и поставить IIS... да шучу я, как начитавшийся тру чел, я принял решения ставить nginx. И, о чудо, помогло! оно снова заработало шустро и даже шустрее, чем было с апачем.
Далее, стоит упомянуть об одной особенности: в системе крутятся проекты, которые постоянно меняют свою стадию, а каждая стадия имеет свое ответственное лицо и проект, в целом, своего куратора. Так вот, чтобы все заинтересованные лица имели актуальную информацию, был введен журнал событий, в котором отображаются все события по движухе, что пропускает пользователь. Как ни странно, но у пользователей (примерно 50/50.. ай ладно, кому я вру, 25/75), по какой-то неведомой причине,  журнал событий сильной любви не снискал, поэтому им насильно сервер собирал в пачки события (по типам) и слал на почту. Но пользователи с маниакальной упертостью продолжали рубить сук на котором сидели, и игорили письма. Но наш бравый отдел решил, что раз они упертые то мы будем еще настойчивее и впилили сервис, который в реальном времени проверяет информацию по событиям и ежели оные присутствуют, вываливать их в ненавязчивом окошке, по 10 в пачке, справа снизу, с возможностью отметить событие прочитанным и/или перейти в новое окно, где открывалось бы окно с проектом/задачей, в общем, всем тем, что вызвало событие и найти 10 отличий с тем что было там раньше.
Понятное дело, что был цельный вопрос, как делать саму движуху событий : вешать на ноду или банально долбиться аяксом к серверу и собирать данные оттуда. В силу количества рук (а на данный момент их всего 4: ваш покорный слуга + его непокорный начальник, который отвечает за 70% логики базы (процедуры, функции) и по совместительству является архитектором билда( если вкратце, то билд - почти сайт, который зависит от ядра, то есть mwce, которая дает необходимый функционал. билд - бизнес логика, ядро - все остальное), который и является местной ERP(уже больше, но не суть), ноде было отказано и залеплено обычным аякс-запросом в бекенд, с нетерпеливым ожиданием ответа. Все это было на 1 сервере, все это было лютой ошибкой. При 30-40 активных пользователях, у которых открыто минимум по 3-4 вкладки ( в среднем, около 10), серверу было, мягко говоря, не хорошо. И тут ваш покорный слуга сел курить Worker'ы от JS, остановился на SharedWorker'е, который и по сей час трудится. Стало значительно легче, но легкое неудобство (как прыщь на 5й точке) все же осталось.
Следует отметить, что к тому времени, рассылка почты уже была на отдельном сервере, где лежало php и кусочек билда, что отвечал только за рассылку данных. Запускается это все с помощью task manager'а (cron) вендового сервера с вызовом нужного модуля из командной строки (все тот же mwce). Так вот, запустив SharedWorker нагрузка сократилась в разы, так как запустив вкладку с системой 1 раз, запускался воркер и сколько бы потом раз не открывались новые вкладки воркер был только 1 и рассылал события по всем вкладкам (как добились этого результата, история отдельная, требующая отдельной статьи, но ежели кому будет совсем интересно, вы только скажите). Но, оставалась 1 проблема... Документы. Загрузка/выгрузка да и просто просмотр того, чего можно загрузить/выгрузить.
И с этого момента стало ясно, что нужны ноды от основного серера, благо есть возможность поднять сабдомены и сильно не напрягаться. С выскакивающими событиями все было просто: слил на другой сервер да волшебное:
header('Access-Control-Allow-Origin: *'); 
решили проблему. Но вот с просмотром и загрузкой документов все гораздо сложнее - левому серверу необходимо понимать, кто к нему пришел и куда его послать: скачать документы или в противоположную сторону. И вот тут был мозговой штурм. Как передать данные с 1 сабдомена на другой.

Самая суть.


Сделали вот как. В базе данных были созданы таблицы под сессию: таблица с идентификатором сессии и таблица с данными, что в сессию надо сувать. Основная суть работы примерно такая:
На основном сервере (там где основная движуха и авторизация сервера) при входе в систему (авторизации) в базу данных добавляются данные, однозначно(или почти) идентифицирующие пользователя и тот девайс с которого он зашел. Для девайса создается хитрослепленный хешик, на основании ряда параметров, которые могли бы его идентифицировать, далее создается 2 куки:

session_set_cookie_params (0, '/', '.domain.ru'); 

В 1 лежит тот самый хитрый хешик, а во второй время создания кука, для обновления информации. Далее, так как куки видны между сабдоменами, благополучно скармливаем тому сайту куки, по ним он смотрит в базу и если там есть кука, то создает сессии, в которых четко сказано, кто сюда пришел. Получился своеобразные механизм мастер-слейва, где основной сервер занимается записью новых даных в сессию бд, а вспомогательные, сервисные сервера однозначно понимают кто с браузера к ним пожаловал, тем самым убрав проблему с постоянным слетом сессий сервера (я про session livetime, ибо теперь из базы все это достается без надобности лишний раз авторизовываться) + удобная возможность переносить/разносить нагрузку повышая скорость работы всей системы в целом.

Продолжение следует...
Наверно...
Может  быть...


Комментариев нет:

Отправить комментарий