[技术博客]服务器部署

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  阅读(334)  评论(0)    收藏  举报