Ajax+Tornado模拟长、短轮询

一、短轮询

  在传统的短轮询中,浏览器每隔一段时间向服务器发送请求,看服务器有无更新。缺点是效率低,因为服务器不是总有更新数据;再者,如果大量用户不停的请求服务器,会造成较大的负载压力。

  浏览器端,利用jQuery.ajax发送请求

 1 <html>

 2 <head>

 3     <title>Short Polling</title>

 4     <script type="text/javascript" src="lib/jquery.min.js"></script>

 5 </head>

 6 <body>

 7     <p>Short Polling - Unsorted list...</p>

 8     <ul></ul>

 9     <script>

10         (function($) {            

11             var polling = function() {

12                 $.get('/polling', function(data){

13                     $("ul").append("<li>"+data+"</li>");

14                 });

15             };

16             interval = setInterval(polling, 3000);

17         })(jQuery);

18     </script>

19 </body>

20 </html>

  服务器端,tornado.httpserver响应请求(同步)

 1 import os

 2 import random

 3 import tornado.httpserver

 4 import tornado.ioloop

 5 import tornado.options

 6 import tornado.web

 7 

 8 from tornado.options import define, options

 9 

10 define("port", default=8088, help="run on the given port", type=int)

11 

12 class MainHandler(tornado.web.RequestHandler):

13     def get(self):

14         self.write("Main page...")

15 

16 class ShortPollingHandler(tornado.web.RequestHandler):

17     def get(self):

18         num = random.randint(1,100)

19         self.write(str(num))

20 

21 def main():

22     tornado.options.parse_command_line()

23     settings = {

24         "static_path" : os.path.join(os.getcwd(), "public"),

25     }

26     application = tornado.web.Application([

27         (r"/", MainHandler),

28         (r"/polling", ShortPollingHandler),

29     ], **settings)

30     http_server = tornado.httpserver.HTTPServer(application)

31     http_server.listen(options.port)

32     print "server listening on port %d" % options.port

33     tornado.ioloop.IOLoop.instance().start()

34 

35 if __name__ == "__main__":

36     main()

  连接的平均时长0.5ms左右:由于浏览器端定时发送请求,如果连接在服务器端发生阻塞,则会造成服务器端负载压力上升;当服务器端无阻塞且无更新时,连接立即断掉,浏览器端的大量请求未能取得有效数据,效率低下。

二、长轮询

  用户发出请求建立连接,当服务器端有数据返回后连接才会断掉,接着用户端发送一个新的连接请求。

  浏览器端,在jQuery.get的callback中重新发出连接请求

 1 <html>

 2 <head>

 3     <title>Long Polling</title>

 4     <script type="text/javascript" src="lib/jquery.min.js"></script>

 5 </head>

 6 <body>

 7     <p>Long Polling - Unsorted list...</p>

 8     <ul></ul>

 9     <script>

10         (function($) {          

11             var polling = function() {

12                 $.get('/polling', function(data){

13                     $("ul").append("<li>"+data+"</li>");

14                     polling();

15                 });

16             };

17             polling();

18         })(jQuery);

19     </script>

20 </body>

21 </html>

  服务器端,tornado.httpserver响应请求(异步)

 1 import os

 2 import time

 3 import random

 4 import tornado.httpserver

 5 import tornado.ioloop

 6 import tornado.options

 7 import tornado.web

 8 

 9 from tornado.options import define, options

10 

11 define("port", default=8088, help="run on the given port", type=int)

12 

13 

14 class MainHandler(tornado.web.RequestHandler):

15     def get(self):

16         self.write("Main page...")

17 

18 class PollHandler(tornado.web.RequestHandler):

19     @tornado.web.asynchronous

20     def get(self):

21         if self.request.connection.stream.closed():

22             return

23         num = random.randint(1, 100)

24         tornado.ioloop.IOLoop.instance().add_timeout(

25             time.time()+3,

26             lambda: self.send(data=num, callback=self.get)

27         )

28              

29     def send(self, data, callback):

30         try:

31             self.write(str(data))

32             self.finish()

33         except:

34             pass

35 

36 def main():

37     tornado.options.parse_command_line()

38     settings = {

39         "static_path" : os.path.join(os.getcwd(), "public"),

40     }

41     application = tornado.web.Application([

42         (r"/", MainHandler),

43         (r"/polling", PollHandler),

44     ], **settings)

45     http_server = tornado.httpserver.HTTPServer(application)

46     http_server.listen(options.port)

47     print "server listening on port %d" % options.port

48     tornado.ioloop.IOLoop.instance().start()

49 

50 

51 if __name__ == "__main__":

52     main()

  连接的平均时长3s左右。

三、参考

  1 - Browser 与Server 持续同步的作法介绍(Polling, Comet, Long Polling, WebSocket)

    http://www.josephj.com/entry.php?id=358

  2 - Browser和Server持续同步的几种方式(jQuery+tornado演示)

    http://qinxuye.me/article/ways-to-continual-sync-browser-and-server/

你可能感兴趣的:(tornado)