🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 请求 web应用给我们的感知都是以请求的方式呈现和运行的。 比如浏览器的表单提交,ajax请求,socket请求,服务端php的curl从一个服务器对另一个服务器的请求。 请求无处不在,请求支撑着我们日常的所有网络应用,不论是app还是网站的,这些都是网络应用,想要运行都离不开请求。 * * * * * ### TODO ajax相应一定要等到服务器完全响应断开连接才可以吗,如果服务器不断开连接,一直flush()推送呢,客户端能源源不断的收到信心吗? [php死循环代码一直在运行? - 知乎](https://www.zhihu.com/question/46275054/answer/136984342) [0714/2013 作业及预习+代码+视频 - 历史视频及代码 自学it网-公益PHP培训!](http://www.zixue.it/forum.php?mod=viewthread&tid=7820&extra=page%3D2%26filter%3Dtypeid%26typeid%3D35%26typeid%3D35) [实现Comet(服务器推送)的两种方式:长轮询和http流_蔡武坤的博客-CSDN博客](https://blog.csdn.net/weixin_39181833/article/details/79723745) > XMLHttpRequest 可以不断监听使用 xhr.readyState == 3 [xiasf - comet - Coding.net](https://coding.net/u/xiasf/p/comet/git) > 原来ajax是服务端推送一次就断开了,得再重新发起一次ajax,但是其阻塞了请求也是有意义的,而不是客户端一个定时器每隔一个固定的时间去请求,这样效率是最低的(不能预知,什么时候到达,请求什么时候返回,有可能同时,无法控制顺序)。(**这样也实现了【单例请求】,不会造成并发请求,“并发”更新UI的问题**) [ajax、反向ajax、jsonp详解 - CSDN博客](http://blog.csdn.net/kabulore/article/details/51910978) [反向AJAX - CSDN博客](http://blog.csdn.net/lccone/article/details/7743886) > Comet 这些技术不能大规模使用,因为占用了用于处理响应的进程(php-fpm),最终会导致并发能力越来越低,服务不可用的。 ~~~ **实时信息很难从技术上解决。** …… Comet(服务器推) 第二种主动式反向Ajax方法是Comet,这是一种基于HTTP长连接的服务器推动方式。客户端向服务器发送请求后,服务器将数据通过response发送给客户端,但并不会将此response关闭,而是一直通过response将最新的数据发送给客户端浏览器,直到客户端浏览器关闭。 ~~~ >[danger] 服务器会阻塞请求,而不马上断开连接,而客户端也能源源不断的收到信息。 [30分钟学会反向Ajax - 冷豪 - 博客园](http://blog.csdn.net/kabulore/article/details/51910978) [网页实时聊天之js和jQuery实现ajax长轮询 - 枕边书 - 博客园](https://www.cnblogs.com/zhenbianshu/p/4964095.html) ![](http://cdn.aipin100.cn/18-7-2/22155054.jpg) > #### 长轮询的思想: > > 如图:用AJAX发送询问信息,服务器在没有信息要返回的时候进入无限等待。由于AJAX异步的特性,PHP在服务器端执行等待不会影响到页面的正常处理。一旦服务器查询到返回信息,服务器返回信息,AJAX用回调函数处理这条信息,同时迅速再次发送一个请求等待服务器处理。 > > 与 **传统轮询(简易轮询)** 相比,长轮询在服务器没的返回信息的时候进入等待,减少了普通轮询服务器无数次的空回复。**可以这样认为,长轮询 使服务器每次的返回更有目的性,而不是盲目返回。** [Comet技术详解:基于HTTP长连接的Web端实时通信技术 - helloJackJiang - 博客园](https://www.cnblogs.com/imstudy/p/5696033.html) ~~~ “服务器推”是一种很早就存在的技术,以前在实现上主要是通过客户端的套接口,或是服务器端的远程调用。因为浏览器技术的发展比较缓慢,没有为“服务器推”的实现提供很好的支持,在纯浏览器的应用中很难有一个完善的方案去实现“服务器推”并用于商业程序。最近几年,因为 AJAX 技术的普及,以及把 IFrame 嵌在“htmlfile“的 ActiveX 组件中可以解决 IE 的加载显示问题,一些受欢迎的应用如 meebo,gmail+gtalk 在实现中使用了这些新技术;同时“服务器推”在现实应用中确实存在很多需求。因为这些原因,基于纯浏览器的“服务器推”技术开始受到较多关注,Alex Russell(Dojo Toolkit 的项目 Lead)称这种 **基于 HTTP 长连接、无须在浏览器端安装插件的“服务器推”技术为“Comet”。** 使用 AJAX 实现“服务器推”与传统的 AJAX 应用不同之处在于: 服务器端会阻塞请求直到有数据传递或超时才返回。 客户端 JavaScript 响应处理函数会在处理完服务器返回的信息后,再次发出请求,重新建立连接。 当客户端处理接收的数据、重新建立连接时,服务器端可能有新的数据到达;这些信息会被服务器端保存直到客户端重新建立连接,客户端会一次把当前服务器端所有的信息取回。 ~~~ [feed留,单聊群聊,系统通知,状态同步,到底是推还是拉?](https://mp.weixin.qq.com/s/54yEWWet9mFztv1fO_GTqQ) > 大部分webim(特别是同时在线量大的)是http轮询请求,后续撰文 [WEB即时通信最佳实践](https://mp.weixin.qq.com/s/t1YkuDxUessq5bfials4gw) * * * * * ### 实现单例请求 要用自循环/自调用方式来发出请求,而不能用定时器,这样就能保证请求的顺序性,保证每一时刻只有一个请求,请求中或等待响应。 伪代码: ```javascript function get(cb) { $.ajax(data, function() { cb(get); }); } get(get); ``` [为什么尽量别用 setInterval](https://mp.weixin.qq.com/s/8An8mfJQaursg4lDdoPayg) > 无视网络延迟:它仍然会按定时持续不断地触发请求,最终你的客户端网络队列会塞满Ajax调用。 * * * * * ### 夯住! [http如何像tcp一样实时的收消息?](https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651959605&idx=1&sn=21f25087bef3c3a966ef03b824365621&scene=4&rd2werd=1#wechat_redirect) > 没有消息到达的时候,**这个http消息连接将被夯住,不返回,由于http是短连接,这个http消息连接最多被夯住90秒**,就会被断开(这是浏览器或者webserver的行为) > > webim通过http长轮询可以保证消息的绝对实时性。这种实时性的保证不是通过增加轮询频率来保证的,而是通过夯住http消息连接来保证的 [网页端收消息,究竟是推还是拉?](https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651961175&idx=1&sn=4e74348e9e6c20aa11bf55949b24e20a&scene=0#wechat_redirect&rd2werd=1#wechat_redirect) > 不像普通的“请求-响应”式HTTP请求,这个HTTP会被服务端夯住,直到有推送通知到达,或者超过约定的时间 [秒杀系统架构优化思路](https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651959391&idx=1&sn=fb28fd5e5f0895ddb167406d8a735548&scene=4&rd2werd=1#wechat_redirect) > 用户层面肯定是同步的(用户的http请求是夯住的),服务层面可以同步可以异步。 [webim如何用轮询保证消息绝对实时](https://mp.weixin.qq.com/s/VOSQLXBb7f1CZHj1dPRi3A) > 没有消息到达的时候,这个http消息连接将被夯住,不返回,由于http是短连接,这个http消息连接最多被夯住90秒,就会被断开(这是浏览器或者webserver的行为) [58到家数据库30条军规解读](https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=2651959906&idx=1&sn=2cbdc66cfb5b53cf4327a1e0d18d9b4a&chksm=bd2d07be8a5a8ea86dc3c04eced3f411ee5ec207f73d317245e1fefea1628feb037ad71531bc&scene=4&rd2werd=1#wechat_redirect) > 无主键的表删除,在row模式的主从架构,会导致备库夯住 * * * * * ### http 常见的就是http请求了,这是应用层的协议,之上链路层就是TCP、IP了。 我们用浏览器打开网页就是http请求。 ajax也是http请求。 常用的curl也是http请求。 关于请求,我们需要知道的,请求包含哪些重要的信息: - 请求地址 - 请求头(协议头信息,包含 Query String Parameters) - body(Form Data) - 数据编码(发送数据的数据编码,默认表单为 `Content-Type:application/x-www-form-urlencoded`) - <del>数据格式(发送数据的数据格式)</del> - 期望返回的数据格式(Accept) 注意:要分开理解数据编码和字符编码的概念。 Content-type: application/x-www-form-urlencoded; charset=UTF-8 (数据类型,数据编码) **Accept: \*/\*:** 客户端可以使用Accept字段声明自己可以接受哪些数据格式,也表示客户端期望接受到什么类型的数据格式。 * * * * * >[danger] 服务器端想要实现“异步”(返回数据给浏览器,并断开与浏览器的连接,但是后端服务不停止,继续运行),如果想实现这样,服务端必须做一些处理才行,参见参考资料。 >[danger] 服务端完全响应完,浏览器才能收到200的状态(只有浏览器和后端断开连接了,ajax才能算是响应完成,不然一直加载的状态,即使是有数据不断flush输送过来了) * * * * * ### socket 待续 * * * * * ### 参考 [HTTP 协议超详细讲解](https://www.toutiao.com/a6506706975080841732/?tt_from=weixin&utm_campaign=client_share&timestamp=1514976679&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1) [HTTP,HTTP2.0,SPDY,HTTPS你应该知道的一些事 - WEB前端 - 伯乐在线](http://web.jobbole.com/87695/) [专题 | JerryQu 的小站](https://imququ.com/post/series.html) [Http协议的详细总结](https://www.toutiao.com/a6516479528183792131/?tt_from=weixin&utm_campaign=client_share&timestamp=1517277124&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1) [http简介](https://segmentfault.com/a/1190000009744707#articleHeader3) [理解HTTP之Content-Type](https://segmentfault.com/a/1190000003002851) [一文带你了解 HTTP 黑科技](https://mp.weixin.qq.com/s/UWYe_3hcnClvsLvFJRBztA) [jQuery Ajax 操作函数](http://www.w3school.com.cn/jquery/jquery_ref_ajax.asp) [jQuery ajax - ajax() 方法](http://www.w3school.com.cn/jquery/ajax_ajax.asp) [HTML \<form\> 标签](http://www.w3school.com.cn/tags/tag_form.asp) [文字编码的那些事 – 人人网FED博客](https://fed.renren.com/2017/11/11/text-encode/) [【底层原理】字符集和字符编码(上)](https://mp.weixin.qq.com/s/DwsXrnq_-Mjw8hVekPZ4LQ) [HTML URL 编码](http://www.w3school.com.cn/tags/html_ref_urlencode.html) [常用对照表 - Mime-Type](http://tool.oschina.net/commons) [AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式](http://blog.csdn.net/mhmyqn/article/details/25561535) [PHP获取POST数据的三种方法](http://blog.csdn.net/jiao_fuyou/article/details/46314727) [钉钉开放平台文档中心 - 建立连接](https://open-doc.dingtalk.com/docs/doc.htm?spm=a219a.7629140.0.0.uzGzqQ&treeId=385&articleId=104980&docType=1) >[danger] POST请求请在HTTP Header中设置 Content-Type:application/json,否则接口调用失败 [HTTP协议系列五—结合报文和Wireshark再谈TCP三次握手](https://www.toutiao.com/a6508678486687744519/?tt_from=weixin&utm_campaign=client_share&timestamp=1515523641&app=news_article&utm_source=weixin&iid=22069500288&utm_medium=toutiao_android&wxshare_count=1) [HTTPS为什么安全? - CSDN博客](http://blog.csdn.net/xifeijian/article/details/54667989) [技术轮回,静态Web再度成为新趋势?](https://mp.weixin.qq.com/s/JrsJiO_B8wJDjLqKN7awkQ) [淘宝服务端高并发分布式架构演进之路](https://mp.weixin.qq.com/s/rAJfL6ykQYtBi0iTazptuQ) [可用性高达5个9!支付系统高可用架构设计实战](https://mp.weixin.qq.com/s/h8puL7jTE9YYOXO-mwWu3Q) [被吹得天花乱坠的无服务器架构究竟是什么鬼?](https://mp.weixin.qq.com/s/2n_vYhnlP27FK9_cH8pZFQ) [「ThinkPHP开发者周刊」第40期——高并发](https://mp.weixin.qq.com/s/yeleXMzL2SRYpyOmZv4XDQ) > Laravelv6 发布 —— 引入部署平台 Vapor [如何将Web主页性能提升十倍以上?](https://mp.weixin.qq.com/s/_DxXom8wI_eRlztci0Hj-w) [详解三次握手和四次挥手:遇到心动的女孩时,如何去把握?](https://mp.weixin.qq.com/s/cFiXzkelFaed50l_A0ummA) [LVS四种实现模式详解](https://mp.weixin.qq.com/s/1bXTMG7QtEQsoEjdHSwXsw) [通俗易懂的Nginx工作原理](https://mp.weixin.qq.com/s/FBdasszBrVAqgLGXxuge2w) [Linux惊群相关问题分析](https://mp.weixin.qq.com/s/ExRqSTBQ1_Z82SdgVUhOwg) [揭开 asyncio 的神秘面纱 :从 hello world 说起](https://mp.weixin.qq.com/s/ltORoBfRowAR8iXYD3NDQw) > asyncio 是用来编写并发程序的库。在爬虫、客户端应用等开发场景中, 我们经常会需要将多个网络请求并行化来提高程序性能,而 asyncio 框架正好可以很方便的帮助我们实现这个需求。 [史上最污技术解读,我竟然秒懂了](https://mp.weixin.qq.com/s/Ueh1QubRUkfDDP-ujAytUg) [不要相信requests返回的text](https://mp.weixin.qq.com/s/ueDhUwAB1yipsOQsKEAqNQ) [九种跨域方式实现原理](https://mp.weixin.qq.com/s/LV7qziMyrMt0_EJWo05qkA) [如何给女朋友解释为什么200M宽带,打王者荣耀还是会卡?](https://mp.weixin.qq.com/s/4QFAcSY7Ode5NLijLwFUfA) * * * * * [访问式的web服务(二)](https://www.kancloud.cn/xiak/php-node/491960) > 关于提交了关闭浏览器会出现的问题分析。 * * * * * [Http 历险记(上)](https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513069&idx=1&sn=548c497c46c7c076145064a120c7c101&scene=21#wechat_redirect) [Http历险记(下)-- Struts的秘密](https://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExNg==&mid=2665513080&idx=1&sn=d24a4cdfc71412c581393d584fd91326&scene=21#wechat_redirect) * * * * * [AJAX POST请求中参数以form data和request payload形式在servlet中的获取方式 - 痴人说梦 - CSDN博客](http://blog.csdn.net/mhmyqn/article/details/25561535) ~~~ 2015-04-17后记: 最近在看书时才真正搞明白,服务器为什么会对表单提交和文件上传做特殊处理,因为表单提交数据是名值对的方式,且Content-Type为application/x-www-form-urlencoded,而文件上传服务器需要特殊处理,普通的post请求(Content-Type不是application/x-www-form-urlencoded)数据格式不固定,不一定是名值对的方式,所以服务器无法知道具体的处理方式,所以只能通过获取原始数据流的方式来进行解析。 jquery在执行post请求时,会设置Content-Type为application/x-www-form-urlencoded,所以服务器能够正确解析,而使用原生ajax请求时,如果不显示的设置Content-Type,那么默认是text/plain,这时服务器就不知道怎么解析数据了,所以才只能通过获取原始数据流的方式来进行解析请求数据。 ~~~ [PHP获取未知MIME类型(如text/xml)的请求数据 - 步知道 - CSDN博客](http://blog.csdn.net/luochuan/article/details/8282436) ~~~ PHP默认识别的数据类型是application/x-www.form-urlencoded标准的数据类型,我们在接收这种常规的数据类型的时候可以用全局数组$_REQUEST、$_POST或者$_GET来获取客户端请求的数据。 如果遇到未识别MIME类型的请求数据,如Content-Type=text/xml 类型或者直接POST一个JSON数据流,那么php要怎么获取数据呢,PHP文档里是这么描述的: The RAW / uninterpreted HTTP POST information can be accessed with: $GLOBALS['HTTP_RAW_POST_DATA'] This is useful in cases where the post Content-Type is not something PHP understands (such as text/xml). 由于PHP默认只识别application/x-www.form-urlencoded标准的数据类型,因此,对型如text/xml的内容无法解析为$_POST数组,故保留原型,交给$GLOBALS['HTTP_RAW_POST_DATA'] ($HTTP_RAW_POST_DATA)来接收。 注意:此变量仅在碰到未识别 MIME 类型的数据时产生,$HTTP_RAW_POST_DATA 对于 enctype="multipart/form-data" 表单数据不可用。 ~~~ [http头部content-type与数据格式 - Trifling_的博客 - CSDN博客](http://blog.csdn.net/trifling_/article/details/53009500) [HTTP协议详解(真的很经典) - Hundre - 博客园](http://www.cnblogs.com/li0803/archive/2008/11/03/1324746.html) [popen——php多进程利器 - CSDN博客](https://blog.csdn.net/leinchu/article/details/8191067) [php中popen,exec,system,passthru到底有多大区别 - CSDN博客](https://blog.csdn.net/fishg/article/details/6138348) [PHP 调用系统外部命令 system() exec() passthru() 和 popen() - CSDN博客](https://blog.csdn.net/wzhwho/article/details/6944019) [php - popen如何实现多进程并发执行,循环里的pclose会等待进程完毕再进行下一次循环 - SegmentFault 思否](https://segmentfault.com/q/1010000007205306?_ea=1273185) [php - popen函数调本地脚本并传参数 - SegmentFault 思否](https://segmentfault.com/q/1010000006160351) [使用fsockopen()实现异步调用PHP - CSDN博客](https://blog.csdn.net/lzr77/article/details/16369863) > ……当 PHP 脚本正常地运行 NORMAL 状态时,连接为有效。当客户端中断连接时,ABORTED 状态的标记将会被打开。远程客户端连接的中断通常是由用户点击 STOP 按钮导致的。当连接时间超过 PHP 的时限(请参阅 set_time_limit() 函数)时,TIMEOUT 状态的标记将被打开。…… [php fsockopen()方法,简化,异步非阻塞调用 - CSDN博客](https://blog.csdn.net/qq_22823581/article/details/77712987) [PHP触发耗时脚本 - SegmentFault 思否](https://segmentfault.com/q/1010000004593434) [PHP fsockopen函数问题,本脚本无阻塞触发其他脚本失败 - SegmentFault 思否](https://segmentfault.com/q/1010000004590173?_ea=660163) [一文读懂 HTTP 2.0 之服务器推送](https://mp.weixin.qq.com/s/YQCSJQpfnSENpzVpO5YAZg) [【协议森林】从理论到实践,全方位认识DNS(理论篇)](https://mp.weixin.qq.com/s/wzO1yUQGYXge7eTnZMqz0g) [一个秒杀系统的设计思考](https://mp.weixin.qq.com/s/a_xiXBUbpIZ3HtuYvdYSPA) * * * * * [php://input - 简单--生活 - 博客园](http://www.cnblogs.com/xiangxiaodong/archive/2012/11/07/2758685.html) [PHP: php:// - Manual](http://php.net/manual/zh/wrappers.php.php) [JS 服务器推送技术 WebSocket 入门指北](https://mp.weixin.qq.com/s/IRH0Y8wJjGKsydRWJ6KH7g) [我遇过的最难的Cookie问题](https://mp.weixin.qq.com/s/UxySd528XMxsyD7GBC96EQ) [Web 实时推送技术的总结](https://mp.weixin.qq.com/s/23unZJrMP9sVe5PTCApzGQ) [网页端收消息,究竟是推还是拉?](https://mp.weixin.qq.com/s/Z_xItxDUmUJO-W3bgYwb5Q) > 不像普通的“请求-响应”式HTTP请求,这个HTTP会被服务端夯住,直到有推送通知到达,或者超过约定的时间 [系统通知,居然有人使用拉取?](https://mp.weixin.qq.com/s/cFtFQb4-9__Jqw6wTinftw) > 拉 其实就是web访问式服务了。 [双机热备的原理](https://mp.weixin.qq.com/s/mKkLJLr_XF_M-gkFr4jTyg) [DNS原理入门](https://mp.weixin.qq.com/s/tROPiINO4Rj1pyNBsNhvlw) [群消息已读回执(这个diao),究竟是推还是拉?](https://mp.weixin.qq.com/s/fQhmrrJ0jypm_O3WFs7ftw) > 聊天消息只需要记录偏序,这条消息之前未读,就可以,而通知类消息需要记录每一条消息的阅读状态。 [群消息,究竟存1份还是多份?](https://mp.weixin.qq.com/s/1Pd0vhDu8lh9bpvKGQqLVA) [网页端收消息,究竟是推还是拉?](https://mp.weixin.qq.com/s/Z_xItxDUmUJO-W3bgYwb5Q) [不懂RPC,休谈微服务](https://mp.weixin.qq.com/s/dohsfOBkl2dGbOyQp1WpnQ) ~~~ 服务端可以提供api调用,为什么还需要RPC呢? 作者 如果对性能要求较高,就可以使用RPC。 ~~~ * * * * * ### php中实现异步的奇淫巧技 [php提前响应请求继续执行代码(伪异步)-仙士可博客,技术博客,php,技术分享](http://www.php20.cn/article/159) [PHP主动断开与浏览器的连接](http://blog.csdn.net/dodott/article/details/54629180) [PHP 在 Nginx 下主动断开连接 Connection Close 与 ignore_user_abort 后台运行 - 蜗牛的专栏 - CSDN博客](http://blog.csdn.net/zhouzme/article/details/46886811) [关于PHP连接处理中set_time_limit()、connection_status()和ignore_user_abort()深入解析 - 很多时候,你缺少的不是知识而是热情 - CSDN博客](http://blog.csdn.net/jiao_fuyou/article/details/17138057) [php输出缓冲与http的联系](http://mp.weixin.qq.com/s/DNbdCSj0RhalQGVyKTUnGA) > 其实这样**治标不治本**,因为fpm能力有限,你这儿占住了,那其他请求怎么办,所以这不能真正解决问题。 >[tip] 这样治标不治本,虽然前端收到完整的响应断开连接了,但是后端服务并未就此结束,会一直占用当前php-fpm,这将导致系统的并发能力降低,任何时候都要考虑代码的运行方式和运行环境,脱离这个前提,讨论别的就是错的,没有意义。 [加速PHP的ECHO | 风雪之隅](http://www.laruence.com/2011/02/13/1870.html) > 这也就引出了今天我要谈的这个问题, 如何让ECHO变快, 让PHP的请求处理过程, 尽快结束… > > 最后要说明, 这样做, 只是把原来ECHO的等待时间, 转移给了Apache, 并没有真正的减少客户端获取到内容的时间. 它只是加速了PHP的处理过程, 提前了PHP的退出时机, 从而能减少PHP对资源的占用时间, 间接增加资源的占用率. [使用fastcgi_finish_request提高页面响应速度 | 风雪之隅](http://www.laruence.com/2011/04/13/1991.html) > 当PHP运行在FastCGI模式时,PHP FPM提供了一个名为fastcgi_finish_request的方法.按照文档上的说法,此方法可以提高请求的处理速度,如果有些处理可以在页面生成完后再进行,就可以使用这个方法. > > 这样一下,像登录的话,可能涉及很多复杂的东西可以我们可以放在”**伪后台执行**(fastcgi_finish_request)”, 但是如果数量多的话, 就会出现超时的现象, 可以在头部加入set_time_limit(0); * * * * * ### 扩展 常规下,**php代码写出来的都是同步代码**(即服务端代码一行一行按顺序执行,全部执行完毕,返回给浏览器,并断开与浏览器的连接,也就是 **服务端完全响应完,浏览器才能收到200的状态**)。 但是通过一些技巧,可以实现所谓的异步,上面有讲到。 [guzzle/guzzle](https://github.com/guzzle/guzzle) 里面有异步的curl请求,这是怎么做到的呢? ```php // Send an asynchronous request. $request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org'); $promise = $client->sendAsync($request)->then(function ($response) { echo 'I completed! ' . $response->getBody(); }); $promise->wait(); ``` 有时间再去研究一下,不过目前猜测很可能就是通过上面说的那种技巧实现的。 猜测也不对,curl是在服务端发起的,这种技巧应该不行的。 [PHP实现执行定时任务的几种思路详解 - Web烤猫 - SegmentFault](https://segmentfault.com/a/1190000002955509) > fsockopen可以实现在请求访问某个文件时,不必获得返回结果就继续往下执行程序,这是和curl通常用法不一样的地方,**我们在使用curl访问网页时,一定要等curl加载完网页后,才会执行curl后面的代码,虽然实际上curl也可以实现“非阻塞式”的请求,但是比fsockopen复杂的多,所以我们优先选择fsockopen**,fsockopen可以在规定的时间内,比如1秒钟以内,完成对访问路径发出请求,完成之后就不管这个路径是否返回内容了,它的任务就到这里结束,可以继续往下执行程序了。利用这个特性,我们在正常的程序流中加入fsockopen,对上面我们创建的这个定时任务php的地址发出请求,即可让定时任务在后台执行。如果上面这个php的url地址是www.yourdomain.com/script.php,那么我们在编程中,可以这样: [PHP非阻塞模式 | 尘缘的博客](http://www.4wei.cn/archives/1002336) [简单介绍PHP非阻塞模式_php实例_脚本之家](http://www.jb51.net/article/80381.htm) [PHP的非阻塞或并行请求实现方式 - 简书](https://www.jianshu.com/p/7a15f974657d) [php非阻塞访问url 解析socket阻塞与非阻塞,同步与异步 - 橙虚缘空间 - CSDN博客](http://blog.csdn.net/qq43599939/article/details/50570098) [PHP异步:在PHP中使用 fsockopen curl 实现类似异步处理的功能 - Web烤猫 - SegmentFault 思否](https://segmentfault.com/a/1190000002982448) [PHP HTTP客户端-Guzzle原理解析](https://mp.weixin.qq.com/s/Qr1mCwrpnu2cOPuJP6ID5w) [PHP中用简单征服复杂,fsockopen函数实现多进程并发](https://www.toutiao.com/a6389852540971892994/?tt_from=weixin&utm_campaign=client_share&wxshare_count=1&timestamp=1538709320&app=news_article_lite&utm_source=weixin&iid=33124962994&utm_medium=toutiao_android&group_id=6389852540971892994) > fsockopen 无阻塞并发调用,精髓在于是无阻塞调用,不用阻塞等调用返回。(操作的同时向任务发送fsockopen无阻塞请求,并带上载荷,就可以替代MQ了。) [除了芯片 ,还有一种神秘的技术曾被国外垄断](https://mp.weixin.qq.com/s/5s9D1Bv8Ehc8MPTDieVyQw)(硬件层的负载均衡方案) [如何给女朋友解释什么是分布式和集群?文末有惊喜!](https://mp.weixin.qq.com/s/d6d1fTj1qKVFqZ8PXVq6NQ) [炫技,从 12.67s 到 1.06s 的网站性能优化实战](https://mp.weixin.qq.com/s/D43XIqa7BrSEzE4ISXxWmg) [“12306”的架构到底有多牛逼?](https://mp.weixin.qq.com/s/oqjbW4ylAwVm5iUWsuJiEQ) [Nginx负载均衡健康检测,你了解过吗?](https://mp.weixin.qq.com/s/wAJpvlyOtRiHQLkMxjp5Ow) > 这样就不会大家集中去监听一个资源了(监听资源/节点),避免了争抢问题,同时确定了顺序性,不可谓不高明啊 [【系统架构】仅需这一篇,吃透「负载均衡」妥妥的](https://mp.weixin.qq.com/s/SO1ZLSPaRkk8WwUl9u-JPA) [咖啡馆的故事:FTP, RMI , XML-RPC, SOAP, REST一网打尽](https://mp.weixin.qq.com/s/OXIFJGSozoRWNaLhnD0wxw) [Varnish_百度百科]([https://baike.baidu.com/item/Varnish/10219137?fr=aladdin](https://baike.baidu.com/item/Varnish/10219137?fr=aladdin)) > Varnish是一款高性能的开源HTTP加速器,挪威最大的在线报纸 Verdens Gang 使用3台Varnish代替了原来的12台Squid,性能比以前更好。 [【系统架构】分布式之缓存击穿(上)](https://mp.weixin.qq.com/s/MXM2gtMVk5ViyragLK_1Tw) * * * * * **思考** 如果实现了所谓的异步,**即快速返回结果给浏览器,并断开连接,浏览器收到http状态200**,但此时后端还没结束,还在继续执行,那这样的话就不需要了MQ了啊,替代了MQ的功能啊(**本来立即要做的事情,但是由于事情太费时间,前台不能等,而且这个事情的实时性要求不是那么高,并不是说一定要你同步做,所以放到队列里面,让另一个人去做**),当然这里所说的队列只是MQ中最普通的一种队列模式,MQ不只是这一种队列模式,还有延时队列等等。 >[danger] **异步/MQ:[调用方] 不依赖于 [此逻辑]的执行。(主要目的在于[解耦](https://www.zhihu.com/question/20278169),让合适的人干合适的事情,并且相互之间没有依赖)** >[danger] 同步处理主要的任务,异步处理非紧要的事,并且耗时的事,但是又不可能全部异步没有同步,同步就像一个树的根和主干,异步就是主干上的一些分支,叶子。异步要做的事也是从同步来的,同步快速保存数据。同步是根,异步是叶。这就是他们在软件开发中的关系。 [深入NGINX:nginx高性能的实现原理 - panda521 - 博客园](https://www.cnblogs.com/chenjfblog/p/8715580.html) [Nginx+Php-fpm运行原理详解 - CSDN博客](https://blog.csdn.net/u013474436/article/details/52972699) >[danger] 不过这样就没意义了,队列主要的思想就是异步,不阻塞当前响应,让一些耗时任务可以堆积在**Broker(中间/第三方系统)** 中等待,这样不会影响系统的服务能力,而如果这样做,虽然表面看起来效果和队列一样的,但是请求多了,php-fpm处理的连接是有限的,会导致很多请求没办法响应,都阻塞着,最终超时。严重影响系统的并发服务能力。 > 这样治标不治本,会占用php-fpm(新的请求也是打在其他php-fpm上),任何时候都要考虑代码的运行方式和运行环境,脱离这个前提,讨论别的就是错的,没有意义。 >[tip] fsockopen 虽然能实现所谓“异步”的调用,看似在功能上可以完全替代MQ,**先不论这样会继续占用php-fpm进程(新的请求也是打在其他php-fpm上)**,单从工程上来说,**这样的实现不能体现服务/编码的工程化**,违背了开发的模块化,所以是不提倡这样使用的,实际生产中不能这样写代码。 **这种方式只是一种伪多进程并发,伪异步,伪后台执行。** (知识点:并发,并行,队列,异步) * * * * * [淘宝详情页的 BigRender 优化与存放大块 HTML 内容的最佳方式](https://lifesinger.wordpress.com/2011/09/23/bigrender-for-taobao-item/) ~~~ 对于复杂页面,为了将用户关注的内容尽可能快渲染出来,至少有两种方式: 一、Facebook 的 BigPipe 方式。先输出页面整体布局,然后逐步输出脚本块,一边输出一边执行,将内容渲染回页面布局中。这样可以让服务端的运算、网络传输和浏览器端的渲染变成并行。BigPipe 最主要解决的问题是服务端的运算时间,当服务端的运算时间大于 300 ~ 500ms 时才能体现出优势。当服务端响应非常快(小于 100ms),BigPipe 退化为下面要讲的 BigRender. 二、淘宝商品详情页的 BigRender 方式。淘宝的商品详情页,服务端平均响应时间为 52ms, 采用 BigPipe chunked 输出意义不大。这次优化主要在浏览器端。页面下载完毕后,要经过 Tokenization — Tree Construction — Rendering. 要让首屏尽快出来,得给浏览器减轻渲染首屏的工作量。可以从两方面入手: 减少 DOM 节点数。节点数越少,意味着 Tokenization, Rendering 等操作耗费的时间越少。(对于典型的淘宝商品详情页,经测试发现,每增加一个 DOM 节点,会导致首屏渲染时间延迟约 0.5ms.) 减少脚本执行时间。脚本执行和 UI Update 共享一个 thread, 脚本耗的时间越少,UI Update 就能越发提前。 ~~~ Facebook 的 BigPipe 也是一种比较好的方式,做法是是先push出页面的结构,然后一边计算一边输出页面的填充内容,当然这个内容只能通过输出js脚本填充了。 * * * * * [浅谈服务器端推送技术](http://www.toutiao.com/i6473074659892920845/) 原来服务器和浏览器不断开,ajax也是可以收到数据的,不一定要是这个状态:`xhr.readyState==4 && xhr.status==200` ~~~ if (xhr.readyState==4 && xhr.status==200) { var str =xhr.responseText; } ~~~ ~~~ 流 流是通过HTTP流实现的。不同与长轮询,它在页面的整个生命周期内只能使用一个HTTP连接。浏览器向服务器发送一个请求,服务器保持连接打开,然后周期性地向浏览器发送数据。 服务器端实现: <?php $i = 0; while(true){ echo "Number is $i"; flush(); sleep(10); $i++; } 浏览器端实现: function createStreamingClient(url,progress,finished){ var xhr = new XMLHttpRequest(), received = 0; xhr.open("get",url,true); xhr.onreadystatechange = function(){ var result; if(xhr.readyState == 3){ //只取得最新数据并调整计数器 result = xhr.responseText.substring(received); received += result.length; //用新数据调用progress回调函数 progress(result); }else if(xhr.readyState == 4){ finished(xhr.responseText); } }; xhr.send(null); return xhr; } ~~~ * * * * * ### 假异步?取代普通队列? php后端可以发送断开头后再继续执行,甚至前端也可以不用等到http状态200,那这么来看的话,就可以很简单的将耗时的操作“异步”了啊,这样就可以完全不需要普通的队列了啊。 完全可以用这种方式替代普通的队列服务了啊。其实这种作弊的方式,只适用于访问式web,服务端作为被调用方,这其实不算真正的异步,只是欺骗调用方而已。真正的异步是调用方执行异步代码不会阻塞调用方本身,等异步代码执行玩后会自动返回结果给调用方。异步其实是一种程序模型。 只要调用方不需要立即得到结果的调用都可以异步,语言调用运行时得到结果的也不能异步,只能同步阻塞调用。 我们平常写代码的结构和方式,就是自上而下的同步结构,同步代码。这也是我们正常的认知。 而异步代码往往需要执行环境的支持或者特殊的进程实现,比如浏览器中的js异步是靠事件循环和定时器来实现的,这是浏览器这个宿主环境自带的功能。有一些则需要多个进程配合,比如后台的常驻服务,多工人进程等,比如 [Swoole](https://www.swoole.com/)。 **从沙子到应用** 不管理念和概念多么先进,抽象出来的技术多么复杂,其实底层实现都是朴素的,本质都是一样的(返璞归真),以不变应万变,要知道计算机就是抽象的。一层一层的往上抽象、封装,直至到最上面的一层,即:呈现在我们眼前的应用。 所有的问题都可以通过抽象,分层设计来描述和解决。 但是注意所有东西都是相对的,比如相对于机器码来说,编程语言就是应用层了,而相对于底层协议,我们编写的业务代码才是属于应用层。 * * * * * last update:2018-1-5 18:51:09