大部分Web应用(包括我们之前的例子)都是阻塞性质的,也就是说当一个请求被处理时,这个进程就会被挂起直至请求完成。在大多数情况下,Tornado处理的Web请求完成得足够快使得这个问题并不需要被关注。然而,对于那些需要一些时间来完成的操作(像大数据库的请求或外部API),这意味着应用程序被有效的锁定直至处理结束,很明显这在可扩展性上出现了问题。

不过tornado给了我们更好的方法来处理这种情况。应用程序在等待第一个处理完成的过程中,让I/O循环打开以便服务于其他客户端,直到处理完成时启动一个请求并给予反馈,而不再是等待请求完成的过程中挂起进程。

我们首先构造一个阻塞性质的例子来看下:

在这个例子中我们首先需要实例化一个HTTPClient类,然后调用对象的fetch方法。通过fetch方法我们构建一个URLL来抓取阿里云根据地区名获取经纬度接口。网站会返回一个json的结果,我们将这个json结果呈现在我们的网页上

通过阿里云查询成都的经纬度

我们的代码构造如下:

通过获取网页传递的参数a来得到从查询的城市,并且构造完整的URL。response获取到网页反馈的信息并且反馈到网页上

class indexHandler(tornado.web.RequestHandler):

def get(self, *args, **kwargs):

query=self.get_argument('a').encode('utf-8')

client=tornado.httpclient.HTTPClient()

response=client.fetch("http://gc.ditu.aliyun.com/geocoding?"+urllib.urlencode({'a':query}))

body=json.loads(response.body)

self.write(response.body)

得到的结果如下。

从tornado的后台打印中看到整个的响应时延是96.78ms.

[I 171231 14:44:18 web:2063] 200 GET /?a=%E6%88%90%E9%83%BD (127.0.0.1) 96.78ms

到这里,我们已经编写了一个请求阿里云反馈城市经纬的应用。但是只有一个请求也就是可以认为是单线程应用,如果我们有多个请求的时候,性能会如何呢?

我们需要使用一个测试工具来测试大量请求的时候性能表现。这里我们用到siege工具进行测试。使用方法很简单:

siege http://127.0.0.1:8000/?a=成都 -c10 -t10s

参数的解释如下:-c代表的是设置的同时并发的用户数。

-c NUM, --concurrent=NUM

This option allows you to set the concurrent number of users. The

total number of users is technically limited to your computer's

resources.

You should not configure more users than your web server is

configured to handle. For example, the default apache configuration

is capped at 255 threads. If you run siege with -c 1024, then 769

siege users are left waiting for an apache handler.

For this reason, the default siege configuration is capped at 255

users.  You can increase that number inside s

-t代表的是测试运行的时间,-t10s代表运行10秒的意思

-t NUMm, --time=NUMm

This option is similar to --reps but instead of specifying the

number of times each user should run, it specifies the amount of

time each should run.

The value format is "NUMm", where "NUM" is an amount of time and

the "m" modifier is either S, M, or H for seconds, minutes and

hours. To run siege for an hour, you could select any one of the

following combinations: -t3600S, -t60M, -t1H.  The modifier is not

case sensitive, but it does require no space between the number and

itself.

执行结果如下:可以看到成功发送请求65次。不到10秒的时间平均响应时间达到了1.03m秒,

root@zhf-maple:/home/zhf/桌面# siege http://127.0.0.1:8000/?a=成都 -c10 -t10s

** SIEGE 4.0.2

** Preparing 10 concurrent users for battle.

The server is now under siege...

Lifting the server siege...

Transactions:           65 hits

Availability:        74.71 %

Elapsed time:         9.27 secs

Data transferred:         0.01 MB

Response time:         1.03 secs

Transaction rate:         7.01 trans/sec

Throughput:         0.00 MB/sec

Concurrency:         7.21

Successful transactions:          65

Failed transactions:           22

Longest transaction:         1.40

Shortest transaction:         0.47

我们加大同时复用的次数:在这里设置为20个并发用法。可以看到平均相应时间直接翻倍成2.29秒

root@zhf-maple:/home/zhf/桌面# siege http://127.0.0.1:8000/?a=成都 -c20 -t10s

** SIEGE 4.0.2

** Preparing 20 concurrent users for battle.

The server is now under siege...

Lifting the server siege...

Transactions:           70 hits

Availability:        76.92 %

Elapsed time:         9.89 secs

Data transferred:         0.01 MB

Response time:         2.29 secs

Transaction rate:         7.08 trans/sec

