PHP පසුපෙළ Redis streams බසයට මාරු කිරීම සහ රාමු-ස්වාධීන පුස්තකාලයක් තෝරා ගැනීම

PHP පසුපෙළ Redis streams බසයට මාරු කිරීම සහ රාමු-ස්වාධීන පුස්තකාලයක් තෝරා ගැනීම

පෙරවදන

මම විනෝදාංශයක් ලෙස පවත්වාගෙන යන මගේ වෙබ් අඩවිය, රසවත් මුල් පිටු සහ පුද්ගලික අඩවි සත්කාරකත්වය සැපයීමට නිර්මාණය කර ඇත. මෙම මාතෘකාව මගේ ක්‍රමලේඛන ගමනේ ආරම්භයේදීම මා උනන්දු වීමට පටන් ගත්තේය; ඒ මොහොතේම මම තමන් ගැන, ඔවුන්ගේ විනෝදාංශ සහ ව්‍යාපෘති ගැන ලියන විශිෂ්ට වෘත්තිකයන් සොයා ගැනීම ගැන උනන්දු විය. ඒවා මා විසින්ම සොයා ගැනීමේ පුරුද්ද අද දක්වාම පවතී: සෑම වාණිජමය හා ඉතා වාණිජ නොවන වෙබ් අඩවියකම පාහේ, මම කතුවරුන් වෙත සබැඳි සෙවීම සඳහා පාදකය දෙස බලමි.

අදහස ක්රියාත්මක කිරීම

පළමු අනුවාදය මගේ පුද්ගලික වෙබ් අඩවියේ html පිටුවක් පමණි, එහිදී මම ul ලැයිස්තුවකට අත්සන් සහිත සබැඳි තැබුවෙමි. කාලයක් තිස්සේ පිටු 20 ක් ටයිප් කර ඇති අතර, මෙය එතරම් ඵලදායී නොවන බව සිතීමට පටන් ගත් අතර ක්රියාවලිය ස්වයංක්රීය කිරීමට උත්සාහ කිරීමට තීරණය කළේය. ස්ටැක්ඕවර් ප්‍රවාහයේදී, බොහෝ අය ඔවුන්ගේ පැතිකඩවල අඩවි දක්වන බව මම දුටුවෙමි, එබැවින් මම php හි විග්‍රහයක් ලිවීය, එය සරලවම පැතිකඩ හරහා ගොස්, පළමු එකෙන් පටන් ගෙන (SO හි ලිපින අද දක්වා මේ ආකාරයට ය: `/users/1` ), අවශ්‍ය ටැගයෙන් සබැඳි උපුටා ගෙන එය SQLite වෙත එක් කරන ලදී.

මෙය දෙවන අනුවාදය ලෙස හැඳින්විය හැක: HTML හි ස්ථිතික ලැයිස්තුව ප්‍රතිස්ථාපනය කරන ලද SQLite වගුවක URL දස දහස් ගණනක එකතුවකි. මම මෙම ලැයිස්තුවේ සරල සෙවීමක් කළා. නිසා එහි තිබුණේ URL පමණි, එවිට සෙවීම හුදෙක් ඒවා මත පදනම් විය.

මෙම අදියරේදී මම ව්‍යාපෘතිය අතහැර දමා බොහෝ කාලයකට පසු නැවත එයට පැමිණියෙමි. මෙම අවස්ථාවෙහිදී, මගේ සේවා පළපුරුද්ද දැනටමත් වසර තුනකට වඩා වැඩි වූ අතර මට වඩා බැරෑරුම් දෙයක් කළ හැකි බව මට හැඟුණි. මීට අමතරව, සාපේක්ෂව නව තාක්ෂණයන් ප්රගුණ කිරීමට මහත් ආශාවක් විය.

නවීන අනුවාදය

ව්යාපෘති Docker හි යොදවා ඇති අතර, දත්ත සමුදාය mongoDb වෙත මාරු කරන ලදී, සහ වඩාත් මෑතකදී, රාබු එකතු කරන ලදී, එය මුලින් හැඹිලිගත කිරීම සඳහා විය. PHP microframeworks වලින් එකක් පදනමක් ලෙස භාවිතා කරයි.

ප්රශ්නය

