Mindahkeun backend PHP kana beus aliran Redis sareng milih perpustakaan mandiri kerangka

Mindahkeun backend PHP kana beus aliran Redis sareng milih perpustakaan mandiri kerangka

foreword

Website abdi, nu kuring ngajalankeun salaku hobi, dirancang pikeun host kaca imah metot jeung situs pribadi. Topik ieu mimiti dipikaresep ku kuring di awal perjalanan program kuring; dina waktos éta kuring kagum ku milarian profésional hébat anu nyerat ngeunaan diri, hobi sareng proyék na. Kabiasaan pikeun mendakanana sorangan tetep dugi ka ayeuna: dina ampir unggal situs komérsial sareng henteu pisan komérsial, kuring teras-terasan milarian dina footer pikeun milarian tautan ka pangarang.

Palaksanaan gagasan

Versi kahiji éta ngan hiji kaca html dina ramatloka pribadi kuring, dimana kuring nempatkeun Tumbu kalawan tanda tangan kana daptar ul. Saatos ngetik 20 halaman dina sababaraha waktos, kuring mimiti mikir yén ieu henteu efektif pisan sareng mutuskeun pikeun nyobian ngajadikeun otomatis prosésna. Dina stackoverflow, kuring perhatikeun yén seueur jalma nunjukkeun situs dina propilna, janten kuring nyerat parser dina php, anu ngan saukur ngaliwat propil, dimimitian ku anu munggaran (alamat dina SO dugi ka ayeuna sapertos kieu: `/users/1` ), sasari Tumbu ti tag nu dipikahoyong tur ditambahkeun kana SQLite.

Ieu tiasa disebat versi kadua: kumpulan puluhan rébu URL dina tabel SQLite, anu ngagentos daptar statik dina html. Kuring ngalakukeun hiji pilarian basajan dina daptar ieu. Sabab ngan aya URL, teras milarian ngan ukur dumasar kana éta.

Dina tahap ieu kuring ngantunkeun proyék sareng uih deui saatos lami. Dina tahap ieu, pangalaman damel abdi parantos langkung ti tilu taun sareng kuring ngarasa yén kuring tiasa ngalakukeun anu langkung serius. Sajaba ti éta, aya kahayang hébat ngawasaan téknologi rélatif anyar.

Vérsi modern

proyek deployed di Docker, database ditransferkeun ka mongoDb, sarta leuwih anyar, lobak ditambahkeun, nu mimitina ngan keur cache. Salah sahiji microframeworks PHP dipaké salaku dadasar.

masalah

Situs anyar ditambah ku paréntah konsol anu sakaligus ngalakukeun ieu:

  • Ngundeur eusi ku URL
  • Nyetél bandéra anu nunjukkeun naha HTTPS sayogi
  • Preserves hakekat ramatloka
  • Sumber HTML sareng header disimpen dina sajarah "indexing".
  • Parses eusi, extracts Judul jeung Pedaran
  • Nyimpen data ka kumpulan misah

Ieu cukup pikeun nyimpen situs sareng nampilkeunana dina daptar:

Mindahkeun backend PHP kana beus aliran Redis sareng milih perpustakaan mandiri kerangka

Tapi ideu sacara otomatis ngindeks, ngagolongkeun sareng ngémutan sadayana, ngajaga sadayana énggal-énggal, henteu pas kana paradigma ieu. Malah ngan saukur nambahkeun metoda web pikeun nambahkeun kaca diperlukeun duplikasi kode jeung blocking pikeun nyegah DDoS poténsial.

Sacara umum, tangtosna, sadayana tiasa dilakukeun sacara sinkron, sareng dina metode wéb anjeun ngan saukur tiasa nyimpen URL supados daemon monstrous ngalaksanakeun sadaya tugas pikeun URL tina daptar. Tapi tetep, sanajan di dieu kecap "antrian" nunjukkeun sorangan. Sareng upami antrian dilaksanakeun, maka sadaya pancén tiasa dibagi sareng dilaksanakeun sahenteuna asynchronously.

kaputusan

Ngalaksanakeun antrian sareng ngadamel sistem anu didorong ku acara pikeun ngolah sadaya tugas. Sareng kuring parantos lami nyobian Redis Streams.

Ngagunakeun aliran Redis dina PHP

Sabab Kusabab kerangka abdi sanes salah sahiji tilu raksasa Symfony, Laravel, Yii, Abdi hoyong manggihan perpustakaan bebas. Tapi, sakumaha tétéla (dina ujian kahiji), mustahil pikeun manggihan perpustakaan serius individu. Sagalana patali antrian boh mangrupa proyék ti 3 commits lima taun ka tukang, atawa dihijikeun ka kerangka.

Kuring geus kadéngé loba ngeunaan Symfony salaku supplier komponén mangpaat individu, sarta kuring geus ngagunakeun sababaraha di antarana. Sarta ogé sababaraha hal ti Laravel ogé bisa dipaké, contona ORM maranéhna, tanpa ayana kerangka sorangan.

symfony / utusan

Calon kahiji langsung sigana idéal sareng tanpa ragu kuring dipasang. Tapi tétéla jadi leuwih hese google conto pamakéan luar Symfony. Kumaha carana ngumpul beus pikeun ngirimkeun pesen ti sakumpulan kelas kalayan nami universal, henteu aya artina, bahkan dina Redis?

Mindahkeun backend PHP kana beus aliran Redis sareng milih perpustakaan mandiri kerangka

