Зареждане на данни с Ajax от отдалечен сървър

Задача за оптимизиране бързината на сайт

Наскоро работих по сайта Речник на думите в българския език. В този сайт при търсене по някоя дума в дясната колона се зарежда блок с подобни думи. Подобните думи са такива, които се получават от търсената дума с добавяне, премахване или подмяна на една или две букви. За откриването на такива думи се използва алгоритъм с висока степен на сложност, който е бавен, защото претърсва цялата таблица с думи. Таблицата беше с размер около 100 000 реда и нарастваше и в резултат на това зареждането на страницата се бавеше до към 30 секунди - прекалено дълго време за уеб страница. Задачата ми беше да измисля начин за оптимизиране на бързодействието на сайта.

Решение

Първото, което направих е да опитам да оптимизирам SQL заявката. Ползваният алгоритъм не подлежи на оптимизация, затова се наложи да прибягна до някои дребни хитрости. Например търсене на подобни думи в ограничен набор от думи с дължина +/-2 спрямо дължината на търсената дума. Създадох някои допълнителни индекси на SQL таблиците и успях да съкратя средното време на около 8 секунди. Да чакаш цялата страница 8 секунди също е прекалено досадно и затова направих блока с подобни думи да се зарежда с Ajax. По този начин страницата се показваше веднага и само блока се бавеше, което беше напълно допустимо. Вече си мислех, че съм приключил, когато дойде писмо от хостинг доставчика, че се ползва прекалено бавна заявка, която бави другите сайтове на този споделен хостинг и настояваха да се оптимизира. Така стигнах до идеята, че данните за подобните думи трябва да се зареждат от отдалечен сървър. За да стане възможно това, трябва отдалеченият сървър да има същата таблица с думи в базата си данни. Направих автоматичен скрипт, който периодично да копира таблиците от единия сървър на другия. По този начин освен всичко друго се получи и още един архив на данните. След това оставаше да направя Ajax да се обръща към новия сървър. Тук отново има проблем: от съображения за сигурност Ajax не може да се обръща към домейн различен от този, на който се изпълнява. За да заобиколя това ограничение аз използвам следната програмистка техника: Ajax се обръща към скрипта similarClient.php разположен локално на сървъра на rechnik.info, който прави заявка към скрипт с име words.php на отдалечения сървър. Там се търси за подобни думи в копието на базата данни и намерения резултат се изпраща към similarClient.php, който го връща като резултат към Ajax. Към цялата система се добавя и кеширане на заявките, локално върху отдалечения сървър - този подход спестява дисково пространство на хостинга за сметка на увеличен трафик. При първото търсене в речника по дадена дума резултата се бави няколко секунди, но при всяко следващо търсене по тази дума, резултата се взема от кеш и става почти моментално. Всичко това може да изглежда малко сложно, но можеш да видиш колко добре действа в сайта на Речника.

Сигурност

Скриптът разположен на отдалечения сървър, който получава дума и връща списък с подобни думи е уеб скрипт и се извиква през HTTP. Това означава, че всеки който знае URL адреса и какви параметри приема, може лесно да използва това за свои цели и да прави заявки към сървъра. Използвайки горния метод, аз скривам URL адреса и това повишава сигурността многократно. Въпреки това е възможно връзката да бъде подслушана или логовете на сървъра да станат достъпни публично. Това ще разкрие URL адреса и някой може да се възползва. Затова един съвет: никога не разчитай само на сложен и таен URL адрес на скрипт!

Аз използвам допълнителни механизми за защита: отдалеченият сървър приема заявки само от IP адреса на rechnik.info. Това увеличава сигурността, но за съжаление не е напълно достатъчно, защото е възможно да пристигнат заявки с фалшифициран IP адрес. Следващиата стъпка е добавяне на кодиран параметър в GET заявката. По този начин URL адреса на заявката прилича на следния:

http://remote.domain.com/words.php?a=дума&code=a4b25d814f32b2c852c3d71d3

Низа подаван в променливата "code", е кодирана от скрипта similarClient.php и само скрипта words.php знае как да го разкодира и да разбере дали е валиден. Резултат се връща, само ако стойността е валидна, в противен случай опита се записва и се съобщава на админ. За да може някой да хакне това, трябва да има FTP достъп до някой от двата php файла.Следващата стъпка е ползване на HTTPS вместо HTTP, но тук вече навлизаме в сферата на банковия софтуер 🙂

Сигурен съм, че много хора ще се запитат: "За какво е всичко това? Какво толкова защитаваш?".

Нека да кажем, че се упражнявам 🙂 Не обичам да оставям нещата на случайността и не правя компромиси със сигурността. Винаги изпипвам нещата и се подсигурявам двойно. Препоръчвам ти да се научиш да работиш по този начин.

SEO

Описаната система си има и недостатъци. От SEO гледна точка връзките в блока Подобни думи са невидими за търсачките. За да може сайта да се индексира добре е нужен или Google sitemap, или допълнителен блок с връзки като този със "Случайни думи". Още по-добра работа би свършил блок със "Съседни думи", в който за дадена страница връзките винаги да са едни и същи.

