It-trasferiment tal-backend PHP lejn ix-xarabank tal-flussi Redis u l-għażla ta 'librerija indipendenti mill-qafas

It-trasferiment tal-backend PHP lejn ix-xarabank tal-flussi Redis u l-għażla ta 'librerija indipendenti mill-qafas

Daħla

Il-websajt tiegħi, li nmexxi bħala passatemp, hija mfassla biex tospita home pages interessanti u siti personali. Dan is-suġġett beda jinteressani fil-bidu nett tal-vjaġġ tiegħi ta’ programmazzjoni; f’dak il-mument kont affaxxinat billi nsib professjonisti mill-aqwa li jiktbu dwarhom infushom, dwar il-passatempi u l-proġetti tagħhom. Il-vizzju li niskoprihom għalija nnifsi għadu sal-lum: fuq kważi kull sit kummerċjali u mhux kummerċjali ħafna, inkompli nfittex fil-footer fit-tfittxija ta 'links għall-awturi.

Implimentazzjoni tal-idea

L-ewwel verżjoni kienet biss paġna html fuq il-websajt personali tiegħi, fejn poġġejt links bil-firem f'lista ul. Wara li ttajpjat 20 paġna fuq perjodu ta 'żmien, bdejt naħseb li dan ma kienx effettiv ħafna u ddeċidejt li nipprova awtomat il-proċess. Fuq stackoverflow, ndunajt li ħafna nies jindikaw siti fil-profili tagħhom, għalhekk ktibt parser f'php, li sempliċement għadda mill-profili, ibda mill-ewwel (indirizzi fuq SO sal-lum huma bħal dan: `/users/1` ), estratt links mit-tikketta mixtieqa u żiedha f'SQLite.

Din tista 'tissejjaħ it-tieni verżjoni: ġabra ta' għexieren ta 'eluf ta' URL f'tabella SQLite, li ssostitwiet il-lista statika f'HTML. Għamilt tfittxija sempliċi fuq din il-lista. Għax kien hemm biss URLs, allura t-tfittxija kienet sempliċement ibbażata fuqhom.

F'dan l-istadju abbandunajt il-proġett u rritornajt għalih wara żmien twil. F'dan l-istadju, l-esperjenza tax-xogħol tiegħi kienet diġà ta' aktar minn tliet snin u ħassejt li stajt nagħmel xi ħaġa aktar serja. Barra minn hekk, kien hemm xewqa kbira li tikkontrolla teknoloġiji relattivament ġodda.

Verżjoni moderna

Proġett skjerat f'Docker, id-database ġiet trasferita għal mongoDb, u aktar reċentement, ġie miżjud ir-ravanell, li għall-ewwel kien biss għall-caching. Wieħed mill-mikroframeworks PHP jintuża bħala bażi.

problema

Siti ġodda huma miżjuda minn kmand tal-console li b'mod sinkroniku jagħmel dan li ġej:

  • Jniżżel il-kontenut mill-URL
  • Issettja bandiera li tindika jekk HTTPS kienx disponibbli
  • Jippreserva l-essenza tal-websajt
  • L-HTML tas-sors u l-headers huma ssejvjati fl-istorja ta '"indiċjar".
  • Teżamina l-kontenut, estratti Titolu u Deskrizzjoni
  • Tissejvja d-dejta f'ġabra separata

Dan kien biżżejjed biex sempliċement taħżen is-siti u turihom f'lista:

It-trasferiment tal-backend PHP lejn ix-xarabank tal-flussi Redis u l-għażla ta 'librerija indipendenti mill-qafas

Iżda l-idea li awtomatikament jiġi indiċjat, kategorizzat u klassifikat kollox, li jżomm kollox aġġornat, ma kinitx tidħol sew f'din il-paradigma. Anke sempliċement iż-żieda ta 'metodu tal-web biex iżżid paġni kienet teħtieġ duplikazzjoni tal-kodiċi u imblukkar biex tevita DDoS potenzjali.

