Kuhamisha maandishi ya nyuma ya PHP kwa basi ya mitiririko ya Redis na kuchagua maktaba inayojitegemea.

Kuhamisha maandishi ya nyuma ya PHP kwa basi ya mitiririko ya Redis na kuchagua maktaba inayojitegemea.

utangulizi

Tovuti yangu, ambayo ninaendesha kama hobby, imeundwa kukaribisha kurasa za nyumbani za kuvutia na tovuti za kibinafsi. Mada hii ilianza kunivutia mwanzoni mwa safari yangu ya programu; wakati huo nilivutiwa na kupata wataalamu wazuri ambao wanaandika juu yao wenyewe, vitu vyao vya kupumzika na miradi. Tabia ya kuwagundua mwenyewe inabaki hadi leo: karibu kila tovuti ya kibiashara na sio ya kibiashara sana, ninaendelea kuangalia kwenye ukurasa wa chini kutafuta viungo kwa waandishi.

Utekelezaji wa wazo

Toleo la kwanza lilikuwa ukurasa wa html kwenye wavuti yangu ya kibinafsi, ambapo niliweka viungo vilivyo na saini kwenye orodha ya ul. Baada ya kuandika kurasa 20 kwa muda, nilianza kufikiria kuwa hii haikuwa nzuri sana na niliamua kujaribu kugeuza mchakato huo otomatiki. Kwenye stackoverflow, niligundua kuwa watu wengi wanaonyesha tovuti kwenye wasifu wao, kwa hivyo niliandika kichanganuzi katika php, ambacho kilipitia wasifu, kuanzia na ya kwanza (anwani kwenye SO hadi leo ni kama hii: `/users/1` ), ilitoa viungo kutoka kwa lebo inayotaka na kuiongeza katika SQLite.

Hili linaweza kuitwa toleo la pili: mkusanyiko wa makumi ya maelfu ya URL kwenye jedwali la SQLite, ambalo lilichukua nafasi ya orodha tuli katika HTML. Nilifanya utafutaji rahisi kwenye orodha hii. Kwa sababu kulikuwa na URL pekee, basi utafutaji ulitegemea tu.

Katika hatua hii niliacha mradi huo na nikarudi baada ya muda mrefu. Katika hatua hii, uzoefu wangu wa kazi ulikuwa tayari zaidi ya miaka mitatu na nilihisi kuwa naweza kufanya jambo zito zaidi. Kwa kuongezea, kulikuwa na hamu kubwa ya kujua teknolojia mpya.

Toleo la kisasa

Mradi iliyotumwa katika Docker, hifadhidata ilihamishiwa kwa mongoDb, na hivi majuzi, radish iliongezwa, ambayo mwanzoni ilikuwa ya kuakibisha tu. Mojawapo ya mifumo midogo ya PHP inatumika kama msingi.

tatizo

Tovuti mpya zinaongezwa na amri ya koni ambayo hufanya yafuatayo kwa usawa:

  • Inapakua maudhui kulingana na URL
  • Huweka bendera inayoonyesha kama HTTPS inapatikana
  • Inahifadhi kiini cha tovuti
  • Chanzo cha HTML na vichwa vimehifadhiwa katika historia ya "index".
  • Huchanganua maudhui, dondoo za Kichwa na Maelezo
  • Huhifadhi data kwenye mkusanyiko tofauti

Hii ilitosha tu kuhifadhi tovuti na kuzionyesha kwenye orodha:

Kuhamisha maandishi ya nyuma ya PHP kwa basi ya mitiririko ya Redis na kuchagua maktaba inayojitegemea.

Lakini wazo la kuorodhesha kiotomatiki, kuainisha na kuorodhesha kila kitu, kusasisha kila kitu, halikufaa vizuri katika dhana hii. Hata kwa kuongeza tu mbinu ya wavuti ili kuongeza kurasa zinazohitajika kurudia msimbo na kuzuia ili kuzuia uwezekano wa DDoS.

