PHP ServerPush
原文:http://yorsal.com/archives/302
随着人们对Web即时应用需求的不断上升,Server Push(推送)技术在聊天、消息提醒尤其是社交网络等方面开始兴起,成为实时应用的数据流核心。这篇日志试图探讨的便是各种适合于PHP的Push的实现方式以及其优劣。
1. 什么是Server Push
想象在聊天应用中,如果使用传统的ajax来承担消息的传入,那么一般是通过每隔一定时间拉取一次信息的方式实现,但是其实这种方式有大量查询是浪费的。聊天等Web应用更需要服务器在特定时间来主动告知前端有新的消息(Push),而不是前端每时每刻问服务器:“来消息了吗?”(Pull)。这也正是为什么这个技术常被叫做反向ajax。
其他别名:Comet,反向Ajax
2. 如何实现Push
其实所谓的推送技术也没有多么复杂,目前从大类上有3种,一种仍然建立在ajax基础上,还有一种建立在框架基础上,最后一种抛弃了传统的HTTP协议,使用Flash或者HTML5的WebSockets技术。接下来将对这三种类别产生的不同的方式进行探讨。
1) Ajax 长轮询
Ajax长轮询从本质上来说仍然是一种pull,但是实时性较高,无用请求减少很多,是一种不错的Push实现方案。不过它只减少了网络上的无谓消耗。
核心: 客户端发起一个ajax请求,服务端将请求搁置(pending)或者说挂起,直到到了超时时间(timeout)或需要推送时返回;客户端则等待ajax返回后处理数据,再发起下一个ajax请求。
优点: 兼容性较高,实现简单
缺点: 对于php这种语言来说,如果要做到实时,那么服务端就要承受大得多的压力,因为搁置到什么时候往往是不确定的,这就要php脚本每次搁置都进行一个while循环。
当然,如果服务器刷新每秒级,那尚可接受,只是实时性上退化了。
注意: 浏览器有连接数限制。我得出的结论是如果当前页面上有一个ajax请求处于等待返回状态,那么其他ajax请求都会被搁置(Chrome, Firefox已测)。如果页面有一般ajax需求怎么办?解决方法是开个框架,框架中使在另一个域名下进行Comet长轮询,需要注意跨域问题。
PHP实现: Jquery+php实现comet
2) Frame 长连接
受到ajax启发,出现了框架下的长连接。
核心: Frame中发起一个普通请求,服务器将其搁置;需要推送时输出直接执行
脚本,然后继续保持连接。如果担心超时问题可以改成框架论询。
优点: 与1一样具有高兼容特性
缺点: 最大的问题是如果框架在载入,那么浏览器就好一直显示“载入中”,这就弱爆了(解决方法参见文末的相关阅读资源)。同样服务器也要能hold住大量循环……另外,是否有同域连接限制没测试。
3) Flash/HTML5 WebSockets
用flash来发起WebSockets,秒杀前面一切问题。
优点: 标准化, RealTime, Push
缺点: 服务器需要能应对WebSockets;还有如果既没有Flash又不支持HTML5的怎么办?
PHP实现: Start Using HTML5 WebSockets Today
6) 使用兼容封装层(socket.io)
以上每种方法都有优劣,那么终极解决方案便是合在一起!能WebSockets时候就WebSockets,不支持HTML5特性就退化到Flash,没有Flash则退化到Ajax长轮询。这也是我的Rainbowfish所采用的方式。
优点: 高度封装,编写非常容易,几乎不需要关心如何去实现的。实时,超低负载,高并发。
缺点: 其实算不上缺点,socket.io的服务器端要求是node.js,而不是php。
个人看法: 如果你是独立主机,能运行程序,那么socket.io配合node.js是个非常高效的选择。为什么呢?因为它还可以避免php的服务端高负载。
Rainbowfish的消息系统通过这种方式实现: 所有客户端都通过socket.io挂在nodejs服务器上(注意: 只是挂着,不需要任何循环,因为它是事件驱动的);需要推送消息了,服务器就与nodejs通信(比如访问某个地址来实现),告诉它推送什么消息到哪里;nodejs收到推送信号后,则通过socket.io实时传输数据给浏览器。这个其实也是一条单向的路,因为nodejs服务器不具备与php通信的能力,实际上也不需要,网页上直接连php就可以了。
3. 结束语
事实上,第一个方法(Ajax Long Pull)是一个不错的方法,只是如果使用php完成的话服务器负载上有点大,但这其实是通病;而最后列举的socket.io方案完全避免了这个问题,因为它属于另一种架构,并且这种组合也可以配合几乎所有的脚本语言实现push。
对于实时性要求非常高的应用,或许使用php实现实时部分并不是一个好的选择,将会面临非常大的服务器负载(可以通过编写支持等待事件的扩展来解决这个问题);如果只是消息提示等,则可以调整服务器上刷新的间隔降低到秒的级别,负载尚可接受。不过无论哪种用途,配合那些非阻塞语言或许才是最好的选择。
4. 相关阅读
How to implement COMET with PHP
Start Using HTML5 WebSockets Today
PHP ServerPush的更多相关文章
- PHP ServerPush (推送) 技术的探讨
2016年11月29日17:51:03 转自:http://www.cnblogs.com/hnrainll/archive/2013/05/07/3064874.html 需求: 我想做个会员站内通 ...
- PHP ServerPush <转>
http://www.cnblogs.com/hnrainll/archive/2013/05/07/3064874.html
- PHP ServerPush (推送) 技术
用来代替ajax的请求 转自:http://blog.163.com/bailin_li/blog/static/17449017920124811524364/ 需求: 我想做个会员站内通知的功能. ...
- PHP ServerPush (推送) 技术的探讨[整理]
需求: 我想做个会员站内通知的功能.不想用以前的ajax查询,听说有个推技术.以下文章介绍的不错,来自转载, ============================================= ...
- PHP ServerPush (推送) 技术的探讨【转】
随着人们对Web即时应用需求的不断上升,Server Push(推送)技术在聊天.消息提醒尤其是社交网络等方面开始兴起,成为实时应用的数据流核心.这篇日志试图探讨的便是各种适合于PHP的Push的实现 ...
- 【干货分享】前端面试知识点锦集04(Others篇)——附答案
四.Others部分 技术类 1.http状态码有哪些?分别代表是什么意思? (1).成功2×× 成功处理了请求的状态码.200 服务器已成功处理了请求并提供了请求的网页.204 服务器成功处理了请求 ...
- h5面试题集合
一.闭包的理解: 使用闭包主要是为了设计私有的方法和变量.闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露. 闭包三个特性: 1.函数嵌套函数 ; ...
- 使用php+swoole对client数据实时更新(下)
上一篇提到了swoole的基本使用,现在通过几行基本的语句来实现比较复杂的逻辑操作: 先说一下业务场景.我们目前的大多数应用都是以服务端+接口+客户端的方式去协调工作的,这样的好处在于不论是处在何种终 ...
- 使用php+swoole对client数据实时更新(上)
如果想对一个列表做实时的更新,传统的做法是采用轮询的方式.以web为例,通过Ajax定时请求服务端然后获取数据显示在页面.这种方式实现简单,缺点就是浪费资源. HTTP1.1新增加了对websocke ...
随机推荐
- C++四种不同的对象生存方式
在C++中,有四种方法产生一个对象. 第一种方法是在堆栈(stack)之中产生: void MyFunc() { CFoo foo;//在堆栈(stack)中产生foo对象 } 第二种方法是在堆(he ...
- input中的id和name
name在以下用途是不可替代的: 1. 表单(form)的控件名,提交的数据都用控件的name而不是id来控制.因为有许多name会同时对应多个控件,比如checkbox和radio,而id必须是全文 ...
- TCP通信三次握手的过程
过程 编辑 第一次 第一次握手:建立连接时,客户端 发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认:SYN:同步序列编号(Synchronize Sequence Nu ...
- UILabel常用属性
[super viewDidLoad]; // 实例化UILabel并指定其边框 UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0 ...
- mysql快速上手3
上一章给大家说的是数据库的视图,存储过程等等操作,这章主要讲索引,以及索引注意事项,如果想看前面的文章,url如下: mysql快速上手1 mysql快速上手2 索引简介 索引是对数据库表中一个或多个 ...
- 求一个String 类型数组是不是都是回文,是返回1,否则返回-1
package 回文; public class yhisHuiWen { public static void ishuiwen(String arr[]){ boolean flag=true;/ ...
- C# 条码标签打印程序,RDLC报表动态显示多条码标签的方法
初学c#,因最近公司客户要求原出货标签需实现条码化,练手的机会来了,遂动手做这个程序,开始都是一些增删改查操作一直很顺利,但到RDLC报表将条码显示到报表上犯难了,因为初学未接触过报表,上网查资料均一 ...
- 自改xss小平台上线
原先一直用xss.hk结果不知怎么被关的,正好手上有代码于是自己搭了一个,网上的类似的xss平台大多一样,原先的xss的chrome插件,不适合 "manifest_version" ...
- Is C# a clone of a Microsoft replacement for Java?
Is C# a clone of a Microsoft replacement for Java?Let's look at what Anders Hejlsberg Said. Hejlsber ...
- composer的安装
HomeGetting StartedDownloadDocumentationBrowse Packages Dependency management Declaring dependencies ...