የPHP ጀርባን ወደ ሬዲስ ዥረቶች አውቶቡስ በማስተላለፍ እና በማዕቀፍ ላይ የተመሰረተ ገለልተኛ ቤተ-መጽሐፍትን መምረጥ

የPHP ጀርባን ወደ ሬዲስ ዥረቶች አውቶቡስ በማስተላለፍ እና በማዕቀፍ ላይ የተመሰረተ ገለልተኛ ቤተ-መጽሐፍትን መምረጥ

መቅድም

እንደ የትርፍ ጊዜ ማሳለፊያ የምሠራው የእኔ ድረ-ገጽ አስደሳች የሆኑ የቤት ገጾችን እና የግል ድረ-ገጾችን ለማስተናገድ የተነደፈ ነው። ይህ ርዕሰ ጉዳይ በፕሮግራም ጉዞዬ መጀመሪያ ላይ ይማርከኝ ጀመር፤ በዚያን ጊዜ ስለራሳቸው፣ በትርፍ ጊዜያቸው እና ስለፕሮጀክቶቻቸው የሚጽፉ ድንቅ ባለሙያዎችን በማግኘቴ አስደነቀኝ። ለራሴ እነሱን የማወቅ ልማድ እስከ ዛሬ ድረስ ይኖራል፡ በሁሉም የንግድ እና የንግድ ድረ-ገጾች ላይ ማለት ይቻላል፣ ከደራሲያን ጋር አገናኞችን ለመፈለግ ግርጌ ላይ መመልከቴን እቀጥላለሁ።

የሃሳቡ ትግበራ

የመጀመሪያው እትም በግሌ ድረ-ገጽ ላይ ያለ የኤችቲኤምኤል ገጽ ብቻ ነበር፣ ፊርማ ያላቸውን አገናኞች ወደ ul ዝርዝር አስገባለሁ። ለተወሰነ ጊዜ 20 ገጾችን ከተየብኩ በኋላ, ይህ በጣም ውጤታማ እንዳልሆነ ማሰብ ጀመርኩ እና ሂደቱን በራስ-ሰር ለመሞከር ወሰንኩ. በተደራራቢ ፍሰት ላይ፣ ብዙ ሰዎች በመገለጫቸው ውስጥ ጣቢያዎችን እንደሚጠቁሙ አስተውያለሁ፣ ስለዚህ በ php ውስጥ ተንታኝ ጻፍኩኝ ፣ እሱም በቀላሉ ፕሮፋይሎችን ውስጥ አልፋለሁ ፣ ከመጀመሪያው ጀምሮ (በ SO ላይ ያሉ አድራሻዎች እስከ ዛሬ ድረስ: `/ተጠቃሚዎች/1`) ), ከተፈለገው መለያ ላይ አገናኞችን አውጥተው በ SQLite ውስጥ አክለዋል.

ይህ ሁለተኛው ስሪት ተብሎ ሊጠራ ይችላል-በኤስኪውላይት ሠንጠረዥ ውስጥ በአስር ሺዎች የሚቆጠሩ ዩአርኤሎች ስብስብ ፣ እሱም በኤችቲኤምኤል ውስጥ የማይንቀሳቀስ ዝርዝሩን ተክቷል። በዚህ ዝርዝር ላይ ቀላል ፍለጋ አደረግሁ. ምክንያቱም ዩአርኤሎች ብቻ ነበሩ፣ ከዚያ ፍለጋው በቀላሉ በእነሱ ላይ የተመሰረተ ነበር።

በዚህ ደረጃ ፕሮጀክቱን ትቼ ከረጅም ጊዜ በኋላ ወደ እሱ ተመለስኩ። በዚህ ደረጃ፣ የስራ ልምዴ ከሶስት አመት በላይ ነበር እና የበለጠ ከባድ ነገር ማድረግ እንደምችል ተሰማኝ። በተጨማሪም በአንጻራዊነት አዳዲስ ቴክኖሎጂዎችን ለመቆጣጠር ከፍተኛ ፍላጎት ነበረው.

ዘመናዊ ስሪት

ፕሮጀክቱ በዶከር ውስጥ ተሰማርቷል፣ የውሂብ ጎታው ወደ mongoDb ተላልፏል፣ እና በቅርቡ ደግሞ ራዲሽ ተጨምሯል፣ እሱም መጀመሪያ ላይ ለመሸጎጫ ብቻ ነበር። ከ PHP ማይክሮ ክፈፎች ውስጥ አንዱ እንደ መሰረት ነው.