B'mod ġenerali, ovvjament, kollox jista 'jsir b'mod sinkroniku, u fil-metodu tal-web tista' sempliċement issalva l-URL sabiex id-daemon monstrous iwettaq il-kompiti kollha għall-URLs mil-lista. Iżda xorta waħda, anke hawn il-kelma "kju" tissuġġerixxi lilha nnifisha. U jekk kju jiġi implimentat, allura l-kompiti kollha jistgħu jinqasmu u jitwettqu mill-inqas b'mod mhux sinkroniku.

deċiżjoni

Implimenta kjuwijiet u agħmel sistema mmexxija mill-avvenimenti għall-ipproċessar tal-kompiti kollha. U kont ilni nixtieq nipprova Redis Streams.

L-użu ta 'flussi ta' Redis f'PHP

Għax Peress li l-qafas tiegħi mhuwiex wieħed mit-tliet ġganti Symfony, Laravel, Yii, nixtieq insib librerija indipendenti. Iżda, kif irriżulta (fl-ewwel eżami), huwa impossibbli li ssib libreriji serji individwali. Dak kollu relatat mal-kjuwijiet huwa jew proġett minn 3 commits ħames snin ilu, jew huwa marbut mal-qafas.

Smajt ħafna dwar Symfony bħala fornitur ta 'komponenti individwali utli, u diġà nuża xi wħud minnhom. U wkoll xi affarijiet minn Laravel jistgħu jintużaw ukoll, pereżempju l-ORM tagħhom, mingħajr il-preżenza tal-qafas innifsu.

symfony/messenger

L-ewwel kandidat mill-ewwel deher ideali u bla ebda dubju installajtha. Iżda rriżulta li kien aktar diffiċli biex google eżempji ta 'użu barra minn Symfony. Kif tiġbor minn mazz ta 'klassijiet b'ismijiet universali, bla sens, xarabank biex tgħaddi l-messaġġi, u anke fuq Redis?

It-trasferiment tal-backend PHP lejn ix-xarabank tal-flussi Redis u l-għażla ta 'librerija indipendenti mill-qafas

Id-dokumentazzjoni fuq is-sit uffiċjali kienet pjuttost dettaljata, iżda l-inizjalizzazzjoni kienet deskritta biss għal Symfony bl-użu YML favorit tagħhom u metodi maġiċi oħra għan-non-symphonist. Ma kelli l-ebda interess fil-proċess ta 'installazzjoni innifsu, speċjalment waqt il-vaganzi tas-Sena l-Ġdida. Imma kelli nagħmel dan għal żmien twil mhux mistenni.

Li tipprova ssib kif tistjanzja sistema bl-użu ta' sorsi ta' Symfony mhijiex ukoll l-aktar biċċa xogħol trivjali għal skadenza stretta:

It-trasferiment tal-backend PHP lejn ix-xarabank tal-flussi Redis u l-għażla ta 'librerija indipendenti mill-qafas

Wara li dħalt f’dan kollu u ppruvajt nagħmel xi ħaġa b’idi, wasalt għall-konklużjoni li kont qed nagħmel xi tip ta’ krozzi u ddeċidejt li nipprova xi ħaġa oħra.

illuminati/kju

Irriżulta li din il-librerija kienet marbuta sew mal-infrastruttura ta 'Laravel u mazz ta' dipendenzi oħra, għalhekk ma qattajtx ħafna ħin fuqha: installajtha, ħarist lejha, ​​rajt id-dipendenzi u ħassejtha.

yiisoft/yii2-queue

Ukoll, hawnhekk kien immedjatament preżunt mill-isem, għal darb'oħra, konnessjoni stretta ma 'Yii2. Kelli nuża din il-librerija u ma kinitx ħażina, imma ma ħsibtx dwar il-fatt li tiddependi kompletament fuq Yii2.

Il-bqija

Kull ħaġa oħra li sibt fuq GitHub kienu proġetti mhux affidabbli, skaduti u abbandunati mingħajr stilel, frieket u numru kbir ta 'commits.

Ritorn għal symfony/messenger, dettalji tekniċi

