snidel

2025-12-07 0 978

snidel

一个多进程容器。 snidel使所有PHP开发人员更容易在没有任何扩展的情况下进行并行处理

请考虑向该项目的作者Akihito Nakano捐款,以表达您的❤️和支持。

赞助商@ackintosh在Github赞助商上

snidel解决了什么?

(en)

没有几个人,使用PHP开始他们的编程运营商,然后继续。并行处理,他们不熟悉它,可能是他们的障碍。

否则,那些不得不使用PHP的语言开发的人(例如一种具有较高功能的语言用于并行处理)。 (过去是我。)

为了使并行处理更轻松,本能地使用它们,我开始开发snidel 。

当您考虑“如何并行?”时, snidel可能是您的选择之一。这对我来说是一种荣幸。

(JA)

我认为有些程序员已经开始使用PHP编程,并通过PHP(我)建立了职业生涯。对于这样的人来说,并行处理可能不熟悉它,或者似乎是一个高阈值。

另外,有些人必须在某种情况下不受PHP以外的其他语言(例如,由于各种情况而具有出色机制的语言)进行开发(例如,我以前是这种情况)。

我们已经开始开发snidel ,目的是使使用并行处理更轻松,直观地解决问题。

我希望snidel可以成为您的选择之一,如果您说:“我想并行执行此过程,我该怎么办?”

通过作曲家安装snidel

 $ composer require ackintosh/ snidel :~0.11.0

建筑学

好处

也可能通过建立功能(例如exec )进行并行处理:

 initialize_data_required_for_the_slow_jobs ();

