[技术博客]服务器部署

q2l

0x0 了解uWSGI*

​ 可能有的同学对UWSGI比较陌生,更多是知道NGINX,但是我们的服务器一开始的时候是先使用了uWSGI,后来才加上NGINX的。

​ uWSGI,是一个对WSGI协议的实现的应用,所以我们先来了解一下什么是WSGI。

​ WSGI,Web Server Gateway Interface,也叫做the Python Web Server Gateway Interface,显然是为Python所准备的web服务器网关接口,作用是在协议之间进行转换。目前很多框架都自带了uWSGI的实现,如Flash、Django、webPy等,但是自带的实现性能不敢恭维,多用作测试,发布的话需要自己重新配置。

​ 简单点说,WSGI就是web服务器和web应用之间的桥梁:

img

​ 其作用还可以用一副漫画说明:

img

img

img

​ WSGI的作用此时应该已经理解了,总结一下:

  • WSGI有两方:“服务器”或“网关”一方,以及“应用程序”或“应用框架”一方。服务方调用应用方,提供环境信息,以及一个回调函数(提供给应用程序用来将消息头传递给服务器方),并接收Web内容作为返回值。
  • 所谓的 WSGI中间件同时实现了API的两方,因此可以在WSGI服务和WSGI应用之间起调解作用:从WSGI服务器的角度来说,中间件扮演应用程序;而从应用程序的角度来说,中间件扮演服务器
  • “中间件”组件可以执行以下功能:
    • 重写环境变量后,根据目标URL,将请求消息路由到不同的应用对象。
    • 允许在一个进程中同时运行多个应用程序或应用框架。
    • 负载均衡和远程处理,通过在网络上转发请求和响应消息。
    • 进行内容后处理,例如应用XSLT样式表。

​ 差不多说完WSGI,接下来引入一下uwsgi,可能这时候有人迷惑了,一下大写一下小写,实际上这两个是不同的:uwsgi与WSGI一样是一种通信协议,是uWSGI服务器的独占协议,用于定义传输信息的类型(type of information),每一个uwsgi packet前4byte为传输信息类型的描述,与WSGI协议是两种东西,据说该协议是fcgi协议的10倍快。我们的主角uWSGI是一个web服务器,实现了WSGI协议、uwsgi协议、http协议等

0x1 部署uWSGI

​ uWSGI的部署非常简单,直接在python环境下安装即可:pip install uwsgi

​ 新建 test.py:

def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]

​ 运行uWSGI:uwsgi --http :8001 --wsgi-file test.py

​ 此时在 http://127.0.0.1:8001 应该已经有Hello World的输出了,说明安装成功。

​ uWSGI可以配置多进程多线程,这个在后面一起讲。

0x2 了解NGINX

​ 其实一开始的时候,我们并不想部署NGINX,觉得直接用python的runserver+uWSGI跑足以,但是随着访问数量的增多,甚至我们组内的测试使用都会出现卡顿,这时我们觉得是应该学习一下了。

​ NGINX大家非常熟悉,但是对于更多JAVA后端的同学来说,APACHE应该是早有耳闻,APACHE和NGINX一样是一种WEB服务器,找到一张对比图:

web服务功能 NGINX APACHE
方向代理 支持反向代理
Rewrite 非常好 非常好
fastCHI(网关接口)
热部署 支持 不支持
系统压力比较 很小
稳定性 非常好
安全性 一般
静态文件处理 非常好 一般
动态文件处理 非常好
虚拟主机 支持 支持
内存消耗 非常小 很大
扩展资料 很少 非常多

两者最核心的区别在于:

APACHE是同步多进程模型,一个连接对应一个进程,而NGINX是异步的,多个连接(上万级别)可以对应一个进程。

所以一般来说,需要性能的WEB服务,大多使用NGINX,而需要稳定的更考虑APACHE,后者的各种功能模块实现都比前者更加完善,配置更多。更加通用的方案是:前端NGINX抗并发,后端APACHE集群,组成配合。

像是淘宝、支付宝、迅雷、新浪博客等高并发的网站,都是用的是NGINX作为WEB服务器。

Taobao目前使用Tengine

Tengine基于NGINX开发

考虑到我们的实际情况:

  1. 服务器配置低:2C4G
  2. 静态资源请求多:加载登陆界面和个别界面需要加载背景图片
  3. 需要频繁启动:网站版本迭代更新快
  4. 对同时连接数量要求高
  5. 可能需要反向代理

根据上面几个特点,我们选择了NGINX作为web服务器。

0x3 部署NGINX

​ 接下来以我们运行CentOS的aliyun的2C4G的ECS服务器为环境进行介绍。

​ 首先,需要安装NGINX,在CentOS下直接 yum install -y nginx即可。

​ NGINX的配置需要在/etc/nginx/nginx.conf中修改,这个等下一起说。

0x4 NGINX和uWSGI建立连接

​ uWSGI对于动态资源的处理很好,NGINX对于静态资源的处理很好,所以通常django应用会结合NGINX和uWSGI一起作为web服务端。NGINX抗高并发,接收所有的请求,对于静态资源的请求直接自身处理,对于动态资源的请求再转发给uWSGI处理。接下来详述我们的NGINX配置:

