此篇文章是针对小白的一篇理解Flask,uWSGI,nginx的文章,只介绍了理解,并没有介绍如何部署。
由于工作需要使用flask写了一个简易的web页面,所以按照接口文档demo写好以后本地测试一切正常,但是发布到服务器以后有一串警告:
WARNING:This is a developnent server. Do not use it in a production deploynent
意思是我的这个启动方式不能在生产环境上使用,我的启动方式是:
app.run(host=“0.0.0.0”, port=5000)
这种启动方式只适用于开发模式,用这种模式启动是使用了Flask的内置开发服务器启动的,Flask的开发服务器是为了方便本地开发和测试设计的,性能和稳定性都不足以直接面向公网生产服务。
所以带着疑问上网查了一下,一个通用的部署方式就是:flask + uwsgi + nginx,但对于一个这方面几乎是小白的人来说,就会有很多疑问:什么是uwsgi?什么是nginx?为什么要这样部署,不用nginx行不行?等等问题,下面我就用一个例子来说明理解。
Flask(运行程序 )、uWSGI(应用服务器)、nginx(web服务器)。
通过一个银行办事大厅的类比,来直观解释下web服务器和应用服务器的区别与关系:
假设一个银行的办事大厅有两个区域:
接待区: 几个窗口,柜员在这里受理来办事的客户(用户)。
后台区: 员工在这里核心业务,例如开户、贷款等。
那么:
web服务器(如nginx)就相当于接待区的窗口和柜员。它直接面向客户,接收客户的请求,但是不能处理业务。
应用服务器(如uWSGI)相当于后台区的员工。它能直接处理核心业务,但是不与客户直接对话。
两者关系是:
web服务器接收请求,将需求交给应用服务器处理,应用服务器将结果返回给web服务器,由web服务器响应用户。
它们各自有分工:web服务器专注网络通信和用户交互。应用服务器专注业务处理和数据计算。但又需要紧密结合,以提供完整的服务。
普通代理,比如柜员接受客户请求,转交后台;客户知道自己在跟柜员对话。
而反向代理,从客户角度就像不存在一样!客户表面看是直接跟后台正常交互,但实际上中间被无形插入了一个代理层(nginx),且客户并不知情。举例:
普通代理:客户 → 柜员代理 → 后台
反向代理:客户 →(无感知)→ nginx → 后台
可以看到反向代理“隐藏”了自己,构建了一个黑盒流量入口,外界感知不到代理的存在。这带来的优势比如:
所以简言之,反向代理相当于应用服务器前面的一层隐形防护网,带来更强的安全与扩展性。
有的时候,Flask应用能不用nginx,直接让uWSGI对外,是因为uWSGI这个应用服务器本身内置了网络服务的功能。
我们扩展下这个银行的场景:
原先的后台员工(uWSGI)只能在后台办公,需要柜员(nginx)与客户沟通。但是银行后来让员工们接受了额外培训,掌握了柜员的部分工作,比如接待客户,了解需求等。
于是员工就同时具备了后台处理能力,以及与客户BASIC的交互能力。这就是 uWSGI 的实际情况。
那么银行可以做出两种选择:
依然保留专门的柜员,以发挥专业分工的优势;
直接让员工自行处理客户,减少一个环节;
这就是你的Flask应用可直接使用uWSGI,或者结合nginx的区别。
之所以我们更建议nginx+uWSGI,是因为专业分工能发挥二者各自的专业优势,组合后服务能力更强,尤其是应用复杂度高时。
在很多Web应用的部署架构中,并不一定包含uWSGI或类似的应用/进程管理服务器。这其实跟我们选择使用的后端框架及其自身特性有关。以Python后端为例,不同框架对部署架构的需求不同:
而对于Node、Java等其他语言的后端框架也有类似的特性和约定。
所以回到问题,之所以一个Vue+Django应用可以仅使用Nginx部署,是因为:
所以结论是,这并不违反我们对部署架构不同角色的理解,而是跟所选择使用的后端框架的特性有关。我们需要基于其自身的约定来设计合适的部署方案。