Прочетена:15142
1 - лоша2 - слаба3 - средна4 - добра5 - отлична (2 гласа, оценка: 5,00 от 5. Моля изберете оценка!)
Loading...
Георги Стефанов
Магистър по информатика, който се занимава с компютри от 1988 г., професионално с програмиране от 1998 г., а с уеб технологии от 2002 г. Има богат опит при оптимизиране на бизнес сайтове. Повече от 15 години развива успешно свои уеб проекти и работи с български и международни компании за постоянно подобряване на техните сайтове и увеличаване на онлайн продажбите. 

10 comments on “Зареждане на данни с Ajax от отдалечен сървър”

  1. https е цаката, но има и друг, по-лесен начин. Променливата code може да е "променлива" малко по-буквално, т.е. да не е една и съща и да не се повтаря. За целта на двата сървъра ще ти трябва по още 1 таблица. както и скалъпен набързо криптиращ алгоритъм. Също и флууд контрол разбира се.
    Ае стига съм давал акъли 🙂

  2. Нещо сериозно си омазал щом в таблица с едва 300к реда търсиш повече от 30-50мс (мили секунди). Липсва ти правилна логика на приложението и правилни индекси или сайта ти се хоства на машина от времето на втората световна война (:

  3. @Victor ясно е, че HTTPS е по-добре. Тук обаче давам идея за просто и бързо, но достатъчно сигурно решение. При мен code също е динамична 😉

    @Марто искам да те помоля за малко повече доверие в PHP/MySQL експерта gan. Ако прочетеш внимателно статията ще видиш, че става въпрос за решаване на задача с алгоритъм имащ сложност O(n), което като време съответства на това да преминеш през цялата таблица без да може да ползваш индекс. От статията също става ясно, че се ползва стандартен споделен хостинг.

  4. Няма как да те приема за експерт, след като толкова лесно решим проблем го изкарваш сложен алгоритъм (:

    Мога да ти дам няколко пример с повечко данни и пак работещи десетки(стотици?) пъти по-бързо

    Ето ти един пример:
    mkfun.com/search.php?q=ivana

    Виж за колко време минава търсенето по една или повече думи (записите в базата са >600к). При това времето, което се показва в дясно е за всички заявки. Пусни си и други заявки за да се убедиш, че не е някакъв кеш. Машинката, на която се изпълнява не е нищо особено - дори е с едва 1gb рам.

  5. Оценявам ентусиазма ти да спориш, но очевидно не разбираш това, което ти казвам. Всъщност изглежда нямаш понятие и от сложност на алгоритми. Бързината на търсачката ти се дължи на използваните индекси, защото алгоритъма за търсене ти го позволява. За да разбереш, за какво става въпрос опитай да решиш следната задача. При търсене по дума да изведеш всички думи, които са на разстояние 2: получават се с добавяне или премахване на 1 или 2 символа към търсената дума, както и размяна на два символа спрямо търсената дума. Например при търсене по ivana да извежда тези които съдържат: ivanata, ivanas, ivan, iva, sivana, arivana, avani, ivtana, ivatana и т.н. Ако постигнеш моето време ще те поздравя с връзка към сайта 😉 Успех!

  6. Искаш да ми кажеш, че алгоритъма ти за премахване/добавяне на знаци към дума е в MySQL?

  7. Имам чувството приятел, че най-после започвам да ти привличам вниманието 🙂 Да, в mySQL-а е, като запазена процедура (stored procedure). Когато уеб сървър и mySQL сървър са на една и съща машина е почти все едно дали алгоритъма е реализиран в mySQL или се обработва от PHP - времето на изпълнение е почти еднакво. Но когато са на различни машини, се съмнявам, че ще искаш да избереш от SQL-а голямо количество данни, които да прехвърлиш по мрежата към уеб сървъра за обработка, защото най-малкото ще ти свърши лимита на трафика на хостинга 😉

  8. Набутал си се в блатото 🙂
    Попадаш в графата "Липсва ти правилна логика на приложението".
    С удоволствие бих разгледал и оптимизирал точно тази част от проекта ти - стига да искаш разбира се.

  9. Малко се съмнявам да успееш да "оптимизираш точно тази част от проекта ми", не защото аз не съм успял, а защото по този начин ще оптимизираш световно известен алгоритъм за търсене на близки думи, с което вероятно ще спечелиш нобелова награда по математика. Предлагам да спрем разговора тук, защото спря да добавя полезно съдържание в блога. Разбира се, ако искаш може да ми пишеш на имейл.

  10. Здравейте,
    за сигурността може да се ползва и AES ще си кодираш данните и даже и да ти прислушат връзката няма да разберат нищо. А може и за още по сигурно да ползваш като допълнение от другата страна user и pass за достъп до отдалечения скрипт така даже и да се смени IP адреса или някой да ти го имитира няма да може да го достъпи.

споделиха
linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram