Проста реализация на механизъм за дълго анкетиране в PHP

И така, какво точно е Long Polling? Изглежда по следния начин: 1) Клиентът изпраща обикновена ajax заявка до сървъра 2) Сървърът, вместо бързо да обработи тази заявка и да изпрати отговор на клиента, стартира цикъл, при всяка итерация на който следи възникването на събития (друг клиент е добавил запис или го е изтрил). 3) Когато възникне събитие, сървърът генерира отговор и го изпраща обратно на клиента, като по този начин изпълнява заявката. 4) Клиентът, след като получи отговор от сървъра, стартира манипулатора на събития и едновременно с това изпраща друга „дълга“ заявка към сървъра.

Тоест всичко е съвсем просто и ясно. Изпълнението обаче повдига няколко проблема, които трябва да бъдат решени.

Стъпки за практикуване

На първо място, възниква въпросът как скриптовете ще взаимодействат помежду си. В крайна сметка за всяка клиентска заявка към сървъра се създава независимо копие на PHP скрипта. Това означава, че е необходима някаква споделена памет за съхраняване на данни за събития. Традиционна опция - стартира демон, който оперира върху събития и поддържа връзка с клиентите. Използването на демон решава проблема с паметта естествено. Клиентите не се обръщат към уеб сървъра, за да получават събития, а към демона. В същото време клиентът, който задейства събитието, също казва на демона, че събитието е настъпило. И така всичко се върти в паметта на този демон. които могат да бъдат написани върху всичко. Но за нас, с оглед на шиенето на едно място и желанието да се справим без приложения на трети страни, демон на нищо няма да работи. И писането на демон в PHP, за моя вкус, не е много интересно. Хостингът може да има проблеми с промяната на максималното време за изпълнение на скрипта, а също така да обмисли интерфейсите за взаимодействие на клиенти с този демон ... Не, ще отидем по друг начин. Остава Aрешите само как да внедрите споделена памет в самия PHP. Опции за съхраняване на събития във файлове и бази данни идват на ум, но искам всичко да е по-близо - в паметта. Memcache, уви, не е достъпен за нас, но какво да правим тогава? И в php има такава концепция като споделена памет, по-точно концепцията не е функция на този език, но ни се дава възможност да я използваме. Механизмите на тази технология ни позволяват да създадем клетка в RAM и да я използваме за собствени цели. Ето какво ще използвам.

Нека се опитаме да представим интерфейс на клас, който ще реализира функционалността, от която се нуждаем. Какви методи са необходими? 1) Естествено, методът "слушане", който ще бъде извикан, когато клиентите изпращат заявки за анкета, и ще наблюдава събитията, които се случват. Нарекох този методслушай. 2) Освен това се нуждаем от метод, който ще създаде събитие. Този метод се наричаpush. 3) Вероятно искаме да обработим данните за събитието, преди да изпратим резултата обратно на клиента. Затова добавих метод, който регистрира събитие и свързва манипулатор към него. Методът се наричаregisterEvent.

В резултат на това получаваме следния интерфейс на класа:

Няколко бележки: 1) Само един манипулатор на събитие се поддържа в методаregisterEvent, поради факта, че върнатата стойност на манипулатора се връща на клиента като данни за събитие. В един манипулатор можете да извикате няколко функции и да съберете отговор на клиента от резултата от тяхната работа. Въпреки това, пренаписването на кода за поддръжка на множество манипулатори може да се направи без много трудности. 2) Методътlistenизползва параметъраlastQueryTime, който ви позволява да обработвате събития, настъпили преди получаването на заявката за слушане. Това може да бъде полезно при натоварванемрежата е висока и между завършването на една заявка за анкета от клиента и началото на друга може да има забележим период от време, в който се случват събития. 3) Горният код не взема предвид едновременния достъп до паметта. Но като цяло. за по-надеждна работа е желателно да се използват семафори. 4) Методътlistenизползва извикването на функциятаsleep(1). Това е необходимо, за да се намали броят на празните итерации. Скоростта на актуализиране веднъж в секунда е достатъчна за симулиране в реално време.

Е, на клиента всичко също е изключително просто. Имаме нужда от метод, който ще изпрати заявка за анкета до сървъра, ще изчака отговор, ще задейства манипулатори на събития и ще изпрати повторно заявката. Е, методът, който регистрира самите манипулатори на събития.

Източници: Описан Polling клас в PHP. Ако някой има нужда от него, ще го изчистя и ще публикувам клиентската страна.

И тук можете да получите грант за тестов период на Yandex.Cloud. Необходимо е само да въведете "Habr" в полето "секретна парола".