用Tornado制作多并发服务器

Tornado的代名词就是异步非阻塞I/O,与其说tornado是一个web框架,我更喜欢把它理解成一个服务器,一个支持多并发的服务器。

Tornado的设计初衷就是为了解决“C10K”的问题,就是一万的并发,Django自带服务器也就支持一百多并发,可见Tornado性能优异。

其实Django和Tornado可以在一起使用,Django和Tornado的结合使得python在web方向具有很强的竞争力。

我用一个实例来解释Tornado的多并发,我自制一个在线翻译,借助有道API,我将需要翻译的数据发送过去之后,有道API会返回给我json数据。

首先,先写一个同步的服务器,我假设我发送数据之后有道会过5秒钟才会把数据返回给我。

#coding=utf-8
import tornado.httpserver

import tornado.ioloop

import tornado.options

import tornado.web

import tornado.httpclient

import urllib

import json

import datetime

import time

 

 

from tornado.options import define,options

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

 

class Index(tornado.web.RequestHandler):

    

    def get(self):

        query = self.get_argument(‘q‘)

        baseurl =r‘http://fanyi.youdao.com/openapi.do?keyfrom=pyworm&key=973100900&type=data&doctype=json&version=1.1&q=‘

        url = baseurl+query

        client = tornado.httpclient.HTTPClient()

        response = client.fetch(url)

        time.sleep(5)

        fanyi = json.loads(response.body) 

        trans = u‘%s:\n%s\n%s\n%s\n%s\n%s‘%(fanyi[‘query‘],‘‘.join(‘-‘ * 3 + u‘翻译‘ + ‘-‘ * 3),‘‘.join(fanyi[‘translation‘]),‘‘.join(‘-‘ * 3 + u‘词典‘ + ‘-‘ * 3),‘‘.join(fanyi[‘basic‘][‘phonetic‘]),‘‘.join(‘-‘ * 3 + u‘网络释义‘ + ‘-‘ * 3),)      

        self.write(trans)

        

        

if __name__ == ‘__main__‘:

    tornado.options.parse_command_line()

    app = tornado.web.Application(handlers = [(r"/",Index)])

    http_server = tornado.httpserver.HTTPServer(app)

    http_server.listen(options.port)

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

运行上面代码之后,访问http://localhost:8000/?q=hello就会看到翻译信息:hello: ---翻译--- 你好 ---词典--- h?‘l??; he- ---网络释义---。然后我就以这台电脑做服务器,另外一台电脑访问这台服务器http://192.168.0.101:8000/?q=hello同样得到翻译信息:hello: ---翻译--- 你好 ---词典--- h?‘l??; he- ---网络释义---。但是如果两台电脑同时进行翻译,会出现5秒之后一台电脑翻译成功,再过5秒另外一台翻译成功,这就是同步,第二台电脑要等第一台翻译完才会去翻译。

现在我要这服务器支持多并发,两台电脑同时翻译,会同时翻译成功。

Tornado包含一个AsyncHTTPClient类,可以执行异步HTTP请求。

#coding=utf-8
import tornado.httpserver

import tornado.ioloop

import tornado.options

import tornado.web

import tornado.httpclient

import urllib

import json

import datetime

import time

 

 

from tornado.options import define,options

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

 

class Index(tornado.web.RequestHandler):

    @tornado.web.asynchronous

    @tornado.gen.engine

    def get(self):

        query = self.get_argument(‘q‘)

        baseurl =r‘http://fanyi.youdao.com/openapi.do?keyfrom=pyworm&key=973100900&type=data&doctype=json&version=1.1&q=‘

        url = baseurl+query

        client = tornado.httpclient.AsyncHTTPClient()

        response = yield tornado.gen.Task(client.fetch,url)

        fanyi = json.loads(response.body) 

        trans = u‘%s:\n%s\n%s\n%s\n%s\n%s‘%(fanyi[‘query‘],‘‘.join(‘-‘ * 3 + u‘翻译‘ + ‘-‘ * 3),‘‘.join(fanyi[‘translation‘]),‘‘.join(‘-‘ * 3 + u‘词典‘ + ‘-‘ * 3),‘‘.join(fanyi[‘basic‘][‘phonetic‘]),‘‘.join(‘-‘ * 3 + u‘网络释义‘ + ‘-‘ * 3),)      

        self.write(trans)

        self.finish()

        

if __name__ == ‘__main__‘:

    tornado.options.parse_command_line()

    app = tornado.web.Application(handlers = [(r"/",Index)])

    http_server = tornado.httpserver.HTTPServer(app)

    http_server.listen(options.port)

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

