Web应用的本质:

  1. 浏览器发送一个http请求;
  2. 服务器收到请求,生成一个html文档;
  3. 服务器把html文档作为http响应的Body发送给浏览器;
  4. 浏览器收到http响应,从http body取出html文档并显示。

最简单的web application就是把html用文件保存。用一个现成的http服务器软件接受用户请求,然后从文件中读取html返回给用户。这种静态服务器软件主要有Apace、Nginx、Lighttpd。正确的做法是接受解析发送http请求响应等底层代码由专门的服务器软件实现。python专注于生成html文档,所以需要一个同意的接口让我们专心用python编写web业务。

WSGI (the Python Web Server Gateway Interface)

是为python语言定义的Web服务器和Web应用程序或框架之间的一种简单而通用的接口。作为一种Web服务器与Web应用程序或应用框架之间的一种低级别的接口,以提升可移植性Web应用开发的共同点。基于现存的CGI(Common Gateway Interface,外部扩展应用程序与Web服务器交互的标准接口)标准设计。很多框架自带了用于测试的WSGI Server,发布时一般使用生产环境的WSGI Server或者联合Nginx做uwsgi。也就是说,WSGI就像是一座桥梁,一边连着web服务器,另一边连着用户的应用。但是呢,这个桥的功能很弱,有时候还需要别的桥来帮忙才能进行处理。WSGI 的作用如图所示:

部署Django项目步骤(四、Web服务器软件) - 图2

WSGI的两端分别为Server/Gateway 和 Application/Frame。服务器调用应用方,提供环境信息,以及一个回调函数(提供给application来传递消息到server),并接受Web内容作为返回值。

WSGI中间件同时实现了API的两方,因此可以在WSGI服务和WSGI应用之间起调解作用:从WSGI服务器的角度来说,中间件扮演应用程序,而从应用程序的角度来说,中间件扮演服务器。“中间件”组件可以执行以下功能:

  1. 1. 重写环境变量后,根据目标URL,将请求消息路由到不同的应用对象。
  2. 2. 允许在一个进程中同时运行多个应用程序或应用框架。
  3. 3. 负载均衡和远程处理,通过在网络上转发请求和响应消息。
  4. 4.进行内容后处理,例如应用XSLT样式表。

WSGI是个啥

部署Django项目步骤(四、Web服务器软件) - 图3

Linux常见的web服务器软件:Apache、Nginx

Apache: 模块多,功能强大,内置了对php、python、Perl和其他语言的支持 Nginx(Engine-x) 轻量级、抗高并发、速度快

1. 使用Apache+mod——wsgi部署

1.1 安装Apache

apt-get install apache2    # apache 2.4

apt-get install libapache2-mod-wsgi-py3 # 安装mod-wsgi

进入/etc/apache2配置目录

root@hecs-x-medium-2-linux-20200704093014:/etc/apache2# ls
apache2.conf    conf-enabled  magic           mods-enabled  sites-available
conf-available  envvars       mods-available  ports.conf    sites-enabled
a2+按两下tab 查看a2指令
root@hecs-x-medium-2-linux-20200704093014:/etc/apache2# a2
a2disconf  a2dismod   a2dissite  a2enconf   a2enmod    a2ensite   a2query

mods-enabled已启动的模块 mods-available已安装模块

查看可用模块

ls mods-available/
...
wsgi.conf     deflate.load 
proxy_connect.load     wsgi.load
...

1.2 编译mod_Wsgi

如何在Apache和Django中使用Django和mod_wsgi

mod_wsgi开发文档

对于大多数Linux发行版,Apache 2.X的“ dev”软件包是“ apache2-dev”,而相应的Apache软件包是“ apache2”。但是,某些系统会根据Apache使用的MPM来区分“ dev”软件包。这样,它也可以称为“ apache2-worker-dev”或“ apache2-prefork-dev”。如果使用Apache 2.X,请勿混淆并错误地安装“ apache-dev”,这是Apache 1.3的“ dev”软件包,仅称为“ apache”。

aot-get update
apt-get install apache2-dev

解压源代码

可以从以下位置获取源代码tar:

进入home目录,将源码与项目相关文件放在同一根目录方便管理.

cd ~/home
wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.7.1.tar.gz    # 下载

root@hecs-x-medium-2-linux-20200704093014:/home# ls
4.7.1.tar.gz       