Dokuméntasi dina situs resmi éta rada lengkep, tapi initialization ieu ngan dijelaskeun pikeun Symfony ngagunakeun YML favorit maranéhanana jeung métode magic séjén pikeun non-symphonist. Kuring teu boga minat dina prosés instalasi sorangan, utamana dina mangsa libur Taun Anyar. Tapi kuring kedah ngalakukeun ieu kanggo waktos anu teu disangka-sangka.

Nyobian terangkeun kumaha cara instantiate sistem nganggo sumber Symfony ogé sanés tugas anu paling sepele pikeun wates waktu anu ketat:

Mindahkeun backend PHP kana beus aliran Redis sareng milih perpustakaan mandiri kerangka

Saatos delving kana sagala ieu sareng nyobian ngalakukeun hiji hal kalawan leungeun kuring, Kuring sumping ka kacindekan yen kuring ngalakukeun sababaraha jenis crutches sarta mutuskeun pikeun nyobaan hal sejenna.

cahayana / antrian

Tétéla yén perpustakaan ieu caket pisan kana infrastruktur Laravel sareng sakumpulan katergantungan anu sanés, janten kuring henteu nyéépkeun waktosna: Kuring dipasang, ningali éta, ningali katergantungan sareng ngahapus.

yiisoft / yii2-antrian

Nya, di dieu éta langsung dianggap tina nami, deui, sambungan anu ketat ka Yii2. Kuring kungsi ngagunakeun perpustakaan ieu teu goréng, tapi kuring teu mikir ngeunaan kanyataan yén éta sagemblengna gumantung Yii2.

Sésana

Sagalana sejenna nu kuring kapanggih dina GitHub éta unreliable, proyék luntur sarta ditinggalkeun tanpa béntang, garpu jeung sajumlah badag commits.

Balik deui ka symfony / messenger, rinci teknis

Kuring kedah terang perpustakaan ieu sareng, saatos nyéépkeun waktos deui, kuring tiasa. Tétéla yén sagalana éta rada singket tur basajan. Pikeun instantiate beus, kuring nyieun pabrik leutik, sabab ... Abdi kedah gaduh sababaraha ban sareng panangan anu béda.

Mindahkeun backend PHP kana beus aliran Redis sareng milih perpustakaan mandiri kerangka

Ngan sababaraha léngkah:

  • Urang nyieun pawang pesen nu kedah saukur callable
  • Urang bungkus aranjeunna dina HandlerDescriptor (kelas ti perpustakaan)
  • Urang bungkus ieu "Descriptors" dina conto HandlersLocator
  • Nambahkeun HandlersLocator kana conto MessageBus
  • Urang lulus sakumpulan `SenderInterface` ka SendersLocator, dina kasus kuring tina kelas `RedisTransport`, anu dikonpigurasi dina cara anu jelas.
  • Nambahkeun SendersLocator kana conto MessageBus

MessageBus ngabogaan `-> dispatch ()` métode nu kasampak up pawang luyu dina HandlersLocator tur ngalirkeun pesen ka aranjeunna, ngagunakeun `SenderInterface` pakait pikeun ngirim via beus (Redis aliran).

Dina konfigurasi wadahna (dina hal ieu php-di), sakabéh kebat ieu tiasa dikonpigurasikeun sapertos kieu:

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

Di dieu anjeun bisa nempo yén di SendersLocator kami geus ditugaskeun béda "transportasi" pikeun dua pesen béda, nu masing-masing boga sambungan sorangan ka aliran pakait.

Kuring ngadamel proyék demo anu misah anu nunjukkeun aplikasi tilu daemon anu saling komunikasi nganggo beus ieu: https://github.com/backend-university/products/tree/master/products/02-redis-streams-bus.

Tapi kuring bakal nunjukkeun anjeun kumaha konsumen tiasa terstruktur:

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

Ngagunakeun infrastruktur ieu dina hiji aplikasi

Saatos ngalaksanakeun beus di backend kuring, kuring misahkeun tahapan individu tina paréntah sinkron kuno sareng ngadamel pawang anu misah, masing-masing ngalakukeun hal sorangan.

Jalur pipa pikeun nambihan situs énggal kana pangkalan data sapertos kieu:

Mindahkeun backend PHP kana beus aliran Redis sareng milih perpustakaan mandiri kerangka

Sareng saatos éta, janten langkung gampang pikeun kuring nambihan fungsionalitas énggal, contona, ékstrak sareng parsing Rss. Sabab prosés ieu ogé merlukeun eusi aslina, lajeng RSS link extractor Handler, kawas WebsiteIndexHistoryPersistor, subscribes kana "Kandungan / HtmlContent" pesen, prosés eta sarta ngalirkeun pesen nu dipikahoyong sapanjang pipa na salajengna.

Mindahkeun backend PHP kana beus aliran Redis sareng milih perpustakaan mandiri kerangka

Tungtungna, urang réngsé kalawan sababaraha daemons, nu masing-masing mertahankeun sambungan ukur kana sumberdaya diperlukeun. Contona sétan gagang ngandung sakabéh pawang nu merlukeun bade Internet pikeun eusi, sarta daemon keukeuh nahan sambungan kana database.

Ayeuna, tinimbang milih tina pangkalan data, id anu diperyogikeun saatos diselapkeun ku persister ngan saukur dikirimkeun via beus ka sadaya pawang anu kabetot.

sumber: www.habr.com

Tambahkeun komentar