Throughput:         0.00 MB/sec

Concurrency:        16.22

Successful transactions:          70

Failed transactions:           21

Longest transaction:         2.56

Shortest transaction:         0.10

如果将并发次数继续往上抬升可以看到响应时间跟随一起增加。当我们增加到100个用户的时候,平均响应时间变成了6.12秒。

root@zhf-maple:/home/zhf/桌面# siege http://127.0.0.1:8000/?a=成都 -c100 -t10s

** SIEGE 4.0.2

** Preparing 100 concurrent users for battle.

The server is now under siege...

Lifting the server siege...

Transactions:           71 hits

Availability:        78.02 %

Elapsed time:         9.49 secs

Data transferred:         0.01 MB

Response time:         6.12 secs

Transaction rate:         7.48 trans/sec

Throughput:         0.00 MB/sec

Concurrency:        45.77

Successful transactions:          71

Failed transactions:           20

Longest transaction:         9.39

Shortest transaction:         0.16

这种增长的速度对于同时大量用户在线访问的时候肯定是无法接收的。幸运的是,Tornado包含一个AsyncHTTPClient类,可以执行异步HTTP请求。代码修改如下。首先使用tornado.web.asynchronous装饰器并在fetch增加回调函数。这个回调函数将在HTTP请求完成时被调用。并用response作为参数。

class indexHandler(tornado.web.RequestHandler):

@tornado.web.asynchronous

def get(self, *args, **kwargs):

query=self.get_argument('a').encode('utf-8')

client=tornado.httpclient.AsyncHTTPClient()

response=client.fetch("http://gc.ditu.aliyun.com/geocoding?"+urllib.urlencode({'a':query}),callback=self.on_response)

def on_response(self,response):

body=json.loads(response.body)

self.write(response.body)

self.finish()

我们来看下性能如何:同样设置-c10 -t10s。响应时间从之前的1.03秒下降到0.19秒。总共传输的次数以及每秒传输的次数也增加

root@zhf-maple:/home/zhf/桌面# siege http://127.0.0.1:8003/?a=成都 -c10 -t10s

** SIEGE 4.0.2

** Preparing 10 concurrent users for battle.

The server is now under siege...

Lifting the server siege...

Transactions:          211 hits

Availability:       100.00 %

Elapsed time:         9.36 secs

Data transferred:         0.00 MB

Response time:         0.19 secs

Transaction rate:        22.54 trans/sec

Throughput:         0.00 MB/sec

Concurrency:         4.39

Successful transactions:         211

Failed transactions:            0

Longest transaction:         0.25

Shortest transaction:         0.17

并发20个用户的时候,响应时间从2.29秒下降为0.22秒

root@zhf-maple:/home/zhf/桌面# siege http://127.0.0.1:8003/?a=成都 -c20 -t10s

** SIEGE 4.0.2

** Preparing 20 concurrent users for battle.

The server is now under siege...

Lifting the server siege...

Transactions:          389 hits

Availability:       100.00 %

Elapsed time:         9.23 secs

Data transferred:         0.01 MB

Response time:         0.22 secs

Transaction rate:        42.15 trans/sec

Throughput:         0.00 MB/sec

Concurrency:         9.38

Successful transactions:         389

Failed transactions:            0

Longest transaction:         0.44

Shortest transaction:         0.1

并发100个用户的时候,响应时间从6.12变成了1.99秒。且成功传输次数增长到了362次

root@zhf-maple:/home/zhf/桌面# siege http://127.0.0.1:8003/?a=成都 -c100 -t10s

** SIEGE 4.0.2

** Preparing 100 concurrent users for battle.

The server is now under siege...

Lifting the server siege...

Transactions:          362 hits

Availability:       100.00 %

Elapsed time:         9.19 secs

Data transferred:         0.01 MB

Response time:         1.99 secs

Transaction rate:        39.39 trans/sec

Throughput:         0.00 MB/sec

Concurrency:        78.53

Successful transactions:         362

Failed transactions:            0

Longest transaction:         3.26

Shortest transaction:         0.21

从这里可以看到,并发带来的性能提升是巨大的。特别是在多用户同时访问的情下。下一章将介绍并发的原理。