Kelli nifhem din il-librerija u, wara li qattajt ftit aktar ħin, stajt. Irriżulta li kollox kien pjuttost konċiż u sempliċi. Biex nipprova l-karozza tal-linja, għamilt fabbrika żgħira, għax... Suppost kelli diversi tyres u bi handlers differenti.

It-trasferiment tal-backend PHP lejn ix-xarabank tal-flussi Redis u l-għażla ta 'librerija indipendenti mill-qafas

Ftit passi biss:

  • Aħna noħolqu messaġġi li jimmaniġġjaw li għandhom ikunu sempliċiment sejħa
  • Aħna nagħlaqhom f'HandlerDescriptor (klassi mil-librerija)
  • Aħna nagħlaq dawn id-“Deskritturi” f’istanza ta’ HandlersLocator
  • Żieda ta' HandlersLocator mal-istanza MessageBus
  • Aħna ngħaddu sett ta ''SenderInterface' lil SendersLocator, fil-każ tiegħi każijiet ta' klassijiet 'RedisTransport', li huma kkonfigurati b'mod ovvju
  • Żieda ta' SendersLocator mal-istanza MessageBus

MessageBus għandu metodu `->dispatch()` li jfittex il-handlers xierqa fil-HandlersLocator u jgħaddilhom il-messaġġ, billi juża l-'SenderInterface' korrispondenti biex jibgħat permezz tax-xarabank (Redis streams).

Fil-konfigurazzjoni tal-kontenitur (f'dan il-każ php-di), dan il-pakkett kollu jista 'jiġi kkonfigurat hekk:

        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);
        },

Hawnhekk tista 'tara li f'SendersLocator aħna assenjati "trasporti" differenti għal żewġ messaġġi differenti, li kull wieħed minnhom għandu l-konnessjoni tiegħu mal-flussi korrispondenti.

Għamilt proġett demo separat li juri applikazzjoni ta 'tliet daemons li jikkomunikaw ma' xulxin bl-użu tax-xarabank li ġej: https://github.com/backend-university/products/tree/master/products/02-redis-streams-bus.

Imma ser nuruk kif konsumatur jista' jiġi strutturat:

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();

Uża din l-infrastruttura f'applikazzjoni

Wara li implimentajt ix-xarabank fil-backend tiegħi, isseparat stadji individwali mill-kmand sinkroniku l-antik u għamilt handlers separati, li kull wieħed minnhom jagħmel l-ħaġa tiegħu.

Il-pipeline għaż-żieda ta' sit ġdid fid-database kien jidher bħal dan:

It-trasferiment tal-backend PHP lejn ix-xarabank tal-flussi Redis u l-għażla ta 'librerija indipendenti mill-qafas

U immedjatament wara dan, sar ħafna aktar faċli għalija li nżid funzjonalità ġdida, per eżempju, estrazzjoni u parsing Rss. Għax dan il-proċess jeħtieġ ukoll il-kontenut oriġinali, allura l-immaniġġjar tal-estrattur tal-link RSS, bħal WebsiteIndexHistoryPersistor, jissottoskrivi għall-messaġġ "Kontenut/HtmlContent", jipproċessah u jgħaddi l-messaġġ mixtieq tul il-pipeline tiegħu aktar.

It-trasferiment tal-backend PHP lejn ix-xarabank tal-flussi Redis u l-għażla ta 'librerija indipendenti mill-qafas

Fl-aħħar, spiċċajna b'diversi daemons, li kull wieħed minnhom iżomm konnessjonijiet biss mar-riżorsi meħtieġa. Per eżempju dimostrazzjoni crawlers fih il-handlers kollha li jeħtieġu li jmorru l-Internet għall-kontenut, u d-daemon jippersistu ikollu konnessjoni mad-database.

Issa, minflok ma jintgħażlu mid-database, l-ids meħtieġa wara l-inserzjoni mill-persistent huma sempliċement trażmessi permezz tax-xarabank lill-handlers kollha interessati.

Sors: www.habr.com

Żid kumment