user root; # 可能要给予NGINX进程以root执行的权限才能对socket之类的文件进行改写

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

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.

include /usr/share/nginx/modules/*.conf;

# mysite_nginx.conf

events {
  worker_connections  1024;  ## Default: 1024
}

http
{
    server_tokens off;
    autoindex off;
    access_log off;
    include mime.types;
    default_type application/octet-stream;
    proxy_hide_header X-Powered-By;

		# 开启gzip压缩更快传输静态资源
    gzip  on;
    gzip_min_length  1k; # 对请求的静态资源的大小设置阈值,小于1k的资源经过压缩反而会变大
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/javascript application/json;
    gzip_disable "MSIE [1-6]\.";
    gzip_vary on;

		include /etc/nginx/mime.types;

    # the upstream component nginx needs to connect to
		# 在这里 NGINX 负责连接的web服务端是django应用程序,是NGXIN的上游upstream
    upstream django {
				# for a file socket
				# 这里的server使用的是sock文件,代替使用服务器端口
        server unix:///your/path/to/backend.sock; 
        # server 127.0.0.1:8001; # for a web port socket (we'll use this first, but replace it later)
    }

    # configuration of the server
    server {
        # the port your site will be served on
        listen      80;
        listen      [::]:80;
        # the domain name it will serve for
        server_name your.ip.address; # substitute your machine's IP address or FQDN
        charset     utf_8_sig; # utf_8_sig 对中文的支持最好
        include /etc/nginx/default.d/*.conf;

        # max upload size
        client_max_body_size 75M;   # adjust to taste

        # Django media
        location /media  {
            alias /your/path/to/media;  # your Django project's media files - amend as required
        }

        location /static {
            # 注意这里我们尝试使用root来定义,请求的静态资源是直接拼接在下面的路径下的,使用root表示所在的根目录,所以如果网站的静态资源都存在于/frontend/static中,下面的root路径应该写/frontend文件夹的路径而不是/static的路径,比如我们的登陆界面北京的连接为:http://website/static/img/bgd.cc940dc6.png,就是将/img/bgd.cc940dc6.png拼接到root后面进行请求
          	# 当然你也可以用上面的alias的别名方式,直接替换请求的路径
            root /your/path/to/static‘s/parent; # your Django project's static files - amend as required
          	# 另一种写法
            # alias /your/path/to/static;
          	break; 
        }

        # Finally, send all non-media requests to the Django server.
        location / {
            uwsgi_pass  django; # 设置将除静态资源外的请求发送给谁,这里的django是上面的upstream的django
            uwsgi_read_timeout 360s; # 设置超时
            uwsgi_send_timeout 360s; # 设置超时
            include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
          	index index.html;
        }   
}

​ 在 upstream django中,我们的server使用了一个套接字,实际上server还可以是服务器的一个端口,如:8001 端口,但是套接字socket是直接给予Unix的底层实现的,套接字文件的读写速度非常快,当并发高时,Unix Socket比TCP port要快一些。但是如果要使用复杂均衡,则必须要使用TCP port。


​ 接下来设置负责处理动态资源请求的后端uWSGI,该文件名为uwsgi.ini,存放在django项目文件夹内:

[uwsgi]
# Django-related settings
# the base directory (full path)
chdir           = /your/path/to/backend
# Django's wsgi file

# module          = backend.wsgi

env = DJANGO_SETTINGS_MODULE=backend.settings    

# the virtualenv (full path)
home            = /your/path/to/venv 

# where wsgi file locate, normaly in app/wsgi.py
wsgi-file = app/wsgi.py 

# where the log file output
daemonize = nohup.out

# process-related settings
# master
master          = true
# maximum number of worker processes
processes       = 10
# the socket (use the full path to be safe
socket          = /your/path/to/backend.sock
# ... with appropriate permissions - may be needed
chmod-socket    = 664
# clear environment on exit
vacuum          = true

harakiri=360 # harakiri(服务器响应时间)超时服务器停止计算
http-timeout=360 # 前后端断开链接时间,服务器继续计算,单独uwsgi时使用
socket-timeout=360 # 前后端断开链接时间,服务器继续计算,配合nginx时使用

# python-autoreload=1
# buffer-size=1024

max-requests = 1000

​ 接下来看app应用内的wsgi的配置,该文件存放在django项目的app应用文件夹内:

"""
WSGI config for backend project.

It exposes the WSGI callable as a module-level variable named ``application``.

For more information on this file, see
https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
"""
import os

from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'backend.settings')

application = get_wsgi_application()

Reference

  1. Python uWSGI 安装配置
  2. uWSGI详解
  3. uwsgi、wsgi和nginx的区别和关系
  4. Official | uwsgi WSGI quickStart
  5. Official | NGINX
  6. Python网络编程之wsgi、uwsgi概念及作用
posted @ 2020-05-29 05:42  CookieLau  阅读(297)  评论(0编辑  收藏  举报