# coding:utf-8 import tornado.web import tornado.ioloop import tornado.httpserver # 新引入httpserver模塊 class IndexHandler(tornado.web.RequestHandler): """主路由處理類""" def get(self): """對應http的get請求方式""" self.write("Hello ") if __name__ == "__main__": app = tornado.web.Application([ (r"/", IndexHandler), ]) # ------------------------------ # 我們修改這個部分 # app.listen(8000) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(8000) # ------------------------------ tornado.ioloop.IOLoop.current().start()
在這一修改版本中,我們引入了tornado.httpserver模塊,顧名思義,它就是tornado的HTTP服務器實現。
我們創建了一個HTTP服務器實例http_server,因為服務器要服務於我們剛剛建立的web應用,將接收到的客戶端請求通過web應用中的路由映射表引導到對應的handler中,所以在構建http_server對象的時候需要傳出web應用對象app。http_server.listen(8000)將服務器綁定到8000端口。
實際上一版代碼中app.listen(8000)正是對這一過程的簡寫。
單進程與多進程
我們也可以一次啟動多個進程,修改上面的代碼如下:
# coding:utf-8 import tornado.web import tornado.ioloop import tornado.httpserver class IndexHandler(tornado.web.RequestHandler): """主路由處理類""" def get(self): """對應http的get請求方式""" self.write("Hello ") if __name__ == "__main__": app = tornado.web.Application([ (r"/", IndexHandler), ]) http_server = tornado.httpserver.HTTPServer(app) # -----------修改---------------- http_server.bind(8000) http_server.start(0) # ------------------------------ tornado.ioloop.IOLoop.current().start()
http_server.bind(port)方法是將服務器綁定到指定端口。
http_server.start(num_processes=1)方法指定開啟幾個進程,參數num_processes默認值為1,即默認僅開啟一個進程;如果num_processes為None或者<=0,則自動根據機器硬件的cpu核芯數創建同等數目的子進程;如果num_processes>0,則創建num_processes個子進程。
本例中,我們使用http_server.start(0),而我的虛擬機設定cpu核數為2,演示結果:
我們在前面寫的http_server.listen(8000)實際上就等同於:
http_server.bind(8000)
http_server.start(1)
說明
1.關於app.listen()
app.listen()這個方法只能在單進程模式中使用。
對於app.listen()與手動創建HTTPServer實例
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(8000)
2.關於多進程
雖然tornado給我們提供了一次開啟多個進程的方法,但是由於:
- 每個子進程都會從父進程中復制一份IOLoop實例,如過在創建子進程前我們的代碼動了IOLoop實例,那么會影響到每一個子進程,勢必會干擾到子進程IOLoop的工作;
- 所有進程是由一個命令一次開啟的,也就無法做到在不停服務的情況下更新代碼;
- 所有進程共享同一個端口,想要分別單獨監控每一個進程就很困難。
不建議使用這種多進程的方式,而是手動開啟多個進程,並且綁定不同的端口。