exec ( \' php slow_job1.php & \' );
exec ( \' php slow_job2.php & \' );

对于以上感到“痛苦”的开发人员, snidel可以提供相当不错的体验,并会简化其PHP编程。

我们将浏览用法,以显示snidel如何并行处理您的编程。使用snidel的经验应解决您的痛苦。让我们开始吧!

用法

基本用法

snidel;

$f = function ($s) {
sleep(3);
echo \’echo: \’ . $s;
return \’return: \’ . $s;
};

$s = time();
$ snidel = new snidel ();
$ snidel ->process($f, [\’foo\’]);
$ snidel ->process($f, [\’bar\’]);
$ snidel ->process($f, [\’baz\’]);

// ` snidel ::results()` returns `\\Generator`
foreach ($ snidel ->results() as $r) {
// string(9) \”echo: foo\”
var_dump($r->getOutput());
// string(11) \”return: foo\”
var_dump($r->getReturn());
}

// If you don\’t need the results, let\’s use ` snidel ::wait()` instead of ` snidel ::results()`
// $ snidel ->wait();

echo (time() – $s) . \’sec elapsed\’ . PHP_EOL;
// 3sec elapsed.\”>

 <?php
use Ackintosh \\ snidel ;

$ f = function ( $ s ) {
    sleep ( 3 );
    echo \' echo: \' . $ s ;
    return \' return: \' . $ s ;
};

$ s = time ();
$ snidel = new snidel ();
$ snidel -> process ( $ f , [ \' foo \' ]);
$ snidel -> process ( $ f , [ \' bar \' ]);
$ snidel -> process ( $ f , [ \' baz \' ]);

// ` snidel ::results()` returns `\\Generator`
foreach ( $ snidel -> results () as $ r ) {
    // string(9) \"echo: foo\"
    var_dump ( $ r -> getOutput ());
    // string(11) \"return: foo\"
    var_dump ( $ r -> getReturn ());
}

// If you don\'t need the results, let\'s use ` snidel ::wait()` instead of ` snidel ::results()`
// $ snidel ->wait();

echo ( time () - $ s ) . \' sec elapsed \' . PHP_EOL ;
// 3sec elapsed.

构造函数参数

所有参数都是可选的。

snidel([
\’concurrency\’ => 3,
// Please refer to `Logging`
\’logger\’ => $monolog,
// Please refer to `Using custom queue`
\’driver\’ => $driver,
// a polling duration(in seconds) of queueing
\’pollingDuration\’ => 1,
]);\”>

 new snidel ([
    \' concurrency \' => 3 ,
    // Please refer to `Logging`
    \' logger \' => $ monolog ,
    // Please refer to `Using custom queue`
    \' driver \' => $ driver ,
    // a polling duration(in seconds) of queueing
    \' pollingDuration \' => 1 ,
]);

call_user_func_array相同的参数

snidel->process($f, [\’arg1\’, \’arg2\’]);

// global function
$ snidel ->process(\’myfunction\’);

// instance method
$ snidel ->process([$instance, \’method\’]);
\”>

 // multiple arguments
$ snidel -> process ( $ f , [ \' arg1 \' , \' arg2 \' ]);

// global function
$ snidel -> process ( \' myfunction \' );

// instance method
$ snidel -> process ([ $ instance , \' method \' ]);

标记任务

snidel->process($f, \’arg-A_tag1\’, \’tag1\’);
$ snidel ->process($f, \’arg-B_tag1\’, \’tag1\’);
$ snidel ->process($f, \’arg_tag2\’, \’tag2\’);

foreach ($ snidel ->results as $r) {
// `Task::getTag()` returns the tag passed as 3rd parameter of ` snidel ::process()`
switch ($r->getTask()->getTag()) {
case \’tag1\’:
$r->getReturn(); // arg-A_tag1 | arg-B_tag1
break;
case \’tag2\’:
$r->getReturn(); // arg_tag2
break;
default:
$r->getReturn();
break;
}
}\”>

 $ f = function ( $ arg ) {
    return $ arg ;
};

$ snidel -> process ( $ f , \' arg-A_tag1 \' , \' tag1 \' );
$ snidel -> process ( $ f , \' arg-B_tag1 \' , \' tag1 \' );
$ snidel -> process ( $ f , \' arg_tag2 \' , \' tag2 \' );

foreach ( $ snidel -> results as $ r ) {
    // `Task::getTag()` returns the tag passed as 3rd parameter of ` snidel ::process()`
    switch ( $ r -> getTask ()-> getTag ()) {
        case \' tag1 \' :
            $ r -> getReturn (); // arg-A_tag1 | arg-B_tag1
            break ;
        case \' tag2 \' :
            $ r -> getReturn (); // arg_tag2
            break ;
        default :
            $ r -> getReturn ();
            break ;
    }
}

记录

snidel支持使用Logger进行记录,该记录器实现PSR-3:Logger接口。

snidel ([\’logger\’ => $monolog]);
$ snidel ->process($f);

// 2017-03-22 13:13:43 > DEBUG > forked worker. pid: 60018 {\”role\”:\”master\”,\”pid\”:60017}
// 2017-03-22 13:13:43 > DEBUG > forked worker. pid: 60019 {\”role\”:\”master\”,\”pid\”:60017}
// 2017-03-22 13:13:43 > DEBUG > has forked. pid: 60018 {\”role\”:\”worker\”,\”pid\”:60018}
// 2017-03-22 13:13:43 > DEBUG > has forked. pid: 60019 {\”role\”:\”worker\”,\”pid\”:60019}
// 2017-03-22 13:13:44 > DEBUG > —-> started the function. {\”role\”:\”worker\”,\”pid\”:60018}
// 2017-03-22 13:13:44 > DEBUG > —-> started the function. {\”role\”:\”worker\”,\”pid\”:60019}
// …
\”>

 // e.g. MonoLog
use Monolog \\ Formatter \\ LineFormatter ;
use Monolog \\ Handler \\ StreamHandler ;
use Monolog \\ Logger ;

$ monolog = new Logger ( \' sample \' );
$ stream = new StreamHandler ( \' php://stdout \' , Logger:: DEBUG );
$ stream -> setFormatter ( new LineFormatter ( \" %datetime% > %level_name% > %message% %context% \\n\" ));
$ monolog -> pushHandler ( $ stream );

$ snidel = new snidel ([ \' logger \' => $ monolog ]);
$ snidel -> process ( $ f );

// 2017-03-22 13:13:43 > DEBUG > forked worker. pid: 60018 {\"role\":\"master\",\"pid\":60017}
// 2017-03-22 13:13:43 > DEBUG > forked worker. pid: 60019 {\"role\":\"master\",\"pid\":60017}
// 2017-03-22 13:13:43 > DEBUG > has forked. pid: 60018 {\"role\":\"worker\",\"pid\":60018}
// 2017-03-22 13:13:43 > DEBUG > has forked. pid: 60019 {\"role\":\"worker\",\"pid\":60019}
// 2017-03-22 13:13:44 > DEBUG > ----> started the function. {\"role\":\"worker\",\"pid\":60018}
// 2017-03-22 13:13:44 > DEBUG > ----> started the function. {\"role\":\"worker\",\"pid\":60019}
// ...

儿童的错误信息

snidel->process(function ($arg1, $arg2) {
exit(1);
}, [\’foo\’, \’bar\’]);
$ snidel ->get();

var_dump($ snidel ->getError());
// class Ackintosh\\ snidel \\Error#4244 (1) {
// …
// }

foreach ($ snidel ->getError() as $pid => $e) {
var_dump($pid, $e);
}
// int(51813)
// array(5) {
// \’status\’ => int(256)
// \’message\’ => string(50) \”an error has occurred in child process.
// \’callable\’ => string(9) \”*Closure*\”
// \’args\’ =>
// array(2) {
// [0] => string(3) \”foo\”
// [1] => string(3) \”bar\”
// }
// \’return\’ => NULL
// }
// }\”>

 $ snidel -> process ( function ( $ arg1 , $ arg2 ) {
    exit ( 1 );
}, [ \' foo \' , \' bar \' ]);
$ snidel -> get ();

var_dump ( $ snidel -> getError ());
// class Ackintosh\\ snidel \\Error#4244 (1) {
// ...
// }

foreach ( $ snidel -> getError () as $ pid => $ e ) {
    var_dump ( $ pid , $ e );
}
// int(51813)
// array(5) {
//   \'status\' =>  int(256)
//   \'message\' => string(50) \"an error has occurred in child process.
//   \'callable\' => string(9) \"*Closure*\"
//   \'args\' =>
//     array(2) {
//       [0] => string(3) \"foo\"
//       [1] => string(3) \"bar\"
//     }
//   \'return\' => NULL
//   }
// }

使用自定义队列

snidel取决于Bernard作为队列抽象层。伯纳德(Bernard)是一个多余的PHP库,用于创建背景作业以供以后处理。
默认情况下, snidel构建了Flatfile驱动程序,但是从种族条件的角度来看,我们建议在生产中使用更可靠的队列。

Amazon SQS

snidel([
\’driver\’ => $driver,
]);\”>

 $ connection = Aws \\ Sqs \\SqsClient:: factory ([
    \' key \'    => \' your-aws-access-key \' ,
    \' secret \' => \' your-aws-secret-key \' ,
    \' region \' => \' the-aws-region-you-choose \'
]);
$ driver = new Bernard \\ Driver \\ SqsDriver ( $ connection );

new snidel ([
    \' driver \' => $ driver ,
]);

有关驾驶员的详细信息,请参阅此处。

文章

这是引入snidel的文章。谢谢你!

  • [php-都

要求

  • PCNTL功能

版本指导

snidel php
0.1〜0.8 > = 5.3
0.9〜 > = 5.6
0.13 > = 7.1

Docker

我们建议您尝试使用Docker,因为snidel需要需求中显示的一些PHP扩展。

在Docker容器中运行单元测试

snidel .
docker run –rm -v ${PWD}:/ snidel snidel php composer.phar install
docker run –rm -v ${PWD}:/ snidel snidel vendor/bin/phpunit\”>

curl -Ss https://get*comp**oser.org/installer | php
docker build -t snidel .
docker run --rm -v ${PWD} :/ snidel snidel php composer.phar install
docker run --rm -v ${PWD} :/ snidel snidel vendor/bin/phpunit

作者

snidel ©Ackintosh,根据MIT许可证发布。
由Ackintosh撰写和维护

github @ackintosh / twitter @nakano_akihito / blog(ja)

作者关于snidel (JA)的博客条目:

  • https://ackintosh.g*ith**ub.io/blog/2015/09/29/snidel/
  • https://ackintosh.g**i*thub.io/blog/2015/11/08/snidel_0_2_0/
  • https://ackintosh.g**it*hub.io/blog/2016/04/04/snidel_0_4_0/
  • https://ackintosh.gi***thub.io/blog/2016/04/04/snidel_0_5_0/
  • https://ackintosh.**gi*thub.io/blog/2016/05/04/snidel_0_6_0/
  • https://ackintosh.gi**th*ub.io/blog/2016/09/09/snidel_0_7_0/
  • https://ackintosh.g*i*thu*b.io/blog/2017/03/10/snidel_0_8_0/
  • https://ackintosh.g**it*hub.io/blog/2017/07/17/snidel_0_9_0/

致谢

感谢Jetbrains提供免费的开源许可证。

下载源码

通过命令行克隆项目:

git clone https://github.com/ackintosh/snidel.git

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 开发教程 snidel https://www.zuozi.net/31609.html

DreamHacker
下一篇: DreamHacker
常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务