php curl header_PHP中的yield与协程(二十一节)

大家好,我是老李。

顺风说骚话,逆风讲道理

最近在大家一起努力下,那个沙雕肺炎患病人数增长率下降了不少,总体来说还算顺,所以今天这篇注定又要骚话连篇了。听说最近不少玉米开始向大连、威海、烟台方向涌入,算是潜在的风险吧,总之,大家也都别放松警惕,不要看到曙光时候给撂倒了。

上一节课我们说的主要是在谢顶道人 --- 老李的提示下,你初步使用了yield...那个你没有名字也不好,给你起个名字,洋气点儿就叫欧阳吧,一听就是个贵族富少继承者们。

喊人先喊亲,要把读者叫舒心

文章别嫌少,得把客官伺候好

开工第一天,你的老板原上草又交给你一个任务并信誓旦旦地答应你如果你能顺利完成任务那么这个月的打卡迟到费就不扣你的了。强大的利好信息让你欲罢不能。事情是这样的,还是上一集那个内存只有100KB的单片机,这个单片机会访问三方服务公司的一个API,但有时候这个API会抽风,老板原上草的意思是这会儿不要阻塞等待而是让这个单片机干点儿别的事儿,等API访问OK了再让TA回来,总之别让TA闲着,算是免费送这个单片机一个满满的福报。

考虑到昨天谢顶道人曾经给你科普过的yield似乎拥有一种让出CPU实现用户调度的能力,你决定展现一波儿自我,而谢顶道人也决定用那双充满了老茧子的手手把手辅导你。