Kwa ujumla, kwa kweli, kila kitu kinaweza kufanywa kwa usawa, na kwa njia ya wavuti unaweza kuhifadhi tu URL ili daemon ya kutisha ifanye kazi zote za URL kutoka kwenye orodha. Lakini bado, hata hapa neno "foleni" linajipendekeza. Na ikiwa foleni inatekelezwa, basi kazi zote zinaweza kugawanywa na kufanywa angalau asynchronously.

uamuzi

Tekeleza foleni na utengeneze mfumo unaoendeshwa na tukio wa kuchakata kazi zote. Na nimekuwa nikitaka kujaribu Mitiririko ya Redis kwa muda mrefu.

Kutumia mitiririko ya Redis katika PHP

Kwa sababu Kwa kuwa mfumo wangu sio mojawapo ya majitu matatu ya Symfony, Laravel, Yii, ningependa kupata maktaba inayojitegemea. Lakini, kama ilivyotokea (kwenye uchunguzi wa kwanza), haiwezekani kupata maktaba kubwa ya mtu binafsi. Kila kitu kinachohusiana na foleni ni mradi kutoka kwa kazi 3 miaka mitano iliyopita, au inahusishwa na mfumo.

Nimesikia mengi kuhusu Symfony kama mtoaji wa vifaa muhimu vya mtu binafsi, na tayari ninatumia baadhi yao. Na pia vitu vingine kutoka kwa Laravel vinaweza pia kutumika, kwa mfano ORM yao, bila uwepo wa mfumo yenyewe.

symfony/messenger

Mgombea wa kwanza mara moja alionekana kuwa bora na bila shaka yoyote niliisakinisha. Lakini iligeuka kuwa ngumu zaidi kutumia mifano ya google nje ya Symfony. Jinsi ya kukusanyika kutoka kwa kundi la madarasa na majina ya ulimwengu, yasiyo na maana, basi ya kupitisha ujumbe, na hata kwenye Redis?

Kuhamisha maandishi ya nyuma ya PHP kwa basi ya mitiririko ya Redis na kuchagua maktaba inayojitegemea.

Hati kwenye tovuti rasmi ilikuwa ya kina kabisa, lakini uanzishaji ulielezewa tu kwa Symfony kwa kutumia YML wanayoipenda zaidi na mbinu zingine za kichawi kwa yule ambaye sio mwimbaji. Sikuwa na nia ya mchakato wa ufungaji yenyewe, hasa wakati wa likizo ya Mwaka Mpya. Lakini ilibidi nifanye hivi kwa muda mrefu bila kutarajia.

Kujaribu kujua jinsi ya kusisitiza mfumo kwa kutumia vyanzo vya Symfony pia sio kazi ndogo sana kwa tarehe ya mwisho ngumu:

Kuhamisha maandishi ya nyuma ya PHP kwa basi ya mitiririko ya Redis na kuchagua maktaba inayojitegemea.

Baada ya kuzama katika haya yote na kujaribu kufanya kitu kwa mikono yangu, nilifikia hitimisho kwamba nilikuwa nikifanya aina fulani ya viboko na niliamua kujaribu kitu kingine.

iliyoangaziwa/foleni

Ilibainika kuwa maktaba hii ilikuwa imefungwa sana kwa miundombinu ya Laravel na rundo la utegemezi mwingine, kwa hivyo sikutumia muda mwingi juu yake: niliiweka, nikaitazama, nikaona utegemezi na kuifuta.

yiisoft/yii2-foleni

Naam, hapa ilichukuliwa mara moja kutoka kwa jina, tena, uhusiano mkali na Yii2. Ilinibidi kutumia maktaba hii na haikuwa mbaya, lakini sikufikiria juu ya ukweli kwamba inategemea kabisa Yii2.

Wengine wote

Kila kitu kingine ambacho nilipata kwenye GitHub havikuwa vya kuaminika, vya zamani na vilivyoachwa bila nyota, uma na idadi kubwa ya ahadi.

Rudi kwa symfony/messenger, maelezo ya kiufundi

