Django如何部署,以及部署时为什么要用 uWSGI与 Nginx?


Django框架的服务器架构一般是 Nginx + uWSGI + Django


网关协议CGI FCGI SCGI WSGI

  • CGI = Common Gateway Interface

顾名思义,它是一种接口规范。规范详细定义了Web服务器中运行的服务器代理程序,怎样获取及返回网页生成过程中,服务器环境上下文和HTTP协议中的参数名称,如大家所熟知的:REQUEST_METHOD,QUERY_STRING,CONTENT_TYPE等等。绝大部分的Web服务器程序,是以脚本的形式代理接受并处理HTTP请求,返回HTTP页面或响应。这些脚本程序,就是大家所熟知的PHP、ASP、JSP等等。

  • FCGI = Fast CGI

它其实是CGI在具体实现中的的一个变种。其设计思路是,通过减少CGI代理程序和Web宿主服务程序的通信开销,从而达到提高Web服务性能的最终目的。由此可见,FCGI在规范上跟CGI并没有不同,只是具体实现方式上有所改进:CGI的做法是,对于每个HTTP请求,Web宿主服务程序都建立新的进程以调用服务器脚本,相应该请求;FCGI的做法是,建立一个独立的FCGI服务程序进程,和Web宿主服务程序进程通信,FCGI服务进程被一旦启动后,自己分配资源、创建线程响应HTTP请求、并决定自身生命周期,从而大大降低了系统为了创建进程而做出的资源开销。现代流行的Web服务器程序,如PHP、ASP.Net,基本都是FCGI的实现。

  • SCGI = Simple CGI

它是FCGI在精简数据协议和响应过程后的产物。其设计目的是为了适应越来越多基于AJAX或REST的HTTP请求,而做出更快更简洁的应答。并且SCGI约定,当服务器返回对一个HTTP协议请求响应后,立刻关闭该HTTP连接。所以不难看出,SCGI更加适合于普遍意义上SOA所提倡的“请求-忘记”这种通信模式。

  • WSGI = Web Server Gateway Interface

此协议是Python语言的专利,它定义了一组在Web服务宿主程序和HTTP响应代理程序之间通信的普遍适用的接口。它的产生是因为Python程序员注意到,对于Web框架和Web宿主服务器程序间,有严重的耦合性,比如说,某些框架是针对Apache的mod_python设计的。于是,WSGI就定义了一套非常低级别的接口。常见的Python Web框架都实现了这个协议:如 CherryPy, Django, web.py, web2py, TurboGears, Tornado, Pylons, BlueBream, Google App Engine[dubious – discuss], Trac, Flask, Pyramid,等等.


WSGI协议,uwsgi协议

WSGI协议通讯协议):Python用于Web开发的协议(用于处理Web服务器和应用程序APP的交互信息)

把http通讯的过程抽象出来(请求数据响应数据的封装)开发者只负责处理中途的数据 


uwsgi协议传输协议速度很快):uWSGI程序实现的一个自有的协议(采用二进制来存储数据之前的协议都是使用字符串所以在存储空间和解析速度上都更快)

注意

WSGI是一种通信协议

uwsgi是一种线路协议而不是通信协议在此常用于在uWSGI服务器与其他网络服务器的数据通信

Web框架一般都自带wsgi服务器 但是性能不好,只作测试用途。(django–wsgiref)


wsgiref模块(django 框架自带)

python提供的,用于测试和学习的简单的WSGI服务器模块。

这个模块监听8000端口把Http请求根据WSGI协议转换application函数中的environ参数然后调用application函数 
wsgiref会把application函数提供的响应头设置转换为HTTP协议的响应头把application的返回return作为响应体
根据HTTP协议生成响应返回给浏览器


uWSGI服务器

uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。

uWSGI的主要特点如下:

  • 超快的性能
  • 低内存占用(实测为apache2的mod_wsgi的一半左右)
  • 多app管理(终于不用冥思苦想下个app用哪个端口比较好了-.-)
  • 详尽的日志功能(可以用来分析app性能和瓶颈)
  • 高度可定制(内存大小限制,服务一定次数后重启等)


为什么要使用Nginx 来做负载均衡

Nginx

1 安全Nginx 作为专业服务器暴露在公网相对比较安全

2 能更好地处理静态资源一些http request header

3 Nginx也可以缓存一些动态内容Nginx可以更好地配合CDN

4 可以进行多台机器的负载均衡

当然,如果访问量不大,其实也没必要加个Nginx,uWSGI足以胜任。

nginx与负载均衡

  • nginx (基于效率最高的 epoll IO 模型 ) 支持并发量 2w,    

  • (它相当于是 精简版的 httpd) web 服务器

niginx 实现负载均衡:

实现方式: 反向代理

代理的类别

  • 1 正向: vpn (正常的使用中间代理 来获取想要的数据)

  • 2 反向(把内网的机器隐藏起来): 用户访问同一台机器(代理机器),然后把用户请求分发到不同的其他机器上,获取结果后再统一的返回给用户