<?php function gen1() {  for( $i = 1; $i <= 10; $i++ ) {    echo "GEN1 : {$i}".PHP_EOL;    // sleep没啥意思,主要就是运行时候给你一种切实的调度感,你懂么    sleep( 1 );    // 这句很关键,表示自己主动让出CPU,我不下地狱谁下地狱    yield;  }}function gen2() {  for( $i = 1; $i <= 10; $i++ ) {    echo "GEN2 : {$i}".PHP_EOL;    // sleep没啥意思,主要就是运行时候给你一种切实的调度感,你懂么    sleep( 1 );    // 这句很关键,表示自己主动让出CPU,我不下地狱谁下地狱    yield;  }}$task1 = gen1();$task2 = gen2();while( true ) {  // 首先我运行task1,然后task1主动下了地狱  echo $task1->current();  // 这会儿我可以让task2介入进来了  echo $task2->current();  // task1恢复中断  $task1->next();  // task2恢复中断  $task2->next();}

7fa35bff58462d67bc380d4f40bcc515.png

GET不到发生了什么,是吗?就是gen1()和gen2()可以交替运行并且每次都是接着从上次的地方开始运行,你要用传统的function是完全做不到的,传统的function只能一口气先完成其中一个函数中的for()然后再能完成另外一个function中的for(),比如下面这坨:

<?php function gen1() {  for( $i = 1; $i <= 10; $i++ ) {    echo "GEN1 : {$i}".PHP_EOL;    sleep( 1 );  }}function gen2() {  for( $i = 1; $i <= 10; $i++ ) {    echo "GEN2 : {$i}".PHP_EOL;  }}gen1();gen2();// 看这里,看这里,看这里!// 上面的代码一旦运行,一定是先运行完gen1函数中的for循环// 其次才能运行完gen2函数中的for循环,绝对不会出现// gen1和gen2交叉运行这种情况

我似乎已然精通了yield

788c64ab5c7334d3da9df2c4e3f261d2.gif

好了欧阳,让我们展示真正的技术吧!下面这个demo,如果访问某个API阻塞的话就主动让出CPU,然后让出的CPU开始往一个文件里写字符串...反正不能让TA闲着:

<?php $ch1 = curl_init();// 这个地址中的php,我故意sleep了5秒钟,然后输出一坨jsoncurl_setopt( $ch1, CURLOPT_URL, "http://www.selfctrler.com/index.php/test/test1" );curl_setopt( $ch1, CURLOPT_HEADER, 0 );$mh = curl_multi_init();curl_multi_add_handle( $mh, $ch1 );// gen1中就是调用三方API,基于multi-curl实现function gen1( $mh, $ch1 ) {  do {    $mrc = curl_multi_exec( $mh, $running );    // 请求发出后,让出cpu    $rs = yield;    // 生产环境千万别这么干......    // 这里加sleep是为了让你看的更清楚流程    sleep( 1 );    echo "收到外部发送数据{$rs}".PHP_EOL;      } while( $running > 0 );  $ret = curl_multi_getcontent( $ch1 );  echo $ret.PHP_EOL;  return false;}// gen2是写文件...function gen2() {  for ( $i = 1; $i <= 10; $i++ ) {    echo "gen2 : {$i}".PHP_EOL;    file_put_contents( "./yield.log", "gen2".$i.PHP_EOL, FILE_APPEND );    $rs = yield;    // 生产环境千万别这么干......    // 这里加sleep是为了让你看的更清楚流程    sleep( 1 );    echo "收到外部发送数据{$rs}".PHP_EOL;      }}$gen1 = gen1( $mh, $ch1 );$gen2 = gen2();while( true ) {  echo $gen1->current();  echo $gen2->current();  $gen1->send("gen1");  $gen2->send("gen2");}

上面这坨代码在飞起来后,我们再等待curl发起请求的5秒钟内,同时可以完成文件写入功能,如果换做平时的PHP程序,就只能是先阻塞等待curl拿到结果后才能完成文件写入,有了一丝丝内味儿了吗?

协程味儿

但是这里必须要值得注意的是,欧阳在gen1()的代码里用的并不是我们一般时候用的curl方法,而是curl_multi_exec(),为啥呢?因为一般般我们最常用的PHP curl方法都是阻塞的,这很致命,这里要点就是:全程不能阻塞,阻塞一处死翘翘。实际上这里最标准的用法就是curl_multi_exec()配合curl_multi_select()。所以,扩散一下思维如果你用file_get_contents()也是不行的。

下面由谢顶道人总结一个PHP中yield的典型使用方法:如果要使用yield实现「异步」,实际上在PHP里也只能是结合select或epoll这些IO服用,具体就是当IO没有ready的时候,yield出让CPU去做别的事情,一旦IO ready了就回来继续执行原来的任务,说白了就是协程调度器!

???

那TM我要这yield到底有啥用?谢顶道人你咋这幽默呢?感觉蒙娜丽莎都是你逗笑的呢~我直接用之前章节里基于libevent实现的服务器不就挺好用的吗?这里要说的就是「基于IO复用实现的异步非阻塞服务器中难以避免的异步回调地狱」写法,说白了就是一层又一层嵌套的on。这在NodeJS里颇为常见,所以后来NodeJS出了一个叫做Promise的关键字来缓解这个问题,这里你可以粗暴的认为yield就是PHP版本的Promise,就是传说中的「用传统同步代码的写法写异步」,但也依然能写出高IO的程序。

世面上有什么典型作品吗?有啊,swoole呀,swoole协程就是基于epoll实现的协程调度器;还有微信开源的libco也基本上是基于IO复用实现的协程调度器。要注意的基于epoll实现协程调度器只是一种实现方式而已,像Golang则是完全是自己在上层实现的调度器。

好看的皮囊就是好看,有趣的灵魂爱咋咋滴...

68a5592947b988c0c59fba1c52701740.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/504357.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用稳压管保护单片机引脚_一步一步,全程揭开单片机的原理,让做电子变得轻松自如!...

学习单片机必要的硬件学习单片机都需要什么&#xff1f;首先要掌握必要的电子基础知识&#xff1b;再次选择大众化、性价比高的单片机&#xff0c;熟悉它的引脚功能定义&#xff1b;另外还需要电脑与下载程序的下载器。一、单片机建议选择型号为STC89C52RC单片机&#xff0c;如…

python word 表格宽度_RPA手把手——python-docx 设置 word 文档中表格格式

艺赛旗|做RPA生态先行者 RPA10.0全新首发免费下载 点击下载 引入会用到的库 from docx import Document from docx.shared import Pt from docx.enum.text import WD_PARAGRAPH_ALIGNMENT from docx.shared import Cm from docx.shared import RGBColor 表格样式 #方法一&#…

软引用和弱引用的区别_强、软、弱、虚引用的区别和使用

原文阅读&#xff1a;强、软、弱、虚引用的区别和使用​mp.weixin.qq.comJava提供了四种级别的应用类型&#xff1a;强引用、软引用、弱引用及虚引用。那么这四种引用类型有什么区别呢&#xff1f;首先我们通过一张图来看看四种引用在Java中的表示&#xff1a;FinalReference由…

python文本文件不能用二进制文件方式读入_如何使用python函数以二进制形式读取文件?...

虽然读取文件的方式各种各样&#xff0c;但是通过二进制&#xff0c;还是头一次&#xff0c;实现过过程并不难&#xff0c;我们需要将文件先做好封存&#xff0c;以函数的形式&#xff0c;保存下来&#xff0c;然后直接导入进行使用&#xff0c;这样就可以读取文件&#xff0c;…

一组数字中算出最相近的组合_据说在金字塔里发现的这组数字,貌似是通往宇宙的密码...

我们都知道阿拉伯数字是全世界都在用的计数单位的数字&#xff0c;我们的生活离不开阿拉伯数字&#xff0c;其广泛性很大。比如买菜、买衣服。做数学题等等都需要用到。不过呢早前有人称在埃及金字塔内发现了一组数字142857&#xff0c;这组数字貌似就是通往宇宙的密码。这一说…

前端悬浮窗效果_Flutter自绘组件:微信悬浮窗(一)

看微信公众号的时候时常会想退出去回复消息&#xff0c;但又不想放弃已经阅读一半的文章&#xff0c;因为回复信息后再从公众号找到该篇文章之间有不必要的时间花费&#xff0c;微信悬浮窗的出现解决了这个烦恼&#xff0c;回复完消息之后只需要点击悬浮窗就可以回到之前在阅读…

date类型_Quartz与Date---cron的相互转换

产生原因:因为项目最近设计到了一个Quartz相关的模块&#xff0c;前端需要传递时间参数到后台, 然后后台设置一个新的定时任务, 所以后台需要一个可以实现Date与cron之间的相互转换(因为Quartz需要的Cron格式的数据)&#xff0c;所以就借助java的SimpleDateFormat的格式化,然后…

vbs if 不等于_6、if语句和关系表达式

示例3.1&#xff1a;星星公司致力于信件快递业务&#xff0c;收费标准是&#xff1a;500g以内6元&#xff0c;超过500g9元。应该就是输入重量&#xff0c;显示钱&#xff0c;那可以用cout和cin&#xff0c;如果w小于500&#xff0c;c是6&#xff0c;否则&#xff0c;c是9。//pr…

python文件是怎么写_python头文件怎么写

本文主要以python2为例。首先介绍一下Python头文件的编程风格&#xff0c;然后再给大家详细介绍import部分的基本用法。这两个部分就是Python中头文件的组成模块。编程风格#!/usr/bin/env python #在文件头部 ( 第一行 ) 加上 设置 Python 解释器 # -*- coding: utf-8 -*- #在文…

【学习笔记】第二章——处理机调度的概念、层次、时机、切换过程 调度方式、调度算法的指标

文章目录一. 概念 & 层次1. 高级调度&#xff08;作业调度&#xff09;2. 中级调度&#xff08;内存调度&#xff09;挂起态 & 七状态模型3. 低级调度&#xff08;进程调度&#xff09;4. 三种调度的对比联系 && 总结二. 时机、切换过程 & 调度方式1. 进程…

formdata上传文件_关于multipart/formdata上传文件

最近在做一个文件上传的开放接口&#xff0c;用到Content-Type: multipart/form-data这种请求类型&#xff0c;特地做了一些研究和记录。在最初的 http协议中&#xff0c;并没有上传文件方面的功能。RFC1867为 http协议添加了这个能力。常见的浏览器&#xff0c;如 Microsoft I…

【学习笔记】第二章——调度算法:先来先服务FCFS、短作业优先SJF、高响应比HRRN

文章目录一. 先来先服务&#xff08;FCFS&#xff09;二. 短作业优先&#xff08;SJF&#xff09;三. 高响应比优先1. 对前面两种算法的思考2. 描述四. 一、二、三总结例子都要手动写一遍哦&#xff5e;这三个是供早期的批处理系统使用的算法 一. 先来先服务&#xff08;FCFS&a…

【学习笔记】第二章——时间片轮转RR、优先级调度、多级反馈队列调度算法

文章目录一. 时间片轮转二. 优先级调度三. 多级反馈队列调度算法四. 总结一. 时间片轮转 公平&#xff0c;轮流给进程提供时间片只用于进程调度&#xff08;只有进程才能被分配时间片&#xff09;抢占式&#xff0c;由时钟装置发出时钟中断来通知**缺点&#xff1a;**高频的进…

laravel 分词搜索匹配度_elasticsearch基础笔记9-elasticsearch 词项全文搜索

es的核心功能就是搜索和分析。那么我们看看搜索相关内容1、搜索机制在进入搜索之前&#xff0c;会对查询体根据情况进行分析和处理。2、有哪些常用搜索类型全文查询 词项查询 复合查询 嵌套查询 位置查询 特殊查询等。我们常用到的就是前三种&#xff0c;学起来简单&#xff0c…

【学习笔记】第二章——进程同步、进程互斥、进程互斥的硬件/软件实现方法

文章目录一. 进程同步 && 进程互斥四个区域四个原则总结&#xff1a;二. 进程互斥的软件实现方法1&#xff09;单标志法2&#xff09;双标志先检查法3&#xff09;双标志后检查法4&#xff09;Peterson 算法总结三. 进程互斥的硬件实现方法1&#xff09;中断屏蔽方法2&…

python的数据结构包括那些_python算法与数据结构-什么是数据结构

一、什么是数据结构 数据结构&#xff0c;直白地理解&#xff0c;就是研究数据的存储方式。 我们知道&#xff0c;数据存储只有一个目的&#xff0c;即为了方便后期对数据的再利用&#xff0c;就如同我们使用数组存储 {1,2,3,4,5} 是为了后期取得它们的值&#xff0c;因此&…

seo自动发外链_一套节约成本全网营销方案-小小课堂SEO培训教程

很多公司都是由一些小型工作室或个人工作室慢慢发展而来的&#xff0c;在这过程中&#xff0c;人员、资金链、资源、项目等因素一旦出现问题&#xff0c;可能会导致项目失败&#xff0c;那么在互联网上投入的资金如果过多&#xff0c;可能都是白白打了水漂。今天&#xff0c;小…

python 支付宝个人账单_金融支付财务融合业务-实践分享1:订单、账单、交易流水、账套知识解构、原理解析...

本文作者从实际工作实践出发&#xff0c;结合案例等分享了电商金融支付财务融合中的基本概念和相关原理解析&#xff0c;包括&#xff1a;订单、账单、交易流水和账知识解构&#xff0c;供大家一同参考和学习。从事电商、进销存、金融、支付、财务的产品同学&#xff0c;是否对…

【学习笔记】第二章——信号量机制 用信号量实现互斥、同步

文章目录一. 信号量机制整型信号量记录型信号量例子&#xff1a;总结二. 用信号量实现互斥、同步互斥同步前驱总结一. 信号量机制 信号量&#xff1a;一个用于表示系统中某种资源的数量的变量&#xff08;整数 or 记录型变量&#xff09;一对原语&#xff1a;wait(S) 和 signa…

opengl 安装_一步步学OpenGL(34) -《GLFX,一个OpenGL效果库》

教程 34GLFX,一个OpenGL效果库原文&#xff1a; http://ogldev.atspace.co.uk/www/tutorial34/tutorial34.htmlCSDN完整版专栏&#xff1a; https://blog.csdn.net/cordova/article/category/9266966理论介绍这篇教程暂时先不继续探索OpenGL的特性和3D技术了&#xff0c;来介绍…