ችግር

አዲስ ጣቢያዎች በኮንሶል ትዕዛዝ የታከሉ ሲሆን ይህም በተመሳሳይ የሚከተሉትን ያደርጋል፡

  • ይዘትን በዩአርኤል ያወርዳል
  • HTTPS መገኘቱን የሚያመለክት ባንዲራ አዘጋጅቷል።
  • የድረ-ገጹን ይዘት ይጠብቃል።
  • ምንጭ HTML እና ራስጌዎች በ"መረጃ ጠቋሚ" ታሪክ ውስጥ ተቀምጠዋል
  • ይዘትን ይመረምራል፣ ርዕስ እና መግለጫ ያወጣል።
  • ውሂብ ወደ የተለየ ስብስብ ያስቀምጣል።

ይህ በቀላሉ ጣቢያዎችን ለማከማቸት እና በዝርዝሩ ውስጥ ለማሳየት በቂ ነበር፡-

የPHP ጀርባን ወደ ሬዲስ ዥረቶች አውቶቡስ በማስተላለፍ እና በማዕቀፍ ላይ የተመሰረተ ገለልተኛ ቤተ-መጽሐፍትን መምረጥ

ነገር ግን ሁሉንም ነገር በራስ-ሰር የማውጣት ፣ የመፈረጅ እና ደረጃ አሰጣጥ ፣ ሁሉንም ነገር ወቅታዊ ለማድረግ ፣ ከዚህ ምሳሌ ጋር በትክክል አልተስማማም ። በቀላሉ የድረ-ገጽ ዘዴን በመጨመር የሚፈለጉትን የኮድ ማባዛትና ማገድ እምቅ DDoSን ለማስወገድ።

በአጠቃላይ ፣ በእርግጥ ፣ ሁሉም ነገር በተመሳሳይ ጊዜ ሊከናወን ይችላል ፣ እና በድር ዘዴ ውስጥ ዩአርኤሉን በቀላሉ ማስቀመጥ ይችላሉ ፣ ስለሆነም ጭራቃዊው ዴሞን ከዝርዝሩ ውስጥ ያሉትን ሁሉንም ተግባራት ያከናውናል ። ግን አሁንም, እዚህ እንኳን "ወረፋ" የሚለው ቃል እራሱን ይጠቁማል. እና ወረፋ ከተተገበረ, ሁሉም ስራዎች ሊከፋፈሉ እና ቢያንስ በተመሳሰሉ መልኩ ሊከናወኑ ይችላሉ.

ዉሳኔ

ወረፋዎችን ይተግብሩ እና ሁሉንም ስራዎች ለማስኬድ በክስተት-ተኮር ስርዓት ይፍጠሩ። እና ሬዲስ ዥረቶችን ለረጅም ጊዜ ለመሞከር ፈልጌ ነበር።

በ PHP ውስጥ Redis ዥረቶችን መጠቀም

ምክንያቱም የእኔ ማዕቀፍ ከሶስቱ ግዙፍ ሲምፎኒ፣ ላራቬል፣ ዪኢ አንዱ ስላልሆነ ራሱን የቻለ ቤተ-መጽሐፍት ማግኘት እፈልጋለሁ። ግን ፣ እንደ ተለወጠ (በመጀመሪያ ምርመራ) ፣ የግለሰብ ከባድ ቤተ-መጽሐፍቶችን ማግኘት አይቻልም። ከወረፋዎች ጋር የተያያዙ ሁሉም ነገሮች ከአምስት ዓመታት በፊት የፈጸሙት ከ 3 ፕሮጀክት ወይም ከማዕቀፉ ጋር የተያያዘ ነው.

ስለ ሲምፎኒ እንደ ግለሰብ ጠቃሚ ክፍሎች አቅራቢ ብዙ ሰምቻለሁ፣ እና አንዳንዶቹን አስቀድሜ እጠቀማለሁ። እና እንዲሁም አንዳንድ ነገሮች ከላራቬል በተጨማሪ ጥቅም ላይ ሊውሉ ይችላሉ, ለምሳሌ የእነሱ ORM, ማዕቀፉ ራሱ ሳይኖር.

ሲምፎኒ / መልእክተኛ