Ilinibidi kufikiria maktaba hii na, baada ya kutumia muda zaidi, niliweza. Ilibadilika kuwa kila kitu kilikuwa kifupi na rahisi. Ili kulazimisha basi, nilitengeneza kiwanda kidogo, kwa sababu ... Nilitakiwa kuwa na matairi kadhaa na washikaji tofauti.

Kuhamisha maandishi ya nyuma ya PHP kwa basi ya mitiririko ya Redis na kuchagua maktaba inayojitegemea.

Hatua chache tu:

  • Tunaunda vidhibiti vya ujumbe ambavyo vinapaswa kupigwa kwa urahisi
  • Tunazifunga kwa HandlerDescriptor (darasa kutoka kwa maktaba)
  • Tunafunga "Maelezo" haya kwa mfano wa HandlersLocator
  • Kuongeza HandlersLocator kwa mfano wa MessageBus
  • Tunapitisha seti ya `SenderInterface` kwa SendersLocator, katika kesi yangu ya madarasa ya `RedisTransport`, ambayo yamesanidiwa kwa njia dhahiri.
  • Kuongeza SendersLocator kwa mfano wa MessageBus

MessageBus ina mbinu ya `->dispatch()` inayotafuta vishikilizi vinavyofaa katika HandlersLocator na kupitisha ujumbe kwao, kwa kutumia `SenderInterface` inayolingana kutuma kupitia basi (Redis mitiririko).

Katika usanidi wa chombo (katika kesi hii php-di), kifungu hiki kizima kinaweza kusanidiwa kama hii:

        CONTAINER_REDIS_TRANSPORT_SECRET => function (ContainerInterface $c) {
            return new RedisTransport(
                $c->get(CONTAINER_REDIS_STREAM_CONNECTION_SECRET),
                $c->get(CONTAINER_SERIALIZER))
            ;
        },
        CONTAINER_REDIS_TRANSPORT_LOG => function (ContainerInterface $c) {
            return new RedisTransport(
                $c->get(CONTAINER_REDIS_STREAM_CONNECTION_LOG),
                $c->get(CONTAINER_SERIALIZER))
            ;
        },
        CONTAINER_REDIS_STREAM_RECEIVER_SECRET => function (ContainerInterface $c) {
            return new RedisReceiver(
                $c->get(CONTAINER_REDIS_STREAM_CONNECTION_SECRET),
                $c->get(CONTAINER_SERIALIZER)
            );
        },
        CONTAINER_REDIS_STREAM_RECEIVER_LOG => function (ContainerInterface $c) {
            return new RedisReceiver(
                $c->get(CONTAINER_REDIS_STREAM_CONNECTION_LOG),
                $c->get(CONTAINER_SERIALIZER)
            );
        },
        CONTAINER_REDIS_STREAM_BUS => function (ContainerInterface $c) {
            $sendersLocator = new SendersLocator([
                AppMessagesSecretJsonMessages::class => [CONTAINER_REDIS_TRANSPORT_SECRET],
                AppMessagesDaemonLogMessage::class => [CONTAINER_REDIS_TRANSPORT_LOG],
            ], $c);
            $middleware[] = new SendMessageMiddleware($sendersLocator);

            return new MessageBus($middleware);
        },
        CONTAINER_REDIS_STREAM_CONNECTION_SECRET => function (ContainerInterface $c) {
            $host = 'bu-02-redis';
            $port = 6379;
            $dsn = "redis://$host:$port";
            $options = [
                'stream' => 'secret',
                'group' => 'default',
                'consumer' => 'default',
            ];

            return Connection::fromDsn($dsn, $options);
        },
        CONTAINER_REDIS_STREAM_CONNECTION_LOG => function (ContainerInterface $c) {
            $host = 'bu-02-redis';
            $port = 6379;
            $dsn = "redis://$host:$port";
            $options = [
                'stream' => 'log',
                'group' => 'default',
                'consumer' => 'default',
            ];

            return Connection::fromDsn($dsn, $options);
        },