tar xvfz 4.7.1.tar.gz    # 解压

root@hecs-x-medium-2-linux-20200704093014:/home# ls
4.7.1.tar.gz        mod_wsgi-4.7.1

配置源代码

要设置准备好构建的软件包,请从源代码目录中运行“配置”脚本:

./configure

配置脚本将尝试通过在各个标准位置中搜索发行版随附的称为“ apxs2”或“ apxs”的Apache构建工具来标识要使用的Apache安装。如果在这些标准位置中没有找到,将搜索您的PATH。

使用哪种Python安装将通过在PATH中查找“ python”可执行文件来确定。

如果这些程序不在标准位置,则无法在PATH中找到它们,或者您希望使用找到的替代版本, 可以将--with-apxs--with-python选项与“配置”脚本结合使用:

root@hecs-x-medium-2-linux-20200704093014:/home# whereis apxs
apxs: /usr/bin/apxs /usr/share/man/man1/apxs.1.gz

root@hecs-x-medium-2-linux-20200704093014:/home# whereis python

root@hecs-x-medium-2-linux-20200704093014:/home# cd ./mod_wsgi-4.7.1
root@hecs-x-medium-2-linux-20200704093014:/home/mod_wsgi-4.7.1# ./configure --with-apxs=/usr/bin/apxs --with-python=/usr/bin/python3.6

make # 编译
make install # 生成文件

Libraries have been installed in:
   /usr/lib/apache2/modules

ls /usr/lib/apache2/modules # 查看文件
cd /etc/apache2/
ls
apache2.conf    conf-enabled  magic           mods-enabled  sites-available    
conf-available  envvars       mods-available  ports.conf    sites-enabled
# sites 为站点配置文件夹
root@hecs-x-medium-2-linux-20200704093014:/etc/apache2# a2enmod wsgi    # 查看mod是否启用
Module wsgi already enabled

cd sites-available
ls
000-default.conf  default-ssl.conf

1.3 配置与启动

root@hecs-x-medium-2-linux-20200704093014:/etc/apache2/sites-available# vim proj_lab.conf
<VirtualHost *:80>    # 80port
        # using mod_wsgi daemon mode
        # WSGIDaemonProcess example.com (custom ,can use your django-project name) python-home=your virtualenv_path python-path=your proj_path
        WSGIDaemonProcess proj_lab python-home=/home/py36_django python-path=/home/proj_lab
        # WSGIProcessGroup example.com (custom ,can use your django-project name)
        WSGIProcessGroup proj_lab
        # The first bit in the WSGIScriptAlias line is the base URL path you want to serve your application at (/ indicates the root url),
        # and the second is the location of a "WSGI file" -- see below -- on your system, usually inside of your project package (mysite in this example).
        # This tells Apache to serve any request below the given URL using the WSGI application defined in that file.
        WSGIScriptAlias / /home/proj_lab/proj_lab/wsgi.py
        # The <Directory> piece just ensures that Apache can access your wsgi.py file.
        <Directory /home/proj_lab/proj_lab>
                <Files wsgi.py>
                        Require all granted
                </Files>
        </Directory>

</VirtualHost>

启动站点

root@hecs-x-medium-2-linux-20200704093014:/etc/apache2/sites-available# a2ensite proj_lab.conf
Enabling site proj_lab.
To activate the new configuration, you need to run:
  systemctl reload apache2

# 先cd到 site-enabled查看已启动的其他站点并关闭
root@hecs-x-medium-2-linux-20200704093014:/etc/apache2# cd sites-available
root@hecs-x-medium-2-linux-20200704093014:/etc/apache2/sites-available# ls
# 关闭默认站点
root@hecs-x-medium-2-linux-20200704093014:/etc/apache2/sites-available# a2dissite 000-default.conf
Site 000-default disabled.
To activate the new configuration, you need to run:
  systemctl reload apache2
# 启动自己的站点
root@hecs-x-medium-2-linux-20200704093014:/etc/apache2/sites-available# a2ensite proj_lab.conf
Site proj_lab already enabled
root@hecs-x-medium-2-linux-20200704093014:/etc/apache2/sites-available# apache2ctl configtest
Syntax OK
root@hecs-x-medium-2-linux-20200704093014:/etc/apache2/sites-available# apache2ctl restart

ERROR apache default page

