Tornadoweb 耗时方法的解决方案(线程池)

对于非常耗时的请求,Tornado提供了异步的方法应对( 比如 AsyncHTTPClient 和 time_out ), 但对于大多是的场景,比如连接数据库,这两个方法并不适用。
翻看源代码的时候发现Tornado提供了一Resolver netutil , 其中有个用线程池实现的非阻塞的Resolver ,  用线程池可以解决大部分耗时请求的问题, 参考这段代码可以实现一个通用的解决方案,并且做到与tornado结合。
这里用到了 concurrent.futures 这个包, 对于Python 3.2之前的版本可以直接import concurrent.futures, 3.2之前的需要安装futures 这个包( pip install futures)

代码很短, 大致如下,

1
2
3
4
5
6
7
8
9
10
11
12
13
from concurrent.futures import ThreadPoolExecutor
from tornado.ioloop import IOLoop
from tornado.concurrent import run_on_executor
 
class AsyncUtils:
    def __init__(self,num_worker=10):
        self.io_loop = IOLoop.current()
        self.executor = ThreadPoolExecutor(num_worker)
 
    @run_on_executor
    def cmd(self,func, *args, **kwargs):
        res = func(*args,**kwargs)
        return res

其中 @run_on_executor, 是tornado提供的一个将同步的方法转为异步的装饰器, 适用这个装饰器要求要有 self.io_loop 和 self.executor 两个变量在, self.executor 执行完任务直接将结果丢给self.io_loop去处理。

cmd 用于包装函数并且执行

用法如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import tornado.ioloop
import tornado.web
import tornado.gen
import time
 
_ASYNC = AsyncUtils(5) #线程池大小为5
 
class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")
 
class MainAsyncHandler(tornado.web.RequestHandler):
     @tornado.web.asynchronous
    @tornado.gen.coroutine
    def get(self):
        res = yield _ASYNC.cmd(time.sleep,10) #sleep 10s
        self.write("Hello, world2")
 
application = tornado.web.Application([
    (r"/", MainHandler),
    (r"/async", MainAsyncHandler),
])
 
if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

这时候打开127.0.0.1:8888/, 会立即打印hello world, 打开http://127.0.0.1:8888/async 会进入sleep, 这时候浏览器是等待状态, 此时打开 http://127.0.0.1:8888/ ,依然会打印hello world , 没有出现卡死状态,等10s后刚刚那 http://127.0.0.1:8888/async 也打印出了hello world2,大功告成

挖坑

工作大半年,忙,一直都没更新博文(其实是借口啦)
闲暇时也多少搞一些小玩具,准备把搞这些东西的一些笔记整理成博文,挖此坑为证:
最近在写一个操作系统,状况大致如下:

  • bootloader: 能启动了,能在Real-Mode下打印一个helloworld
  • protect-mode: 能进入保护模式了,完成了一些初始化,并打印了helloworld
  • exception: 完成中断服务程序, 并做出相应的处理
  • irq: 能捕获硬件中断,比如键盘事件,系统时钟事件
  • 多任务: 研究中
  • paging: 研究中
  • filesys: 研究中
  • posix:感觉好遥远了
  • final:移植各种开源项目………

想做的:

  • node.js
  • haskell
  • 把自己的博客换成由node.js驱动
  • 写一个能在手机里跑的小玩具

Terminal 版的google translate

每次看英文文档的碰上生词都要去打开一次google translate,在墙内打开google的网站又不是那么给力,而且也用不到星际译王这种大部头。刚好最近在看学写shell脚本,就写了个terminal版的google translate,纯当练习使用shell脚本。

原理很简单,就是伪装成浏览器,在url里带上关键词然后去请求页面,将结果解析出来就ok了

继续阅读

Arch 复生记

昨天更新过系统,更新着更新着貌似出了什么问题,当时也没多留意,今日开机, 悲剧了

Unable to find root device /dev/disk/by-uuid/…

