看wsgi协议的定义,感觉都没整明白是什么意思。后来用了之后大致有了自己的理解,这里写一下自己的理解吧:
wsgi有两方,服务器方 和 应用程序
①服务器方:其调用应用程序,给应用程序提供(环境信息)和(回调函数), 这个回调函数是用来将应用程序设置的http header和status等信息传递给服务器方.
②应用程序:用来生成返回的header,body和status,以便返回给服务器方。
用Python语言写的一个符合WSGI的“Hello World”应用程序如下所示:
def app(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) yield "Hello world!\n"
其中
- 第一行定义了一个名为app的应用程序,接受两个参数,environ和start_response,environ是一个字典包含了CGI中的环境变量,start_response也是一个callable,接受两个必须的参数,status(HTTP状态)和response_headers(响应消息的头)。
- 第二行调用了start_response,状态指定为“200 OK”,消息头指定为内容类型是“text/plain”
- 第三行将响应消息的消息体返回。
那通俗点来将的话:
wsgi中的服务器方:我们可以理解成是webserver,当然这个webserver可以是外置的,比如lighttpd,也可以是python自己写的。
而应用程序说白了就是:请求的统一入口!所有的请求都进入到这个app中来处理! 这个app说白了就是一个函数!!(类中的__call__是一样的道理)
=========================================================================================================
这里有很多问题貌似没解决:
1:wsgi一端的webserver是什么,这个貌似是很弱智的问题。比如lighttd就是一个webserver,那我们在lighttpd配置文件中可以指定程序的入口脚本(比如index.php).那么所有请求都会转到这个index.php来执行。 那gunicorn呢?其虽然全部都是用python写的,但是原理和lighttpd一样的,内部都是开socket来监听请求,而后将请求转到后端的python脚本中去执行!当然了:其是转到一个函数中去执行而已!所以我们要做的就是实现这个函数,而后将之加载到gunicorn中,而后启动gunicorn即可!!!!
当然:这里的方式跟lighttpd有所区别,那边只要改一下配置文件,指定请求处理的入口脚本,然后重启lighttpd即可。 而对于gunicorn而言:则是实现一个函数,而后将这个函数加载到gunicorn中,再运行一下gunicorn!
前者lighttpd的很容易理解,后边的不太好理解,这里尝试着去理解吧··
class ShireApplication(Application):
#初始化时调用
def init(self, parser, opts, args):
self.app_uri = args[0]
sys.path.insert(0, os.getcwd())
#运行时调用
def load(self):
try:
return util.import_app(self.app_uri)
except Exception, e:
exc = sys.exc_info()
return make_tb_echo_app(exc)
def main():
sys.argv += ['-c', os.path.join(os.path.dirname(__file__), 'gunicorn_config.py'), 'douban_wsgi',]
ShireApplication("%prog [OPTIONS] APP_MODULE").run()
如上:我们要做的就是继承自Application来实现自己的application,在这个自己的app中来加载处理函数(用import_app函数来加载),而后调用app.run()来启动gunicorn
①如何加载处理请求处理的入口函数
1.用函数import_app()来加载
2.该函数的参数是一个Python模块或脚本.系统会去这个指定的脚本中查找一个名字叫做application的函数对象!
所以我们只要实现一个名字叫application的函数就可以了!(名字不能错)
②这个请求处理入口函数的样式:
这个请求处理入口函数是固定的,按照wsgi协议,其要支持2个参数 env和start_response
那这里还有个问题:传递给入口函数的env里边有什么信息呢?是不是有固定的样式?env是一个dict,里边含有各种环境信息
但是这些环境信息有木有固定的key名字呢??这个协议中没有规定,只是有一些约束而已。
具体如何,我们最好还是看一下具体实现,比如gunicorn中或者werkzeug中的实现。