පහත දැක්වෙන දේ සමමුහුර්තව සිදු කරන කොන්සෝල විධානයක් මඟින් නව අඩවි එකතු කරනු ලැබේ:

  • URL මගින් අන්තර්ගතය බාගන්න
  • HTTPS තිබේද යන්න දැක්වෙන ධජයක් සකසයි
  • වෙබ් අඩවියේ සාරය ආරක්ෂා කරයි
  • මූලාශ්‍ර HTML සහ ශීර්ෂයන් "සුචිගත කිරීමේ" ඉතිහාසය තුළ සුරකිනු ලැබේ
  • අන්තර්ගතය විග්‍රහ කරයි, මාතෘකාව සහ විස්තරය උපුටා ගනී
  • දත්ත වෙනම එකතුවකට සුරකියි

මෙය හුදෙක් අඩවි ගබඩා කර ඒවා ලැයිස්තුවක ප්‍රදර්ශනය කිරීමට ප්‍රමාණවත් විය:

PHP පසුපෙළ Redis streams බසයට මාරු කිරීම සහ රාමු-ස්වාධීන පුස්තකාලයක් තෝරා ගැනීම

නමුත් සෑම දෙයක්ම ස්වයංක්‍රීයව සුචිගත කිරීම, වර්ගීකරණය සහ ශ්‍රේණිගත කිරීම, සියල්ල යාවත්කාලීනව තබා ගැනීමේ අදහස මෙම සුසමාදර්ශයට හොඳින් නොගැලපේ. පිටු එක් කිරීමට වෙබ් ක්‍රමයක් එක් කිරීමට පවා අවශ්‍ය කේත අනුපිටපත් කිරීම සහ විභව DDoS වළක්වා ගැනීම සඳහා අවහිර කිරීම.

පොදුවේ ගත් කල, ඇත්ත වශයෙන්ම, සෑම දෙයක්ම සමමුහුර්තව සිදු කළ හැකි අතර, වෙබ් ක්‍රමයේදී ඔබට සරලවම URL සුරැකිය හැක, එවිට බිහිසුණු ඩීමන් ලැයිස්තුවේ ඇති URL සඳහා සියලුම කාර්යයන් ඉටු කරයි. නමුත් තවමත්, මෙහි පවා "පෝලිම්" යන වචනයම යෝජනා කරයි. පෝලිමක් ක්‍රියාත්මක කරන්නේ නම්, සියලුම කාර්යයන් බෙදිය හැකි අතර අවම වශයෙන් අසමමුහුර්තව සිදු කළ හැකිය.

තීරණය

පෝලිම් ක්‍රියාත්මක කිරීම සහ සියලු කාර්යයන් සැකසීම සඳහා සිදුවීම් මත පදනම් වූ පද්ධතියක් සාදන්න. ඒ වගේම මට දිගු කාලයක් තිස්සේ Redis Streams උත්සාහ කිරීමට අවශ්‍යයි.

PHP හි Redis streams භාවිතා කිරීම

නිසා මගේ රාමුව Symfony, Laravel, Yii යන දැවැන්තයන් තිදෙනාගෙන් එකක් නොවන බැවින්, ස්වාධීන පුස්තකාලයක් සොයා ගැනීමට මම කැමතියි. එහෙත්, එය සිදු වූ පරිදි (පළමු විභාගයේදී), තනි බරපතල පුස්තකාල සොයා ගැනීමට නොහැකි ය. පෝලිම් හා සම්බන්ධ සෑම දෙයක්ම වසර පහකට පෙර කැපවීම් 3 සිට ව්‍යාපෘතියකි, නැතහොත් රාමුවට බැඳී ඇත.

තනි ප්‍රයෝජනවත් සංරචක සැපයුම්කරුවෙකු ලෙස මම Symfony ගැන බොහෝ දේ අසා ඇති අතර මම දැනටමත් ඒවායින් සමහරක් භාවිතා කරමි. තවද Laravel වෙතින් සමහර දේවල් ද භාවිතා කළ හැකිය, උදාහරණයක් ලෙස ඔවුන්ගේ ORM, රාමුව නොමැතිව.

symfony/messenger

පළමු අපේක්ෂකයා වහාම පරමාදර්ශී වූ අතර කිසිදු සැකයකින් තොරව මම එය ස්ථාපනය කළෙමි. නමුත් Symfony වලින් පිටත භාවිතා කිරීම සඳහා ගූගල් උදාහරණ වඩා දුෂ්කර විය. විශ්වීය, අර්ථ විරහිත නම්, පණිවිඩ යැවීම සඳහා බස් රථයක් සහ Redis මත පවා පන්ති සමූහයකින් එකලස් කරන්නේ කෙසේද?