反向代理


	用户pc   --->>         nginx      	   隐藏的内网的 机器 也可以是nginx

			   反向代理		  ---->>     .A

			同时实现了负载均衡   	        ---->>     B


							---->>     C

							---->>     D

							---->>     .....
  • 3 透明(管理用户) :(用户不知道代理的存在)
数据包-->> 交换机 -->> (管理员 设置 透明代理) 中间服务器(限制访问内容) -->> 正常网页

niginx 负载均衡的方式:(要考虑用户的状态维持)

  • (1)round-robin 轮询 默认每个机器一次

      也可以加权重 (使得配置,性能好的机器更多的使用)
    
      缺点:不能保持用户的状态
    
  • (2)使用 ip-hash (用户认证 使得会话保持)

      但是这样 会没有负载均衡
    
  • (3)解决方法:使用一台第三方(共享的机器)的机器来专门 保存用户的 验证信息


Django项目部署

Django的settings中

settings --- ALLOWED_HOST = ['个人的IP']
DEBUG = False

(1)Django代码 拷贝到服务器(用自带的 wsgiref)**

runserver  0.0.0.0:9002 (自带的wsgiref 性能低)

(2) 通过uwsgi


pip install uwsgi

使用  

a   linux 下载 uwsgi 运行 app.py,监听 9001端口

	单文件

		app.py
			def application(env,start_response):
				start_response('200 OK',[('Content-Type','text/html')])
				return [b'hello world']
		启动
		uwsgi --http :9001 --wsgi-file app.py

		访问
		http://140.143.35.239:9001/
		hello world  # 获取响应

b   Django 程序wsgi.py文件):

		用uwsgi 启动django
			uwsgi --http :8000 --module mysite.wsgi
		也可以加配置	
			uwsgi --http :9005 --chdir /data/项目目录/ --wsgi-file /项目/wsgi.py --master --process 4 --threads 2 --static-map /static=/data/...c


		含静态文件

			需要配置 STATIC_ROOT (用于统一收集静态文件)

			收集静态文件   python manage.py collectstatic
		
     Flask程序:
	 
	 uwsgi --http :9002 --wsgi-file run.py --callable app
			

c  写一个 uwsgi.ini 配置文件使用ini配置文件启动

    Django:
    
	  [uwsgi]
	  http = 0.0.0.0:9005
	  chdir = /data/项目目录/ 
	  wsgi-file = /项目/wsgi.py 
	  process = 4 
	  threads = 2 
	  static-map = /static=/data/...c

   uwsgi --ini dmysite_uwsgi.ini
   
   
    Flask
	deploy_uwsgi.ini
		[uwsgi]
		http = 0.0.0.0:9005
		chdir = /data/deploy/
		wsgi-file = run.py
		processes = 4
		static-map = /static=/data/deploy/static
		callable = app
		
     uwsgi --ini deploy_uwsgi.ini
   
   

(3) nginx 反向代理(分发)

uwsgi 处理静态文件的能力不强

使用 -- yum install  nginx


1 启动 uwsgi

  uwsgi  uwsgi_socket.ini

	写一个 uwsgi_socket.ini 配置文件
	  [uwsgi]
	  socket = 0.0.0.0:9005
	  chdir = /data/项目目录/ 
	  wsgi-file = /项目/wsgi.py 
	  process = 4 
	  threads = 2 


2 启动 nginx  

/etc/init.d/nginx start  


	配置nginx.conf 

		user root;
		worker_processes 4;

		error_log /var/log/nginx/error.log;
		pid /var/run/nginx.pid;

		events {
			worker_connections 1024;
		}
		http {
			log_format main  '$remote_addr - $remote_user [$time_local] "$request" '
							 '$status $body_bytes_sent "$http_referer" '
							 ' "$http_user_agent" "$http_x_forwarded_for" ';
			 access_log  /var/log/nginx/access.log main;

			 sendfile             on;
			 tcp_nopush           on;
			 tcp_nodeplay         on;
			 keepalive_timeout         65;
			 # types_hash_max_size         2048;

			 include    /etc/nginx/mime.types;
			 default_type   application/octet-stream;


			 upstream  django {
					# servr unix://path/to/your/mysite.sock;
					servr 127.0.0.1:9001;
				}
			 server {
				 listen    80;
				 charset   utf-8;
				 client_max_body_size  75M;
				 location  /static{
					alias   /root/s5/sdads
				 }
				 location / {
					uwsgi_pass  django;
					include  uwsgi_params;
					 }
				}
			 }

(4) 项目上线

1 vue  --- vue run  build (run build 来生成正式的静态文件) -->>> dist生成一个静态文件

2 上传到服务器 nginx的静态文件的目录

3 django restframework

	location  /api {
		uwsgi_pass  django;
		include    uwsgi_params;
	}

	location  / {
		alias  /静态文件;
	}

(5) 运维部署流程

开发  上传git

运维 通过jekins 软件  --->> 自动化部署(git下载上传到上线服务器)
saltstack管理工具

测试服务器  master  

		saltstack 推送到线上(vue--dist,  api程序)


上线服务器  slave

	正式的
		静态文件目录     uwsgi的目录
Buy me a 肥仔水!