估计是更新内核的时候出了岔子。在强大的google和的帮助下我的Arch终于得以复生。

启动安装光盘

首先得想办法进入archlinux的备用系统,无奈手上无光盘,但庆幸的是机子上有一光盘镜像,grub2也仍建在(还好当初给boot另外分了一个区), grub2是可以引导启动镜像文件的。参照wiki上的方法
按c进入grub2的控制台
set isofile="archlinux-2011.08.19-core-i686.iso"
loopback loop (hd0,msdos6)/$isofile
linux (loop)/arch/boot/i686/vmlinuz archisolabel=ARCH_201108 img_dev=/dev/sda6 img_loop=$isofile earlymodules=loop
initrd (loop)/arch/boot/i686/archiso.img
boot

继续阅读

vim与firefox的完美结合,神器之pentadactyl

首先得鄙视一下这个但疼的插件名 ‘pentadactyl’。 google翻译的结果为五趾,也算多少搭上了边吧。
在pentadactyl是vimperator的分支项目,两者功能几乎一样,但是pentadactyl利用了firefox4.0新的js引擎的特性,速度大幅提升(之前装过vimperator, 有点小卡) 。对于pentadactyl 我的理解就是一个中间层,我们的操作传入到这个中间层,然后经过中间层处理后将命令传给Firefox。

关于安装
firefox的addons里面就有,不过我的firefox是14.0的,安装后有bug,连帮助都打开不了,因此安装了官网的nightly-built 版本。

关于基本的使用

首先是如何绕过这个中间层:
<A-b> 下一个按键将忽略用户定义的映射而是使用内建的设置
<C-v> 下一个按键将跳过pentadactl直接传入给firefox
<C-z> 相当于暂时关闭Pentadactyl,按下<Esc>将恢复
继续阅读

阳朔两日

超级难得的宿舍几个哥都同意出去玩,目的地桂林,从网上随便搜了个旅社,骗上猥琐磊凑足四个人,经历各种囧之后总算在青年节这天晚上登上了前往阳朔的大巴。
之前对桂林的印象只有两个,一个是第五套人民币的二十块钱的背面,另一个是小学的时候学的小竹排在画中游。
六个小时的车程,一路上各种怪山。到达的时候已是深夜两点,住的地方离西街挺近,旁边就是一家青年旅社,从窗外望过去可以看到一座很高的山。
第二天的行程: 野人谷-》一个忘记叫什么的溶洞-》遇龙河的竹筏-》西街的各种high
野人谷什么的不提,无非就是些展示当地民族风俗之类的,每个地方都有,看的多了也就麻了。
自由男神们有木有
继续阅读

C++ 中虚函数的一些笔记

首先推荐一本书《C++高级编程》,花了一个下午的时间在看这本书,感觉这本书翻译的相当不错,讲的也通俗易懂。

说来惭愧,虚函数是一个我一直很迷惑的东西,但后来发现这个确实是C++中非常强大的一个特性。书上建议把所有的成员函数都声明成虚函数,至少析构函数必须是虚函数。先运行两段试验的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;
 
class Super{
	public:
		void foo(){
			cout< <"Super Foo"<<endl;
		}
		void bar(){
			cout<<"Super Bar"<<endl;
		}
};
 
class Sub:public Super{
	public:
		void foo(){
			cout<<"Sub Foo"<<endl;
		}
};
 
int main()
{
	Sub sub;
	sub.foo();
	Super& xx = sub;
	xx.foo();
	return 0;
}

输出的结果: 继续阅读

apt-mirror架设ubuntu源服务器

一直有架设一个本地ubuntu源的想法,google之,发现竟然比我想象中的容易的多
原理很简单,就是把官方的源的所有的原封不动都搬到本地,然后跑个apache把这些东西挂到网上
安装apt-mirror
sudo apt-get install apt-mirror
安装之后在/etc/apt/下会多出个mirror.list 这个就是这个工具的配置文件了,编辑这个文件 继续阅读