tornado之异步web服务一的更多相关文章

  1. tornado之异步web服务二

    前面介绍了异步方法带来的显著性能提升.我们来看下异步使用的方法. 1 首先对于get方法使用tornado.web.asynchronous进行装饰.当使用tornado.web.asynchrono ...

  2. 《Introduction to Tornado》中文翻译计划——第五章:异步Web服务

    http://www.pythoner.com/294.html 本文为<Introduction to Tornado>中文翻译,将在https://github.com/alioth3 ...

  3. Python开发【Tornado】:异步Web服务(一)

    异步Web服务 前言: 到目前为止,我们已经看到了许多使Tornado成为一个Web应用强有力框架的功能.它的简单性.易用性和便捷性使其有足够的理由成为许多Web项目的不错的选择.然而,Tornado ...

  4. 如何设计一个异步Web服务——任务调度

    接上一篇<如何设计一个异步Web服务——接口部分> Application已经将任务信息发到了Service服务器中,接下来,Service服务器改如何对自身的资源进行合理分配以满足App ...

  5. 如何设计一个异步Web服务——接口部分

    需求比较简单,提供一个异步Web服务供使用者调用.比如说,某应用程序需要批量地给图片加lomo效果.由于加lomo效果这个操作非常消耗CPU资源,所以我们需要把这个加lomo效果的程序逻辑放到一台单独 ...

  6. Python开发【Tornado】:异步Web服务(二)

    真正的 Tornado 异步非阻塞 前言: 其中 Tornado 的定义是 Web 框架和异步网络库,其中他具备有异步非阻塞能力,能解决他两个框架请求阻塞的问题,在需要并发能力时候就应该使用 Torn ...

  7. 深入理解Tornado——一个异步web服务器

    本人的第一次翻译,转载请注明出处:http://www.cnblogs.com/yiwenshengmei/archive/2011/06/08/understanding_tornado.html原 ...

  8. 第五章:异步Web服务

    到目前为止,我们已经看到了许多使Tornado成为一个Web应用强有力框架的功能.它的简单性.易用性和便捷性使其有足够的理由成为许多Web项目的不错的选择.然而,Tornado受到最多关注的功能是其异 ...

  9. Tornado创建一个web服务

    import tornado.web import tornado.ioloop import tornado.httpserver import tornado.options import con ...

随机推荐

  1. ajax请求Url加参数的使用方法

    var cId = $(this).data('claim-id');var adoptUrl = "<?php echo $this->createUrl('claim/app ...

  2. AC日记——最短路 洛谷 P2384

    题目背景 狗哥做烂了最短路,突然机智的考了Bosh一道,没想到把Bosh考住了...你能帮Bosh解决吗? 他会给你100000000000000000000000000000000000%10金币w ...

  3. [原创][FPGA]有限状态机FSM学习笔记(一)

    1. 概述--何为有限状态机FSM? 有限状态机-Finite State Machine,简写为FSM,是表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用.通常 ...

  4. [转载][FPGA]Quartus代码保护-生成网表文件

    0. 简介 当项目过程中,不想给甲方源码时,该如何?我们可以用网表文件qxp或者vqm对资源进行保护. 下面讲解这两个文件的具体生成步骤: 1. 基本概念 QuartusII的qxp文件为Quartu ...

  5. k8s-pod的生命周期

    1.pod资源-spec.containers - name:镜像运行起来之后叫容器,该字段为容器名 image:镜像名字 imagePullPolicy:表示从哪拉取镜像, Always:不管本地有 ...

  6. hdu6223(后缀数组)

    题意: 给一个长度为n的字符串s[0..n-1],但i的后继不再是i+1,而是(i*i+1)%n,求所有长度为n的“子串”中,字典序最大的是谁 n<=150000 分析: 如果是一般的字符串,那 ...

  7. ConcurrentHashMap如何保证线程安全

    以前看过HashMap的内部实现,知道HashMap是使用Node数组+链表+红黑树的数据结构来实现,如下图所示.但是HashMap是非线程安全,在多线程环境不能够使用. 不过JDK在其并发包中为我们 ...

  8. 327. Count of Range Sum

    /* * 327. Count of Range Sum * 2016-7-8 by Mingyang */ public int countRangeSum(int[] nums, int lowe ...

  9. 【maven】架包下载失败,maven引入架包失败,pom文件未报错,但是引用的注解找不到

    出现这种问题 看到这个jar包显示是unkown,不知道版本,所以这样的解决方法就是 1.先查看maven设置是使用的自定义的仓库还是默认的仓库 2.删除掉你引用的jar包下载失败的文件夹 3.然后重 ...

  10. 表现层 JSP 页面实现

    一.实验介绍 1.1 实验内容 本节课程主要利用 easyUI 实现系统的前端页面. 1.2 实验知识点 easyUI JavaScript html 1.3 实验环境 JDK1.8 Eclipse ...