关于上面代码用到的装饰器,yield等请参考Tornado文档http://demo.pythoner.com/itt2zh/ch5.html

时间: 2024-08-02 00:02:03

用Tornado制作多并发服务器的相关文章

Unix C语言编写基于IO多路复用的小型并发服务器

背景介绍 如果服务器要同时处理网络上的套接字连接请求和本地的标准输入命令请求,那么如果我们使用accept来接受连接请求,则无法处理标准输入请求;类似地,如果在read中等待一个输入请求,则无法处理网络连接的请求. 所谓I/O多路复用机制,就是说通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但 select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而还

TCP并发服务器,每个客户一个子进程

在阅读完<unix 网络编程:卷一>之后,感觉作者真是unix下编程的大师级的人物.而对于我个人而言,每次阅读完一本技术书籍之后,一定还是得自己重新再写一遍程序(换点内容),复习书本中的内容(大致结构,或者说思想,相同),否则,你很难做到真的理解并掌握的地步. Okay,今天我带来的是服务器模型中的第一种,也是最基本最常用的一种模型–TCP并发服务器,每个客户一个子进程. 先简单介绍一下:TCP并发服务器,每个客户一个子进程,也就是说并发服务器调用fork派生一个子进程来处理每个子进程,使得服

UNIX网络编程卷1 服务器程序设计范式1 并发服务器,为每个客户请求fork一个进程

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.传统并发服务器调用 fork 派生一个子进程来处理每个客户 2.传统并发服务器的问题在于为每个客户现场 fork 一个子进程比较耗费 CPU 时间. /* include serv01 */ #include "unp.h" int main(int argc, char **argv) { int listenfd, connfd; pid_t childpid; void

TCP/IP 网络编程 (抄书笔记 3) -- 僵尸进程和多任务并发服务器

TCP/IP 网络编程 (抄书笔记 3) – 僵尸进程和多任务并发服务器 TCP/IP 网络编程 (抄书笔记 3) – 僵尸进程和多任务并发服务器 Table of Contents 僵尸进程的产生 避免僵尸进程 信号 多任务的并发服务器 僵尸进程的产生 子进程先退出, 父进程没有退出 ==> 僵尸进程 父进程先退出, 子进程没有退出 ==> 子进程被 0 号进程回收, 不会产生僵尸进程 pid_t pid = fork(); if (pid == 0) { // child printf(&

1高并发服务器:多进程服务器

 1多进程并发服务器 使用多进程并发服务器时要考虑以下几点: A.父最大文件描述个数(父进程中需要close关闭accept返回的新文件描述符) B.系统内创建进程个数(和内存大小相关) C.进程创建过多是否降低整体服务性能(进程调度) 2.案例说明 server.c,代码如下: #include <stdio.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #i

2高并发服务器:多线程服务器

 1多进程并发服务器 在使用线程模型开发服务器时需要考虑以下问题: A 调整进程最大文件描述符上限 B 线程如有共享数据,考虑线程同步 C 服务于客户端线程退出时,退出处理 D 2.案例说明 server.c,代码如下: /* server.c */ #include <stdio.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <pthr

TCP并发服务器(五)——每个客户一个线程

TCP并发服务器(五)——每个客户一个线程 1.说明 前面4个版本都是关于进程的,可以将进程改为线程来实现. 这个最简单的版本也快于前面的所有预先派生进程的版本. 2.代码 #include "unpthread.h" void sig_int(int signo) { DPRINTF("sig_int()\n"); void pr_cpu_time(void); pr_cpu_time(); exit(0); } void *doit(void *arg) { v

TCP并发服务器(一)——每个客户一个子进程

TCP并发服务器(一)——每个客户一个子进程 1.说明 这是最传统的并发服务器,对于每一个客户请求fork一个子进程.问题在于每次fork一个子进程比较耗费时间,下面会讲预创建进程. 程序代码基于UNP的库. 程序在使用进程的模式下是最慢的. 2.代码 #include "unp.h" int main(int argc, char *argv[]) { int listenfd; socklen_t addrlen; if (argc = 2) { listenfd = Tcp_li

初步谈谈 C# 多线程、异步编程与并发服务器

多线程与异步编程可以达到避免调用线程异步阻塞作用,但是两者还是有点不同. 多线程与异步编程的异同: 1.线程是cpu 调度资源和分配的基本单位,本质上是进程中的一段并发执行的代码. 2.线程编程的思维符合正常人的思维习惯,线程中的处理程序依然是顺序执行,所以编程起来比较方便,但是缺点也是明显的,多线程的使用会造成多线程之间的上下文切换带来系统花销,并且共享变量之间也是会造成死锁的问题. 3.因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变