PHP පසුපෙළ Redis streams බසයට මාරු කිරීම සහ රාමු-ස්වාධීන පුස්තකාලයක් තෝරා ගැනීම

නිල වෙබ් අඩවියේ ලියකියවිලි තරමක් සවිස්තරාත්මක විය, නමුත් ආරම්භය විස්තර කර ඇත්තේ සිම්ෆොනි සඳහා ඔවුන්ගේ ප්‍රියතම YML සහ වෙනත් මැජික් ක්‍රම භාවිතා කරමින් සිම්ෆොනිස්ට් නොවන අය සඳහා පමණි. විශේෂයෙන්ම අලුත් අවුරුදු නිවාඩු කාලය තුළ ස්ථාපනය කිරීමේ ක්රියාවලිය ගැන මට උනන්දුවක් නොතිබුණි. ඒත් මට මේක කරන්න වුණේ අනපේක්ෂිත ලෙස දිගු කාලයක්.

Symfony මූලාශ්‍ර භාවිතයෙන් පද්ධතියක් ක්ෂණිකව ක්‍රියාත්මක කරන්නේ කෙසේදැයි සොයා බැලීමට උත්සාහ කිරීම ද දැඩි කාල සීමාවක් සඳහා ඉතා සුළු කාර්යයක් නොවේ:

PHP පසුපෙළ Redis streams බසයට මාරු කිරීම සහ රාමු-ස්වාධීන පුස්තකාලයක් තෝරා ගැනීම

මේ හැමදෙයක්ම හොයලා බලලා අත් දෙකෙන් මොනවා හරි කරන්න හැදුවට පස්සේ මම කිහිලිකරු වර්ගයක් කරනවා කියලා නිගමනයකට ඇවිත් තවත් දෙයක් අත්හදා බලන්න හිතුවා.

ආලෝකමත් / පෝලිම්

මෙම පුස්තකාලය Laravel යටිතල ව්‍යුහයට සහ වෙනත් පරායත්තතා සමූහයකට තදින් බැඳී ඇති බව පෙනී ගියේය, එබැවින් මම ඒ සඳහා වැඩි කාලයක් ගත නොකළෙමි: මම එය ස්ථාපනය කර, එය දෙස බලා, පරායත්තතා දැක එය මකා දැමුවෙමි.

yiisoft/yii2-පෝලිම

හොඳයි, මෙන්න එය වහාම නමෙන් උපකල්පනය කරන ලදී, නැවතත්, Yii2 වෙත දැඩි සම්බන්ධතාවයක්. මට මෙම පුස්තකාලය භාවිතා කිරීමට සිදු වූ අතර එය නරක නැත, නමුත් එය සම්පූර්ණයෙන්ම Yii2 මත රඳා පවතින බව මම සිතුවේ නැත.

ඉතිරිය

GitHub හි මා සොයාගත් අනෙක් සියල්ල විශ්වාස කළ නොහැකි, යල් පැන ගිය සහ තරු, ගෑරුප්පු සහ විශාල කැපවීම් නොමැතිව අතහැර දැමූ ව්‍යාපෘති විය.

symfony/messenger, තාක්ෂණික විස්තර වෙත ආපසු යන්න

මට මෙම පුස්තකාලය සොයා ගැනීමට සිදු වූ අතර, තවත් කාලයක් ගත කිරීමෙන් පසුව, මට හැකි විය. සෑම දෙයක්ම තරමක් සංක්ෂිප්ත හා සරල බව පෙනී ගියේය. බස් එක ඉක්මන් කරන්න මම පොඩි ෆැක්ටරියක් හැදුවා මොකද... මට ටයර් කිහිපයක් සහ විවිධ හසුරුවන්න තිබුණා.

PHP පසුපෙළ Redis streams බසයට මාරු කිරීම සහ රාමු-ස්වාධීන පුස්තකාලයක් තෝරා ගැනීම

පියවර කිහිපයක් පමණි:

  • අපි සරලව ඇමතීමට හැකි පණිවිඩ හසුරුවන්න සාදන්නෙමු
  • අපි ඒවා HandlerDescriptor හි ඔතා (පුස්තකාලයෙන් පන්තිය)
  • අපි මෙම “විස්තරයන්” හසුරුවන්නන්ගේ ලොකේටර් අවස්ථාවකින් ඔතා ගනිමු
  • MessageBus උදාහරණයට HandlersLocator එකතු කිරීම
  • අපි SendersLocator වෙත 'SenderInterface' කට්ටලයක් ලබා දෙන්නෙමු, මගේ නඩුවේ 'RedisTransport' පන්තිවල, පැහැදිලිවම වින්‍යාස කර ඇත.
  • MessageBus උදාහරණයට SendersLocator එකතු කිරීම