输入站点ip地址121.37.130.65。如果显示的是Apache Ubuntu Default Page而不是django项目主页。说明没有断开000-default.conf的连接。重新输入上述关闭激活重启的三条指令。成功打开站点。打开了一个没有绑定静态文件的站点。

部署Django项目步骤(四、Web服务器软件) - 图4

This example sets up Django at the site root, but serves robots.txt, favicon.ico, and anything in the /static/ and /media/ URL space as a static file. All other URLs will be served using mod_wsgi:

Alias /robots.txt /path/to/mysite.com/static/robots.txt
Alias /favicon.ico /path/to/mysite.com/static/favicon.ico

Alias /media/ /path/to/mysite.com/media/
Alias /static/ /path/to/mysite.com/static/

<Directory /path/to/mysite.com/static>
Require all granted
</Directory>

<Directory /path/to/mysite.com/media>
Require all granted
</Directory>

WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py

<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
<VirtualHost *:80>
        # using mod_wsgi daemon mode
        # WSGIDaemonProcess example.com (custom ,can use your django-project name) python-home=your virtualenv_path python-path=your proj_path
        WSGIDaemonProcess proj_lab python-home=/home/py36_django python-path=/home/proj_lab
        # WSGIProcessGroup example.com (custom ,can use your django-project name)
        WSGIProcessGroup proj_lab
        # The first bit in the WSGIScriptAlias line is the base URL path you want to serve your application at (/ indicates the root url),
        # and the second is the location of a "WSGI file" -- see below -- on your system, usually inside of your project package (mysite in this example).
        # This tells Apache to serve any request below the given URL using the WSGI application defined in that file.
        WSGIScriptAlias / /home/proj_lab/proj_lab/wsgi.py
        # The <Directory> piece just ensures that Apache can access your wsgi.py file.
        <Directory /home/proj_lab/proj_lab>
                <Files wsgi.py>
                        Require all granted
                </Files>
        </Directory>

        # setting static directory
        Alias /static/ /homt/proj_lab/static/
        <Directory /home/proj_lab/static>
                Require all granted
        </Directory>

        # setting upload media
        Alias /meida/ /home/proj_lab/meida/
        <Directory /home/proj_lab/media>
                Require all granted
        </Directory>
</VirtualHost>

重新断开站点激活并启动站点。若还是无静态文件,一般是文件目录写错。ls查看项目文件夹。

若没有问题。查看apache的日志文件cat /var/log/apache2/error.log

[Thu Jul 09 02:09:18.765083 2020] [authz_core:error] [pid 11577:tid 140206640387840] [client 36.63.96.72:11995] AH01630: client denied by server configuration: /homt, referer: http://121.37.130.65/

发现文件目录home写成了homt。vim修改后重复上述步骤。成功加载。但是还有部分页面static加载失败,这是因为我们的static文件并不都是在同一个目录中,所以需要收集static文件到一个目录中。

部署Django项目步骤(四、Web服务器软件) - 图5

编辑settings.py 一般不推荐在服务器修改。在本地修改上传到github比较符合规定

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.0/howto/static-files/
# 在这里输入下面一行代码
STATIC_ROOT = os.path.join(BASE_DIR,'static_root')
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static')
]

激活虚拟环境,进入项目文件夹。

输入python manage.py help查看指令


[staticfiles]
    collectstatic    # 收集static文件到settings中指定的static_root文件夹

输入python manage.py collectstatic

(py36_django) root@hecs-x-medium-2-linux-20200704093014:/home/proj_lab# ls
comment  data.json  db.sqlite3  manage.py  media  proj_lab  README.md  read_statistics  requirenment.txt  s2aclab  static  static_root  templates
# 项目文件夹多了一个static_root文件夹

然后再次输入vim /etc/apache2/sites-available/proj_lab.conf修改static目录

Alias /static/ /homt/proj_lab/static_root/
<Directory /home/proj_lab/static_root>

部署Django项目步骤(四、Web服务器软件) - 图6

WEll DONE~~

2 用Nginx+uWSGI部署

uWSGI项目中文文档

2.1安装uWSGI

pip -V    # 查看你的pip的python版本是否是和开发环境一致。若不是pyhon3.x请用下述指令
pip3 -V

pip install uwsgi # 安装到公共环境,需安装python的开发包 python3-dev

2.2测试uWSGI

创建一个名为 test.py 文件:

cd /home 
vim test.py
# test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"] # python3 bytes()字节流
    #return ["Hello World"] # python2
