PHP 収量の高度な使用法を学ぶ
冒頭章
PHP
の yield
に初めて触れたとき、私はこう思いました。フェルト、yield
それはどのようなブラック テクノロジですか? Baidu: yield
——コルーチン、ジェネレーター。多くの記事で Iterator
、Generater
について取り上げていますが、これは PHP イテレータの補足です。さらに数ページめくると、Go coroutine
が見つかります。好奇心から、Go Coroutine
をクリックして調べてみました。これには、Concurrency
、Thread
、Pipeline Communication
などの単語が含まれていました。注意: これはブラック テクノロジです。戻って PHP
を確認すると、毎分 Go
に切り替えたいと考えています。
#関連する学習の推奨事項:
PHP に参加するための生成構文
yield構文はバージョン 5.5 の
PHP に追加されました。イテレータとともに使用されます。関数は
プロセス制御コード、および
goto,
return 同様です。
yield $i に実行されると、
return が返されることが分析できます。 $i,
echo "$value\n" の後、
goto
for ($i = 1; $i $i が安全に送信されました。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"><?phpfunction gen_one_to_three() {
for ($i = 1; $i <= 7; $i++) {
//注意变量$i的值在不同的yield之间是保持传递的。
yield $i;
}}$generator = gen_one_to_three();foreach ($generator as $value) {
echo "$value\n";}// output12...67</pre><div class="contentsignin">ログイン後にコピー</div></div>
どのような問題が発生しましたかコードを書くことは問題を解決することです。彼らが遭遇した問題を見てみましょう: PHP関係者に関しては、簡潔かつ簡潔な方法でyieldを全員に紹介する必要があります。一部のネットユーザーは、限られたリソース内で大規模なファイル操作を完了する必要があります。そして私たちの鳥の兄弟。現在の初級レベルの Yield チュートリアルに不満を抱いている PHPer のグループに直面し、タスク スケジューラを例として
yield の高度な使用法を説明しました。 php.net: ジェネレーター構文、
風雪コーナー: コルーチンを使用して PHP でマルチタスク スケジューリングを実装する。
提案された質問、上記の答えを見ると、この PHP コルーチンはそれ以上のものではないと思います (
と比較)。
格言があります - 良い質問は答えよりも重要です
現在、大多数のネチズンは、利益を得るために、より適切で難しい質問をしていません。
yieldこの入出力構文の多くの例は、イテレータとして yield を使用するか、非常に大きなテキストを読み取るために低メモリを使用する例です。
Excel
csv など、どんなに高度なものであっても、単純なタスクスケジューラーを実装するために使用され、このスケジューラーのコードは一見すると似ています。
質問させてください
良い質問と同じように、答えよりも価値があります
PHP を使用して、リクエストを受信してサーバーの時間を返すことができるソケット サーバーを実装します。さて、これが最初の質問です。伏線です。公式回答
- 元のコードに、ソケットサーバーがリクエストを処理する際に他のソケットサーバーに依存し、クライアント機能も必要になるという要件を追加します。つまり、リクエストを受信したり、他のサーバーへのリクエストを開始したりできます。
- 元のソケット サーバーは同時に 1 人の顧客にのみサービスを提供できます。
ソケット サーバーを実現したいと考えています。このサーバーはソケット クライアント機能を備えています。
Concurrency- をサポートし、受信したリクエストとアクティブに開始されたリクエストを処理します。マルチスレッドやマルチプロセスを使用する必要はありません。
-
#この質問はまだ伏線です。これらの質問は非常にドライです。よく考えてください。質問 2 と 3 の答えはすべてスクリプトにあります: nio_server.php
上記のコードでは、ユーザーがショッピング カートのアドオン アクションを要求するという特定のビジネスを列挙しましたが、ショッピング カート サービスに関しては、実現可能性を検証するために商品サービス、在庫サービス、優待サービスと対話する必要があります。アドオン アクションの。リクエストと比較には同期メソッドと非同期メソッドがあります。
ヒント: これは、PHP
- の
- yield 構文に関連しています。
もう一つのリマインダー: yield
文法上の特徴は何ですか、インとアウト
!
コードを見ると、同期、非同期、出たり入ったり
何を思いましたか? 同期処理モードでコードを見ると、これら 3 つの関数
checkProduct
checkPromo がリクエストを開始し、戻りを待ちます。その結果、これら 3 つの関数が実行された後、クライアントの要求が応答されます。 <p>异步处理模式下,这三个函数发起请求完毕后,代码就跳出循环了,然后是在<code>select()
下的一个代码分支中接收请求, 并收集结果。每次收到结果后判断是否完成,完成则响应客户端。
那么能不能这样:在异步处理的流程中,当 Server
收到 自己发起的 client
有数据响应后,代码跳到 nio_server.php 的 247行呢,这样我们的收到请求校验相关的代码就能放到这里,编码能就是同步,容易理解。不然,client
的响应处理放在 280 行以后,不通过抓包,真的很难理解,执行了第 247 行代码后,紧接着是从 280 行开始的。
诶~这里是不是有 进进出出 那种感觉了~ 代码从 247 行出去,开始监听发出 Client
响应,收到返回数据,带着数据再回到 247 行,继续进行逻辑校验,综合结果后,再响应给客户端。
用yield来解决问题
基于 yield 实现的,同步编码,"异步"I/O
的 Socket Server
就实现了。代码。
这里 “异步” 打了引号,大佬别扣这个字眼了。 该是
非阻塞I/O
不等大家的答案了,先上我的结果代码吧,代码呢都放在这个目录下了。
gitee https://gitee.com/xupaul/PHP-generator-yield-Demo/tree/master/yield-socket
运行测试代码
clone 代码到本地后,需要拉起4个 command 命令程序:
拉起3个第三方服务
## 启动一个处理耗时2s的库存服务$ php ./other_server.php 8081 inventory 2## 启动一个处理耗时4s的产品服务$ php ./other_server.php 8082 product 4## 监听8083端口,处理一个请求 耗时6s的 promo 服务$ php ./other_server.php 8083 promo 6
启动购物车服务
## 启动一个非阻塞购物车服务$ php ./async_cart_server.php ## 或者启动一个一般购物车服务$ php ./cart_server.php
发起用户请求
$ php ./user_client.php
运行结果呢如下,通过执行的时间日志,可得这三个请求是并发发起的,不是阻塞通讯。
在看我们的代码,三个函数,发起socket
请求,没有设置callback
,而是通过yield from
接收了三个socket
的返回结果。
也就是达到了,同步编码,异步执行的效果。
运行结果
非阻塞模式
client 端日志:
通过以上 起始时间
和 结束时间
,就看到这三个请求耗时总共就6s,也就按照耗时最长的promo服务的耗时来的。也就是说三个第三方请求都是并发进行的。
cart server 端日志:
而 cart 打印的日志,可以看到三个请求一并发起,并一起等待结果返回。达到非阻塞并发请求的效果。
阻塞模式
client 端日志:
以上是阻塞方式请求,可以看到耗时 12s。也就是三个服务加起来的耗时。
cart server 端日志:
cart 服务,依次阻塞方式请求第三方服务,顺序执行完毕后,共耗时12s,当然如果第一个,获第二个服务报错的话,会提前结束这个检查。会节约一点时间。
工作原理
这里就是用到了 yield
的工作特点——进进出出,在发起非阻塞socket
请求后,不是阻塞方式等待socket响应,而是使用yield
跳出当前执行生成器,等待有socket响应后,在调用生成器的send
方法回到发起socket
请求的函数内,在 yield from Async::all()
接收数据响应数据搜集完毕后,返回。
和Golang比一比
考虑到网速原因,我这就放上一个国内教程链接:Go 并发 教程
php
的协程是真协程,而Go
是披着协程外衣的轻量化线程(“协程”里,都玩上“锁”了,这就是线程)。
我个人偏爱,协程的,觉得线程的调度有一定随机性,因此需要锁机制来保证程序的正确,带来了额外开销。协程的调度(换入换出)交给了用户,保证了一段代码执行连续性(当然进程级上,还是会有换入换出的,除非是跨进程的资源访问,或者跨机器的资源访问,这时,就要用到分布式锁了,这里不展开讨论),同步编码,异步执行,只需要考虑那个哪个方法会有IO交互会协程跳出即可。
和NodeJS比划一下
Javascript 和 PHP 两个脚本语言有很多相似的地方,弱类型,动态对象,单线程,在Web领域生态丰富。不同的是,Javascript
在浏览器端一开始就是异步的(如果js发起网络请求只能同步进行,那么你的网页渲染线程会卡住),例如Ajax
,setTimeout
,setInterval
,这些都是异步+回调的方式工作。
基于V8引擎而诞生的NodeJS
,天生就是异步的,在提供高性能网络服务有很大的优势,不过它的IO编码范式
么。。。刚开始是 回调——毁掉地狱,后来有了Promise——屏幕竖起来看,以及Generator
——遇事不绝yield
一下吧,到现在的Async/Await
——语法糖?真香!
可以说JS的委员非常勤快,在异步编程范式的标准制定也做的很好(以前我尝试写NodeJS
时,几个回调就直接把我劝退了),2009年诞生的NodeJS
有点后来居上的意思。目前PHP
只是赶上了协程,期待PHP的Async/Await
语法糖的实现吧。
PHP yield 使用注意事项
一旦使用上 yield 后,就必须注意调用函数是,会得到函数结果,还是 生成器对象。PHP 不会自动帮你区别,需要你手动代码判断结果类型—— if ($re instanceof \Generator) {}
, 如果你得到的是 生成器,但不希望去手动调用 current() 去执行它,那么在生成器前 使用 yield from 交给上游(框架)来解决。
爆改 Workerman
博客写到这,就开始手痒痒了,看到Workerman框架,我在基础上二开,使其能——同步编码,异步执行。
代码已放到:PaulXu-cn/CoWorkerman.git
目前还是dev阶段,大家喜欢可以先 体验一波。
$ composer require paulxu-cn/co-workerman
一个简单的单线程 TCP Server
<?php// file: ./examples/example2/coWorkermanServer.php , 详细代码见github$worker = new CoWorker('tcp://0.0.0.0:8080');// 设置fork一个子进程$worker->count = 1;$worker->onConnect = function (CoTcpConnection $connection) { try { $conName = "{$connection->getRemoteIp()}:{$connection->getRemotePort()}"; echo PHP_EOL . "New Connection, {$conName} \n"; $re = yield from $connection->readAsync(1024); CoWorker::safeEcho('get request msg :' . $re . PHP_EOL ); yield from CoTimer::sleepAsync(1000 * 2); $connection->send(json_encode(array('productId' => 12, 're' =>true))); CoWorker::safeEcho('Response to :' . $conName . PHP_EOL . PHP_EOL); } catch (ConnectionCloseException $e) { CoWorker::safeEcho('Connection closed, ' . $e->getMessage() . PHP_EOL); }};CoWorker::runAll();
这里设置fork 一个worker
线程,处理逻辑中带有一个sleep()
2s
的操作,依然不影响他同时响应多个请求。
启动测试程序
## 启动CoWorker服务$ php ./examples/example2/coWorkermanServer.php start## 启动请求线程$ php ./examples/example2/userClientFork.php
运行结果
绿色箭头——新的请求,红色箭头——响应请求
从结果上看到,这一个worker线程,在接收新的请求同时,还在回复之前的请求,各个连接交错运行。而我们的代码呢,看样子就是同步的,没有回调。
CoWorker购物车服务
好的,这里我们做几个简单的微服务模拟实际应用,这里模拟 用户请求端
,购物车服务
,库存服务
,产品服务
。 模拟用户请求加购动作,购物车去分别请求 库存,产品 校验用户是否可以加购,并响应客户请求是否成功。
代码我就不贴了,太长了,麻烦移步 CoWorkerman/example/example5/coCartServer.php
运行命令
## 启动库存服务$ php ./examples/example5/otherServerFork.php 8081 inventory 1## 启动产品服务$ php ./examples/example5/otherServerFork.php 8082 product 2
## 启动CoWorker 购物车服务$ php ./examples/example5/coCartServer.php start
## 用户请求端$ php ./examples/example5/userClientFork.php
运行结果
黄色箭头——新的用户请求,蓝色箭头——购物车发起库存,产品检查请求,红色箭头——响应用户请求
从图中看到也是用1个线程服务多个连接,交错运行。
好的,那么PHP CoWorkerman
也能像 NodeJS
那样用 Async/Await
那样同步编码,异步运行了。
快来试试这个 CoWorkerman 吧:
$ composer require paulxu-cn/co-workerman
工作原理
先上图:
写真の上部は Workerman の作業レーン図、写真の下部分は CoWorkerman の作業レーン図です。
workerman
worker プロセス
がブロッキング関数に遭遇すると、IO が返されるまで待機します。この時点で新しいリクエストがある場合、アイドル状態のワーカーはこの新しい接続をめぐって競合します。
上の図では、worker5 での AsyncTCPConnection
の使用状況を説明しました。ワーカー内で非ブロッキング リクエストが開始され、コールバック関数が登録され、プログラムは実行を継続しました。終わり。非同期リクエストが応答した場合は、別の方法で応答する必要があります (自分で別のリクエストを開始してリクエスタに通知するなど)。
下の図 CoWorkerman
には、新しいリクエストを求めて競合する複数のワーカーもあります。ワーカー 1 が新しいリクエストを受信すると、ジェネレーターが生成され、非同期リクエストがコールバックに応答し、応答を要求した後、ジェネレーターが飛び出した場所 (yield
) に戻り、コードの実行を続けます。
非同期リクエストを開始し、コールバック関数を登録します。これらのデフォルトのタスクは、
CoWorkerman
フレームワークで実行されています。コールバック関数の作業は、データの受信と送信です。リクエストを開始した人に送信されます。
#この例では、Promise:all() を呼び出すことによって複数のリクエストが開始され、結果が返されます。ジェネレーターの実行を続行する前に、すべての応答が返されるまで待ってくださいプログラム
yield が飛び出した後、ワーカーはイベント ループ状態 (
$event->loop())、つまりマルチチャネル監視になります。 : リクエスト ポート、サードパーティ クライアントの終了リクエストの応答ポート。このとき、
- に新しいリクエストがある場合、新しいリクエストをめぐって他の
- worker
と競合します。競合が発生した場合、ワーカー内に新しいジェネレータが生成されます。 。
クライアントが応答した場合、コールバック関数が呼び出されます。 - クライアントが応答した場合、ジェネレーター プログラムの実行を継続します。
Worker が 1 つしかない場合、前のリクエストが受け入れられなかった場合でも、
Worker は引き続き処理を受け入れることができると想定できます。完了しました。次のリクエストです。つまり、
CoWorkerman は単一の
Worker の下で実行でき、複数のリクエストを同時に処理できます。
もちろん、ここにも前提があります。ブロッキング機能は、単一のWorker
モードでは実行できません。一度ブロックされると、後続のリクエストはネットワーク カード上でブロックされます。したがって、コードをよく理解していない限り、サードパーティのライブラリを使用する場合は、マルチ
Workerモードで
CoWorkermanを実行することをお勧めします。また、ブロックする場合は、他の
WorkerPocket の新しいリクエストです。
CoWorkerman の意味
- 同期コードを使用して非同期リクエストを開始します。複数のリクエストを同時に実行できます。IO シリアル待機から待機に変更します。恐怖のない待ち時間を短縮するために並行して使用します。コードの可読性を低下させることなく、ビジネス プログラムの効率を向上させます。
- イベントループを1つのスレッドで行うことで、複数のリクエストを可能な限り処理することで、1リクエスト1スレッドによる頻繁なスレッド切り替えを軽減し、コアからの動作効率を向上させます。
CoWorkerman Ecological Niche
は、Workerman Gateway など、純粋な
Socket リクエストを処理するアプリケーションに適しています。 、または
大規模なフロント エンド 複数のサービスを統合する
RPC結果は
統合後の最初の 3 ページに返されますこのようなシナリオです。
ログレコードは各プログラムの最も基本的な要件であり、ファイル書き込み機能がブロッキングしているため、メッセージキューやredisキューを使用するか、同僚には限界と独自の立場があります。Logstash
をスキップして
Elasticsearch#を直接スローすることを推奨します。 ##.
概要わかりました。ネットワーク非同期コーディングまでの PHP コルーチン コーディングはこれで終わりです。この記事を読んで疑問がたくさんある場合は、お問い合わせください。
yield が文法をよく覚えていない場合は、このシリーズの前の記事を読んで復習してください。 うまくいった場合は、3回繰り返してください。
ありがとうございます!
以上がPHP 収量の高度な使用法を学ぶの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。