Hapa unaweza kuona kwamba katika SendersLocator tumegawa "usafiri" tofauti kwa ujumbe mbili tofauti, ambayo kila moja ina muunganisho wake kwa mitiririko inayolingana.

Nilifanya mradi tofauti wa onyesho unaoonyesha matumizi ya damoni tatu zinazowasiliana kwa kutumia basi lifuatalo: https://github.com/backend-university/products/tree/master/products/02-redis-streams-bus.

Lakini nitakuonyesha jinsi mtumiaji anaweza kuunda:

use AppMessagesDaemonLogMessage;
use SymfonyComponentMessengerHandlerHandlerDescriptor;
use SymfonyComponentMessengerHandlerHandlersLocator;
use SymfonyComponentMessengerMessageBus;
use SymfonyComponentMessengerMiddlewareHandleMessageMiddleware;
use SymfonyComponentMessengerMiddlewareSendMessageMiddleware;
use SymfonyComponentMessengerTransportSenderSendersLocator;

require_once __DIR__ . '/../vendor/autoload.php';
/** @var PsrContainerContainerInterface $container */
$container = require_once('config/container.php');

$handlers = [
    DaemonLogMessage::class => [
        new HandlerDescriptor(
            function (DaemonLogMessage $m) {
                error_log('DaemonLogHandler: message handled: / ' . $m->getMessage());
            },
            ['from_transport' => CONTAINER_REDIS_TRANSPORT_LOG]
        )
    ],
];
$middleware = [];
$middleware[] = new HandleMessageMiddleware(new HandlersLocator($handlers));
$sendersLocator = new SendersLocator(['*' => [CONTAINER_REDIS_TRANSPORT_LOG]], $container);
$middleware[] = new SendMessageMiddleware($sendersLocator);

$bus = new MessageBus($middleware);
$receivers = [
    CONTAINER_REDIS_TRANSPORT_LOG => $container->get(CONTAINER_REDIS_STREAM_RECEIVER_LOG),
];
$w = new SymfonyComponentMessengerWorker($receivers, $bus, $container->get(CONTAINER_EVENT_DISPATCHER));
$w->run();

Kutumia miundombinu hii katika programu

Baada ya kutekeleza basi katika sehemu yangu ya nyuma, nilitenganisha hatua za mtu binafsi kutoka kwa amri ya zamani ya kusawazisha na kutengeneza washughulikiaji tofauti, ambao kila mmoja hufanya mambo yake.

Njia ya kuongeza tovuti mpya kwenye hifadhidata ilionekana kama hii:

Kuhamisha maandishi ya nyuma ya PHP kwa basi ya mitiririko ya Redis na kuchagua maktaba inayojitegemea.

Na mara baada ya hapo, ikawa rahisi kwangu kuongeza utendaji mpya, kwa mfano, kutoa na kuchambua Rs. Kwa sababu mchakato huu pia unahitaji maudhui asili, kisha kidhibiti cha kiungo cha RSS, kama vile WebsiteIndexHistoryPersistor, hujiandikisha kupokea ujumbe wa "Maudhui/HtmlContent", kuuchakata na kupitisha ujumbe unaohitajika kwenye mkondo wake zaidi.

Kuhamisha maandishi ya nyuma ya PHP kwa basi ya mitiririko ya Redis na kuchagua maktaba inayojitegemea.

Mwishowe, tuliishia na daemoni kadhaa, ambayo kila moja hudumisha miunganisho kwa rasilimali muhimu tu. Kwa mfano pepo watambaaji ina vidhibiti vyote vinavyohitaji kwenda kwenye Mtandao kwa maudhui, na daemon kuendelea inashikilia muunganisho kwenye hifadhidata.

Sasa, badala ya kuchagua kutoka kwa hifadhidata, vitambulisho vinavyohitajika baada ya kuingizwa na kiendelezi hupitishwa kupitia basi kwa washikaji wote wanaovutiwa.

Chanzo: mapenzi.com

Kuongeza maoni