uwsgi --http :3389 --wsgi-file test.py
...
*** WARNING: you are running uWSGI as root !!! (use the --uid flag) ***
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI worker 1 (and the only) (pid: 13509, cores: 1)

部署Django项目步骤(四、Web服务器软件) - 图7

ctrl+c关闭uwsgi进程
或者
ps -aux|grep uwsgi |awk '{print $2}' |xargs kill -9

配置Django与uwsgi

这是启动uWSGI服务器的示例命令:

uwsgi --chdir=/path/to/your/project \
    --module=mysite.wsgi:application \
    --env DJANGO_SETTINGS_MODULE=mysite.settings \
    --master --pidfile=/tmp/project-master.pid \
    --socket=127.0.0.1:49152 \      # can also be a file
    --processes=5 \                 # number of worker processes
    --uid=1000 --gid=2000 \         # if root, uwsgi can drop privileges
    --harakiri=20 \                 # respawn processes taking more than 20 seconds
    --max-requests=5000 \           # respawn processes after serving 5000 requests
    --vacuum \                      # clear environment on exit
    --home=/path/to/virtual/env \   # optional path to a virtualenv
    --daemonize=/var/log/uwsgi/yourproject.log      # background the process

Django特定的选项如下:

  • chdir:需要在Python的导入路径上的目录路径-即包含mysite软件包的目录。
  • module:要使用的WSGI模块-可能mysite.wsgistartproject创建的模块。
  • env:应该至少包含DJANGO_SETTINGS_MODULE
  • home:项目virtualenv的可选路径。
uwsgi --chdir /home/proj_lab --home /home/py36_django/ --http :3389
# --chdir 项目目录 -- home 虚拟环境 --http 端口号

报错 Internal Server Error

--- no python application found, check your startup logs for errors ---
# 没有指定uwsgi文件

# 指定uwsgi文件
uwsgi --chdir /home/proj_lab home /home/py36_django/ --http :3389 --module proj_lab.wsgi:application

报错 : Not found : xxx static 没有绑定静态文件

uwsgi提供动态服务,所以需要Web服务器软件处理静态文件。

2.3 安装Nginx

先关闭apache服务释放端口。

apache2ctl stop

安装Nginx

apt-get update
apt-get install nginx

2.4 配置与启动

为Django配置Nginx

/home# cd /etc/nginx/
/etc/nginx# ls
conf.d          koi-win            nginx.conf       sites-enabled
fastcgi.conf    mime.types         proxy_params     snippets
fastcgi_params  modules-available  scgi_params      uwsgi_params
koi-utf         modules-enabled    sites-available  win-utf

/etc/nginx# cd sites-available/
/etc/nginx/sites-available# ls
default
/etc/nginx/sites-available# cd .. && cd sites-enabled/
/etc/nginx/sites-enabled# ls
default
/etc/nginx/sites-enabled# cd .. && cd sites-available

你会需要 uwsgi_params 文件,可用在uWSGI发行版本的 nginx 目录下,或者从 https://github.com/nginx/nginx/blob/master/conf/uwsgi_params 找到。

将其拷贝到你的项目目录中。一会儿,我们将告诉nginx引用它。或者自行设置文件,我们选择自己设置文件。

现在,创建一个名为yoursite_nginx.conf的文件,下面为通用模板:

# mysite_nginx.conf

# the upstream component nginx needs to connect to
upstream django {
    # server unix:///path/to/your/mysite/mysite.sock; # for a file socket
    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

# configuration of the server
server {
    # the port your site will be served on
    listen      8000;
    # the domain name it will serve for
    server_name .example.com; # substitute your machine's IP address or FQDN (Fully Qualified Domain Name)全限定域名
    charset     utf-8;

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

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

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

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /path/to/your/mysite/uwsgi_params; # the uwsgi_params file you installed
    }
}

设置proj_lab_uwsgi.conf文件

:/etc/nginx/sites-available# vim proj_lab.conf
server{
        listen 80;
        server_name proj_lab;
        charset utf-8;

        client_max_body_size 75M;       # max upload size

        location /static {
                alias /home/proj_lab/static_root;
        }
        location /media {
                alias /home/proj_lab/media;
        }
        # Finally, send all non-media requests to the Django server.
        location / {
                # socket transmit
                uwsgi_pass 127.0.0.1:8001;
                # the uwsgi_params file you installe
                include /etc/nginx/uwsgi_params;
        }

}

