http环境本身是一种无连接状态的架构,在这种架构下服务器只能是被动的接受客户端的请求,返回结果,而无法主动的给客户端发送数据。而在很多需要实时数据交互(比如web im)的场景中,我们却希望能及时得到服务器给我们返回的数据。此时,一种最为普遍的做法是:在客户端用定时器,定时去请求服务器的服务,来得到最新数据。而这样一来,很多时候却是在做无用功,频繁的请求也会无端的增加服务器和客户端在请求web服务上的消耗。那么是否有一种更好的办法,既可以及时得到服务器的返回,同时又可以减少做无用功,以及频繁请求带来的性能问题呢?# T# j* a6 w4 c9 J: I) F/ K
记得前不久,在园子里有这样的一篇文章,介绍了几种web环境定时刷新数据的机制。其中就有提到google gmail的一种比较巧妙的做法,现在记不得当时是怎么理解这种做法了,只记得有“保持长连接”的基本做法。(当然现在也找不到这篇文章了,希望了解的朋友能提醒一下)。今天由于架构方案的需要,再来仔细思考连接保持方案,以及参考gmail的请求行为,总结了一下,应该是这样的:客户端一直保持一个与服务器的连接,这个连接一直保持着对服务器的请求动作,直到服务器发现有数据后给它返回后,才结束返回这一次请求。客户端在接收到请求返回后,在处理这些返回之前,又向服务器发送了一次连接请求,直到下一次有数据返回。不可避免的有一种情况,就是如果服务器长时间没有需要给客户端发送数据的话,那么可以就会造成请求失败(超时或其它原因)。对于这种情况的处理也是一样的,在错误的回调事件中重新发送一次请求连接。这样就可以模拟保持连接状态了。7 X2 F2 `1 B) J0 S- a
用伪代码来描述一下思路吧:: }' N0 L, b7 S/ c2 ~
客户端脚本:9 e: \- E L. _# N
1: function request()' ]/ l# U+ [& {( ~2 Q- I2 H
2: {! P8 ~1 Y6 A* s1 r# Y( O: |; v
3: ajax.request(url,onsuccessed,onfailed);
, r* k0 q7 z! Y3 x& k6 [7 p4: }
9 H- Z) ~4 k' x; L9 S5: function onsuccessed(response)
: {4 I2 _1 B. b5 }6 ^$ n6: {
& f$ F* v$ K$ H3 X& ?9 y: Q7: //重新发送一次请求& W" e7 E6 m3 [
8: request();
, v/ b6 k: o$ M, m5 h6 z4 I9: //处理返回数据9 y0 u+ |4 G6 Y' E+ A/ t0 O
10: }1 r2 b% a0 w! X
11: function onfailed()5 h B+ `2 _ q6 S0 I' N# x
12: {
# [6 j& k! ] V( L. i/ R# E13: //错误(超时)重新请求" e) T* T. ^# A, O0 }3 p
14: request();
- N D* c6 n% z" s6 Y9 s15: }2 Y7 ?6 t# \* ] U
web服务:
0 f+ z" |5 l" K' o% x6 [1: public class imservice : ihttphandler
6 n! P' M% Y. O6 j, e2: {
& V& C" D6 Z1 M/ o3: public bool isreusable{return false;}7 B- I& K9 R0 { `5 q
4: public void processrequest(httpcontext context)
7 E/ `( ]8 M5 X! p$ @3 v# F4 }5: {
: y2 ?" v3 T4 ]6: //读取最新数据
# Z3 p- d5 P& T+ |0 `& a7: while(true)( p3 W( @ W6 L9 }, A
8: {4 v; P3 m- O3 g# `0 y- D; \
9: string message = getmessage();
9 t: W" A2 [6 q% w7 j10: if(!string.isnullorempty(message))9 G7 z4 U& {- s0 H- H
11: {& }6 |3 {$ z# R& @& C& j9 k8 H6 H( H
12: context.response.write(message);- w8 a$ p7 Q6 c2 V3 d; h
13: break;
8 n1 K' ~# x1 K! E& F14: }
7 G& W' M9 V$ K: ^5 j6 Z0 O15: thread.sleep(500);//等待一段时间再重新读取。5 X: K! z3 n! k1 c
16: }* O" q* j S M |7 x5 N- l; \
17: }
+ o. {7 A/ ?) E# D18: private string getmessage()1 L% _9 j) B, k7 S
19: {
. u* g% a8 o) R1 j: {! q+ y20: //取得最新数据5 e) t0 m b7 m2 J4 ^
21: }
5 U$ `" @/ G) ~* t6 [2 L) G22: }
5 i6 m5 c3 p) Y+ a( d' ?这种方案的好处有:客户端可以第一时间得到服务器需要给客户端发送的数据(而至于web服务怎么知道要给客户端发送数据,也就是服务器的轮循设计,则是另一个需要考虑的方案);可以减化客户端逻辑,无需要创建和释放定时器,并减小由此产生的对客户端性能的损失;减少去服务器的请求次数,减少做无用功,节约节省带宽和减少服务器资源需要处理的连接请求。
% Y1 Q9 I- K2 t3 g# j相信在此之前,已经有很多人在使用这种方案了。欢迎大家就此方案发表自己的见解。
! C8 U8 w+ N' n. M' a& T$ u8 S/ x补充:服务器部分的设计,除了使用轮循外,也可以考虑使用资源互斥访问的方式来设计,这样做可以获得更佳性能,更高实时性,具体的方案应当根据实际情况来考虑。
$ s/ q4 y+ J0 M7 ^: \2 t% k+ L0 Z; B4 t7 @
更多网页制作信息请查看: 网页制作 |
|