uWSGI学习笔记1——认识WSGI

引子

最近项目引入了apscheduler模块做定时任务,在flask本身的调试server中跑的好好的,但是部署到生产环境,就各种报504错误。于是上网搜了一些解决方案,虽然临时解决了,但总觉得心里不放心。加之之前用uwsgi的时候也有一些问题,一直都是临时解决没有深究。这回想接着这个机会好好读一下官方文档,研究一下uwsgi。

初识wsgi

官方文档说uWSGI这个名字中的"WSGI"部分是为了致敬同名的Python标准。WSGI称为Web服务器网关接口(Python Web Server Gateway Interface),是为Python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。WSGI不是服务器,不是模块,不是框架,它是一种通信规范,描述了web server如何与web application通信的规范。要实现WSGI协议,必须同时实现web server和web application,当前运行在WSGI协议之上的web框架有Bottle,Flask,Django。这些框架都自带了WSGI server,但是性能都不好,自带的web server更多的是测试用途,发布时则使用生产环境的WSGI server或者联合nginx做uwsgi。

也就是说,WSGI就像一座桥梁,一边连着web服务器,另一边连着用户应用。

 

WSGI有两方面:“服务器”或“网关”一方,以及“应用程序”或“应用框架”一方。服务方调用应用方,提供环境信息以及一个回调函数(提供给应用程序来将消息头传递给服务器方),并接收web内容作为返回值。

所谓的WSGI中间件同时实现了API的两方,因此可以在WSGI服务和WSGI应用之间起到调解作用:从WSGI服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。

编写WSGI application

WSGI接口要求应用或框架的开发者实现一个函数,就可以响应HTTP请求。来看一个最简单版本的hello.py:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    return [b'<h1>Hello, World!</h1>']

上面的application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

  • environ:一个包含所有HTTP请求信息的dict对象
  • start_response:一个发送HTTP响应的函数

start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list标识的HTTP Header,每个Header用一个包含两个str的tuple表示。

然后函数的返回值b'<h1>Hello, World!</h1>'作为HTTP响应的Body发送给浏览器。

编写WSGI server

有了应用,还需要一个符合WSGI协议的服务器来响应HTTP请求并调用上面写好的WSGI application。Python内置了一个WSGI服务器,这个模块叫做wsgiref,它是用纯Python编写的WSGI服务器的参考实现。所谓“参考实现”是指完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使用。

下面编写一个server.py,负责启动WSGI服务器,加载application()函数

from wsgiref.simple_server import make_server
from hello import application
    
# 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
httpd = make_server('', 8000, application)
print('Serving HTTP on port 8000....')
# 开始监听HTTP请求
httpd.serve_forever()

测试运行

确保hello.py和server.py位于同一目录下,然后再命令行输入python server.py来启动服务器:

启动成功后,打开浏览器,输入http://ip:8000/,就可以看到结果。

在命令行里可以看到wsgiref打印的log信息:

从environ中获取数据

以application的角度看,WSGI服务将用户的输入放入到environ参数中传给application。下面例子从url中获取数据:

def application(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    body = '<h1>Hello, %s!</h1>' % (environ['PATH_INFO'][1:] or 'World')
    return [body.encode('utf-8')]

这个例子可以获取url

 

WSGI数据流总结

WSGI的数据流总结如下:

  1. 浏览器发送HTTP请求到 WSGI server
  2. WSGI server调用WSGI app的函数,将用户数据以dict对象的形式放到environ参数中。
  3. application函数调用start_response函数将HTTP响应码和HTTP header传回给WSGI server
  4. application函数的返回值作为HTTP响应的body返回

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值