MessageBus සතුව `->ඩිස්පැච්()` ක්‍රමයක් ඇති අතර එය HandlersLocator හි සුදුසු හසුරුවන්නන් සොයා බලා ඔවුන්ට පණිවිඩය යවයි, අදාළ 'SenderInterface' භාවිතයෙන් බසය හරහා යැවීමට (Redis streams).

බහාලුම් වින්‍යාසය තුළ (මෙම අවස්ථාවේදී php-di), මෙම සම්පූර්ණ මිටියම මෙලෙස වින්‍යාසගත කළ හැක:

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

SendersLocator හි අපි විවිධ පණිවිඩ දෙකක් සඳහා විවිධ “ප්‍රවාහනය” පවරා ඇති බව මෙහිදී ඔබට දැක ගත හැකිය, ඒ සෑම එකක්ම අදාළ ප්‍රවාහවලට තමන්ගේම සම්බන්ධතාවයක් ඇත.

මම පහත බසය භාවිතා කරමින් එකිනෙකා සමඟ සන්නිවේදනය කරන ඩීමන්වරුන් තිදෙනෙකුගේ යෙදුමක් නිරූපණය කරන වෙනම ආදර්ශන ව්‍යාපෘතියක් සෑදුවෙමි: https://github.com/backend-university/products/tree/master/products/02-redis-streams-bus.

නමුත් පාරිභෝගිකයෙකු ව්‍යුහගත කළ හැකි ආකාරය මම ඔබට පෙන්වන්නම්:

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

යෙදුමක මෙම යටිතල පහසුකම් භාවිතා කිරීම

මගේ පසුපෙළේ බස් රථය ක්‍රියාත්මක කිරීමෙන් පසු, මම පැරණි සමමුහුර්ත විධානයෙන් තනි අදියර වෙන් කර වෙනම හසුරුවන්නෙකු සෑදුවෙමි, ඒ සෑම කෙනෙකුම තමන්ගේම දේ කරයි.

දත්ත සමුදායට නව වෙබ් අඩවියක් එක් කිරීමේ නල මාර්ගය මෙලෙස දිස් විය:

PHP පසුපෙළ Redis streams බසයට මාරු කිරීම සහ රාමු-ස්වාධීන පුස්තකාලයක් තෝරා ගැනීම

ඊට පසු, මට නව ක්‍රියාකාරිත්වය එක් කිරීම වඩාත් පහසු විය, උදාහරණයක් ලෙස, රු. නිසා මෙම ක්‍රියාවලියට මුල් අන්තර්ගතයද අවශ්‍ය වේ, එවිට WebsiteIndexHistoryPersistor වැනි RSS සම්බන්ධක නිස්සාරක හසුරුවන්නා “අන්තර්ගතය/HtmlContent” පණිවිඩයට දායක වී, එය ක්‍රියාවට නංවා, අවශ්‍ය පණිවිඩය එහි නල මාර්ගය ඔස්සේ ඉදිරියට යවයි.

PHP පසුපෙළ Redis streams බසයට මාරු කිරීම සහ රාමු-ස්වාධීන පුස්තකාලයක් තෝරා ගැනීම

අවසානයේදී, අපි ඩීමන් කිහිපයක් සමඟ අවසන් කළෙමු, ඒ සෑම එකක්ම අවශ්‍ය සම්පත් සඳහා පමණක් සම්බන්ධතා පවත්වයි. උදාහරණයක් ලෙස යක්ෂයෙක් crawlers අන්තර්ගතය සඳහා අන්තර්ජාලයට යාමට අවශ්‍ය සියලුම හසුරුවන්නන් සහ ඩීමන් අඩංගු වේ නොනැසී පවතිනවා දත්ත සමුදායට සම්බන්ධතාවයක් පවත්වයි.

දැන්, දත්ත සමුදායෙන් තෝරා ගැනීම වෙනුවට, පර්සිස්ටර් විසින් ඇතුළත් කිරීමෙන් පසු අවශ්‍ය හැඳුනුම්පත්, උනන්දුවක් දක්වන සියලුම හසුරුවන්නන් වෙත බසය හරහා සම්ප්‍රේෂණය වේ.

මූලාශ්රය: www.habr.com

අදහස් එක් කරන්න