የመጀመሪያው እጩ ወዲያውኑ ተስማሚ መስሎ ታየኝ እና ያለምንም ጥርጣሬ ጫንኩት። ነገር ግን ከSymfony ውጭ የአጠቃቀም ምሳሌዎችን ጎግል ማድረግ በጣም አስቸጋሪ ሆኖ ተገኘ። ሁለንተናዊ ፣ ትርጉም የለሽ ስሞች ፣ መልእክት ለማስተላለፍ አውቶቡስ እና በሬዲስ ላይ ከበርካታ ክፍሎች እንዴት እንደሚሰበሰቡ?

የPHP ጀርባን ወደ ሬዲስ ዥረቶች አውቶቡስ በማስተላለፍ እና በማዕቀፍ ላይ የተመሰረተ ገለልተኛ ቤተ-መጽሐፍትን መምረጥ

በኦፊሴላዊው ጣቢያ ላይ ያለው ሰነድ በጣም ዝርዝር ነበር ፣ ግን አጀማመሩ የተገለፀው ለሲምፎኒ የሚወዱትን YML እና ሌሎች አስማታዊ ዘዴዎችን በመጠቀም ብቻ ነው። በተለይም በአዲሱ ዓመት በዓላት ወቅት የመጫን ሂደቱ ምንም ፍላጎት አልነበረኝም. ግን ይህን ማድረግ ያለብኝ ባልጠበቅነው ረጅም ጊዜ ነው።

የሲምፎኒ ምንጮችን በመጠቀም ስርዓትን እንዴት ማፋጠን እንደሚቻል ለማወቅ መሞከር እንዲሁ በጣም ቀላል ስራ አይደለም ለተወሰነ ጊዜ።

የPHP ጀርባን ወደ ሬዲስ ዥረቶች አውቶቡስ በማስተላለፍ እና በማዕቀፍ ላይ የተመሰረተ ገለልተኛ ቤተ-መጽሐፍትን መምረጥ

ወደዚህ ሁሉ ከገባሁ በኋላ በእጄ አንድ ነገር ለማድረግ ከሞከርኩ በኋላ አንድ ዓይነት ክራንች እየሠራሁ እንደሆነ መደምደሚያ ላይ ደረስኩ እና ሌላ ነገር ለመሞከር ወሰንኩ.

የበራ / ወረፋ

ይህ ቤተ-መጽሐፍት ከላራቭል መሠረተ ልማት እና ከሌሎች ጥገኞች ስብስብ ጋር በጥብቅ የተሳሰረ ነው ፣ ስለሆነም በእሱ ላይ ብዙ ጊዜ አላጠፋሁም: ጫንኩት ፣ ተመለከትኩት ፣ ጥገኞቹን አይቼ ሰረዝኩት።

yiisoft/yii2-ወረፋ

ደህና ፣ እዚህ ወዲያውኑ ከስሙ ይታሰባል ፣ እንደገና ፣ ከ Yii2 ጋር ጥብቅ ግንኙነት። ይህን ቤተ-መጽሐፍት መጠቀም ነበረብኝ እና መጥፎ አልነበረም, ነገር ግን ሙሉ በሙሉ በ Yii2 ላይ የተመሰረተ ስለመሆኑ አላሰብኩም ነበር.

የተቀሩት

በ GitHub ላይ ያገኘኋቸው ሁሉም ነገሮች አስተማማኝ ያልሆኑ፣ ጊዜ ያለፈባቸው እና የተተዉ ፕሮጀክቶች ከዋክብት፣ ሹካ እና ብዙ ቁጥር ያላቸው ስራዎች ነበሩ።

ወደ ሲምፎኒ/መልእክተኛ፣ ቴክኒካዊ ዝርዝሮች ተመለስ

ይህንን ቤተ-መጽሐፍት ማወቅ ነበረብኝ እና፣ ትንሽ ተጨማሪ ጊዜ ካሳለፍኩ በኋላ፣ ቻልኩ። ሁሉም ነገር በጣም አጭር እና ቀላል ሆኖ ተገኝቷል። አውቶቡሱን ለማፋጠን ትንሽ ፋብሪካ ሰራሁ ምክንያቱም... ብዙ ጎማዎች እና የተለያዩ ተቆጣጣሪዎች ሊኖሩኝ ይገባ ነበር።