创建新目录存放一些uwsgi配置

示例ini配置文件:

[uwsgi]
chdir=/path/to/your/project
module=mysite.wsgi:application
master=True
pidfile=/tmp/project-master.pid
vacuum=True
max-requests=5000
daemonize=/var/log/uwsgi/yourproject.log

ini配置文件用法示例:

uwsgi --ini uwsgi.ini
/home# mkdir proj_lab_uwsgi
/home/proj_lab_uwsgi# vim proj_lab_uwsgi.ini

home = /home/py36_django
module = proj_lab.wsgi:application

master = True
# the number of worker processes
processes = 4
# respwan processes taking more than 60s
harakiri = 60
# respwan processes after serving 5000 requests
max-requests = 5000

socket = 127.0.0.1:8001
# user identifier
uid = 1000
# group identifier
gid = 2000

# process identification number
pidfile = /home/proj_lab_uwsgi/master.pid
# log
daemonize = /home/proj_lab_uwsgi/proj_lab_uwsgi.log
# server closed recycle
vacuum = True

启动.ini文件

/home/proj_lab_uwsgi# uwsgi --ini proj_lab_uwsgi.ini
realpath() of proj_lab_uwsgi.ini failed: No such file or directory [core/utils.c line 3662]
# 启动失败 原因是 前面vim的.ini的名字写错了。。。复制一份以正确的名称报错并删除错误文件。
/home/proj_lab_uwsgi# cp prj_lab_uwsgi.ini proj_lab_uwsgi.ini
/home/proj_lab_uwsgi# ls
prj_lab_uwsgi.ini  proj_lab_uwsgi.ini
/home/proj_lab_uwsgi# rm prj_lab_uwsgi.ini

/home/proj_lab_uwsgi# uwsgi --ini proj_lab_uwsgi.ini
[uWSGI] getting INI configuration from proj_lab_uwsgi.ini
# 查看进程是否启动
/home/proj_lab_uwsgi#  ps -aux |grep uwsgi
1000     14618  0.3  1.9 145408 39548 ?        S    23:38   0:00 uwsgi --ini proj_lab_uwsgi.ini
1000     14620  0.0  1.4 145408 29720 ?        S    23:38   0:00 uwsgi --ini proj_lab_uwsgi.ini
1000     14621  0.0  1.4 145408 29720 ?        S    23:38   0:00 uwsgi --ini proj_lab_uwsgi.ini
1000     14622  0.0  1.4 145408 29720 ?        S    23:38   0:00 uwsgi --ini proj_lab_uwsgi.ini
1000     14623  0.0  1.4 145408 29720 ?        S    23:38   0:00 uwsgi --ini proj_lab_uwsgi.ini
root     14625  0.0  0.0  14424  1084 pts/1    S+   23:39   0:00 grep --color=auto uwsgi
# 若只有一个进程说明启动失败。

在sites-enabled中创建软连接

/home/proj_lab_uwsgi# cd /etc/nginx
/etc/nginx# ls
conf.d          koi-win            nginx.conf       sites-enabled
fastcgi.conf    mime.types         proxy_params     snippets
fastcgi_params  modules-available  scgi_params      uwsgi_params
koi-utf         modules-enabled    sites-available  win-utf
/etc/nginx# ln -s /etc/nginx/sites-available/proj_lab.conf /etc/nginx/sites-enabled/proj_lab.conf
/etc/nginx# cd sites-enabled/
/etc/nginx/sites-enabled# ls
default  proj_lab.conf

# 查看配置是否正确
/etc/nginx/sites-enabled# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重启nginx服务

service nginx restart

若出现Apache default page 。关闭apache 默认服务。

/etc/apache2/sites-available# a2dissite 000-default.conf
Site 000-default already disabled

或者是/etc/nginx/sites-enabled/中存在default文件。删除它rm default,再重新启动nginx服务。

部署Django项目步骤(四、Web服务器软件) - 图8

WELL DONE~~

uwsgi --reload /home/proj_lab_uwsgi/master.pid 重启进程
uwsgi --stop /... 结束进程

查看Nginx的版本号:nginx -V

启动Nginx:start nginx

快速停止或关闭Nginx:nginx -s stop

正常停止或关闭Nginx:nginx -s quit

配置文件修改重装载命令:nginx -s reload