የPHP ጀርባን ወደ ሬዲስ ዥረቶች አውቶቡስ በማስተላለፍ እና በማዕቀፍ ላይ የተመሰረተ ገለልተኛ ቤተ-መጽሐፍትን መምረጥ

ጥቂት ደረጃዎች ብቻ፡-

  • በቀላሉ ሊጠሩ የሚችሉ የመልእክት አስተናባሪዎችን እንፈጥራለን
  • በ HandlerDescriptor (የላይብረሪውን ክፍል) እናጠቃልላቸዋለን
  • እነዚህን “ገላጭዎች” በ HandlersLocator ምሳሌ እንጠቅሳቸዋለን
  • HandlersLocatorን ወደ MessageBus ምሳሌ በማከል ላይ
  • የ‹የላኪ በይነገጽ› ስብስብን ወደ ላኪዎች እናስተላልፋለን፣ በእኔ ሁኔታ የ‹RedisTransport› ክፍሎች ግልጽ በሆነ መንገድ የተዋቀሩ ናቸው።
  • ወደ MessageBus ምሳሌ ላኪዎችን በማከል ላይ

MessageBus በ HandlersLocator ውስጥ ተገቢውን ተቆጣጣሪዎች የሚፈልግ እና መልእክቱን ወደ እነርሱ የሚያስተላልፍ `->dispatch()` ዘዴ አለው፣ በአውቶቡስ በኩል ለመላክ ተጓዳኝ `የላኪ በይነገጽ›ን በመጠቀም።

በመያዣው ውቅር (በዚህ አጋጣሚ 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);
        },

እዚህ በሰንደሮች ሎካተር ውስጥ ለሁለት የተለያዩ መልዕክቶች የተለያዩ "መጓጓዣዎችን" እንደመደብን ማየት ይችላሉ, እያንዳንዱም ከተዛማጅ ዥረቶች ጋር የራሱ ግንኙነት አለው.

በሚከተለው አውቶብስ በመጠቀም የሶስት ዲሞኖች እርስ በርስ የሚግባቡበትን መተግበሪያ የሚያሳይ የተለየ ማሳያ ፕሮጄክት ሰራሁ። 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 ጀርባን ወደ ሬዲስ ዥረቶች አውቶቡስ በማስተላለፍ እና በማዕቀፍ ላይ የተመሰረተ ገለልተኛ ቤተ-መጽሐፍትን መምረጥ

እና ከዚያ በኋላ ወዲያውኑ አዲስ ተግባር ለመጨመር በጣም ቀላል ሆነልኝ፣ ለምሳሌ Rss ማውጣት እና መተንተን። ምክንያቱም ይህ ሂደትም ዋናውን ይዘት ይፈልጋል፣ ከዚያም የአርኤስኤስ ማገናኛ አውጭው ተቆጣጣሪ፣ እንደ WebsiteIndexHistoryPersistor፣ ለ"ይዘት/ኤችቲኤምኤል ይዘት" መልእክት ተመዝግቧል፣ ያስኬደው እና የሚፈለገውን መልእክት በቧንቧው ላይ የበለጠ ያስተላልፋል።

የPHP ጀርባን ወደ ሬዲስ ዥረቶች አውቶቡስ በማስተላለፍ እና በማዕቀፍ ላይ የተመሰረተ ገለልተኛ ቤተ-መጽሐፍትን መምረጥ

በመጨረሻ ፣ በርካታ ዲሞኖች ጋር ጨርሰናል ፣ እያንዳንዱም አስፈላጊ ከሆኑ ሀብቶች ጋር ግንኙነቶችን ያቆያል። ለምሳሌ ጋኔን ብስኩቶች ለይዘት ወደ በይነመረብ መሄድ የሚያስፈልጋቸው ሁሉንም ተቆጣጣሪዎች እና ዴሞን ይዟል ቀጥል ከመረጃ ቋቱ ጋር ግንኙነት ይይዛል።

አሁን፣ ከመረጃ ቋቱ ውስጥ ከመምረጥ ይልቅ፣ በቋሚው ካስገቡ በኋላ የሚፈለጉት መታወቂያዎች በቀላሉ በአውቶቡስ በኩል ለሁሉም ፍላጎት ላላቸው ተቆጣጣሪዎች ይተላለፋሉ።

ምንጭ: hab.com

አስተያየት ያክሉ