如何一步步在生产环境上部署django和vue

2次阅读

共计 7776 个字符,预计需要花费 20 分钟才能阅读完成。

本文由云 + 社区发表本文主要讲述了如何一步步在生产环境上部署 django 和 vue,操作系统默认为 centos

说明:后文中出现的以下字符串均表示具体的路径或者名称,含义如下:

DJANGO_DIR—- 表示 django 的工程根目录
DJANGO_NAME—- 表示 django 的工程名称
VUE_HTML_DIR—- 表示 vue 编译好的 index.html 路径
VUE_STATIC_DIR—- 表示 vue 编译好的静态文件夹 static 的路径

整体框架
一个常用的 web 框架图如下图所示
框架选用.jpg
我们使用 nginx + uwsgi 来驱动 django,因为 uwsgi 性能非常高
720333-20170312154455592-1425120615.png
一、安装和配置 nginx
安装
使用 yum 安装即可
yum -y install nginx
启动
service nginx start
此时到浏览器输入对应的 ip 地址,出现下面页面即表示安装成功
1324702136-57fb16aa00d21_articlex.png
修改配置文件
nginx 可以新建一个配置,放在项目目录,暂时不修改 nginx 的默认配置,端口号可以换一个,然后在 /etc/nginx/conf.d/ 内新建一个软链接指向该配置文件,这样 nginx 在读取配置时会将该配置一起读进去。这样,访问端口号 8080 的请求便会指向我们自己的这个配置。
server {
listen 8080;
server_name 132.232.50.225;
root /data/;
charset utf-8;
access_log /data/access_narwhals.log;
error_log /data/error_narwhals.log;
client_max_body_size 75M;
location / {
uwsgi_pass 127.0.0.1:9090;
include /etc/nginx/uwsgi_params;
}
location ^~ /admin/ {
uwsgi_pass 127.0.0.1:9090;
include /etc/nginx/uwsgi_params;
}
}
该配置中 uwsgi_pass 要指向 uwsgi 绑定的接口。(我们先假设 uwsgi 配置的是 9090 端口)
二、安装和配置 uwsgi
安装
使用 yum 或者 pip 均可安装
yum install uwsgi
# 或者
pip install uwsgi
不过这里需要注意,如果运行 uwsgi 出现下面错误
uwsgi: option ‘–http’ is ambiguous; possibilities: ‘–http-socket’ ‘–https-socket-modifier2’ ‘–https-socket-modifier1’ ‘–https-socket’ ‘–http11-socket’ ‘–http-socket-modifier2’ ‘–http-socket-modifier1′
getopt_long() error
主要是用 yum 安装的 uwsgi,缺少 python 的 plugin,可以安装对应的插件
yum install uwsgi-plugin-python
plugins = python(加在 ini 配置文件中)
配置
uwsgi 可以使用命令行启动,也可以使用配置文件来启动,推荐使用配置文件来启动守护进程,配置文件内容如下
[uwsgi]
socket = 127.0.0.1:9090
stats = 127.0.0.1:9293
workers = 4
# 项目根目录
chdir = DJANGO_DIR
touch-reload = DJANGO_DIR
py-auto-reload = 1
# 在项目跟目录和项目同名的文件夹里面的一个文件
module= DJANGO_NAME.wsgi
pidfile = /var/run/inner_manager.pid
daemonize = /data/uwsgi9090.log
# If you plan to receive big requests with lots of headers you can increase this value up to 64k (65535).
buffer-size=65535
这里以 socket 形式运行 uwsgi,绑定了本地的 9090 端口,也就是上文 nginx 配置中 uwsgi_pass 指定的端口。
大概解释下几个配置的含义:

chdir—- 应用加载前 chdir 到指定目录,一般设置为 django 的工程根目录
touch-reload—- 如果修改 / 碰了指定的文件,那么重载 uWSGI
module—- 加载一个 WSGI 模块的路径,如果 django 的话就指向对应的 wsgi 文件模块
buffer-size—- 设置请求的最大大小 (排除 request-body),这一般映射到请求头的大小。默认情况下,它是 4k。如果你接收到了一个更大的请求 (例如,带有大 cookies 或者查询字符串),那么你也许需要增加它。它也是一个安全度量,所以调整为你的应用需要,而不是最大输出。该值如果太小会报错

具体参数含义可以到官方文档查找
然后使用命令启动 uwsgi 进程,其中 uwsgi.ini 为上面内容的配置文件
uwsgi -i uwsgi.ini
可以看下日志文件有没有报错,或者看下 ps -ef|grep uwsgi 进程有没有跑起来。一定要确保进程正常 run 起来才行
至此,DJANGO 已经通过 nginx+uwsgi 可以访问了
三、配置访问 vue
其实这里访问编译好的 vue 静态文件有很多方式,本文主要讲述通过 nginx 直接访问和通过 django 路由访问
通过 django 路由访问
其实我们也可以直接通过 http://ip:8080/ 来经由 django 的路由来访问 vue 的页面。当然要做到这样要确保以下配置的正确
找到 DJANGO_DIR 根目录下 DJANGO_NAME 同名文件夹下 urls.py,使用通用视图创建最简单的模板控制器,增加一行路由
url(r’^$’, TemplateView.as_view(template_name=”index.html”)),
这样访问 http://ip:8080/ 时会直接返回 index.html。
上一步使用了 Django 的模板系统,所以需要配置一下模板使 Django 知道从哪里找到 index.html。在 project 目录的 settings.py 下:
TEMPLATES = [
{
‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’,
‘DIRS’: [VUE_HTML_DIR],
‘APP_DIRS’: True,
‘OPTIONS’: {
‘context_processors’: [
‘django.template.context_processors.debug’,
‘django.template.context_processors.request’,
‘django.contrib.auth.context_processors.auth’,
‘django.contrib.messages.context_processors.messages’,
],
},
},
]
按照上述配置完成后,结合前面配置好的 nginx 和 uwsgi,你已经可以通过 http://ip:8080/ 来访问到对应的 vue 编译好的 VUE_HTML_DIR 目录下的 index.html 了,但是这时候你可能会有其他困扰,比如找不到 css 样式文件的问,这经常是静态配置有误导致找不到静态文件的问题。
Django 通过 django.contrib.staticfiles 来管理静态文件,首先确保 django.contrib.staticfiles 已经添加到 INSTALLED_APPS。
然后可以在 DJANGO 的配置文件 settings.py 中增加以下几个配置:
STATIC_URL = ‘/static/’
STATIC_ROOT = os.path.join(BASE_DIR, “static”)
# Add for vuejs
STATICFILES_DIRS = [
VUE_STATIC_DIR,
# other static folders
]

STATIC_URL 对外提供 WEB 访问时 static 的 URL 地址

STATIC_ROOT 设置绝对路径, 用来保存收集到的静态文件,服务器最终也将从该路径中获取文件进行转发。在 collectstatic 运行的时候会把 STATICFILES_DIRS 中的静态文件拷贝到这个目录中, 达到从开发环境到生产环节过程中移植静态文件的作用。

STATICFILES_DIRS 用来配置一些开发环境下生成的静态文件的地址,即编译好的 VUE_STATIC_DIR

在 url.py 中添加路由
url(r’^static/(?P<path>.*)$’, static.serve,
{‘document_root’: settings.STATIC_ROOT}, name=’static’),
配置好以上配置后,编译好的静态文件还在 VUE_STATIC_DIR 目录下,我们最终要执行下面命令才能把 STATICFILES_DIRS 中的静态文件拷贝到 STATIC_ROOT 这个目录中,也就是最终生产环境指定的 static 的存放目录
python manage.py collectstatic
那么为什么不直接手动把构建好的 VUE_STATIC_DIR 中的文件拷过来呢,因为 Django 自带的 App:admin 也有一些静态文件(css,js 等),它会一并 collect 过来,毕竟 nginx 只认项目跟目录的静态文件,它不知道 django 把它自己的需求文件放到哪了
这样你访问 django 的 admin 网址 http://ip:8080/admin 时,也不会出现找不到 css 的问题了
当然这种方式其实是通过 django 的路由来访问静态文件的,一般的,生产环境不会通过 django 来转发静态文件,而是通过其他服务器进行转发,比如 nginx,apache 等,所以这里我们需要再配置下 nginx 的配置文件,在 8080 的 server 中增加如下路径的配置
location /static/ {
expires 30d;
autoindex on;
add_header Cache-Control private;
alias VUE_STATIC_DIR;
access_log off;
}
这样访问静态文件便会直接通过 nginx 来访问了,不用担心静态文件访问导致 Django 的处理速度变慢了。
通过 nginx 直接访问
如果你想直接通过 nginx 访问对应的前端 vue 文件,可以重新配置一个 server 来访问对应的 html 文件,比如上面已经使用了 8080 端口,我们可以用默认的 80 端口来配置个 server,其中 root 可以指向存放 index.html 文件的路径,/static/ 路径下的 root 路径可以指向 html 对应的存放 css 和 js 的 static 文件夹,如果 static 就在 index.html 路径下,不指认也可以。直接修改 /etc/nginx.conf 即可,里面已经有配置好的 80 端口的 server
配置如下所示
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
root VUE_HTML_DIR;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;

location / {
}

location /static/ {
root VUE_STATIC_DIR;
access_log off;
}

error_page 404 /404.html;
location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
这样我们可以通过 http://ip:80/ 来访问 vue 编译好的页面,使用 http://ip:8080/ 访问 django 配置的 cgi 请求
四、通过 supervisor 管理进程
上面我们已经用到了 uwsgi,后面可能还会用到 redis、celery,都需要开启守护进程,其中 celery 自身还不支持守护进程。那么如何管理这么多进程呢,这时候可以考虑下 supervisor
安装
使用 pip 安装即可
pip install supervisor
配置
我们可以配置 redis,celery,uwsgi 进去,比如向下面一样
[program:redis]
; 指定运行目录
directory=%(here)s/
; 执行命令(redis-server redis 配置文件路径)
command=redis-server /etc/redis.conf

; 启动设置
numprocs=1 ; 进程数
autostart=true ; 当 supervisor 启动时, 程序将会自动启动
autorestart=true ; 自动重启

; 停止信号
stopsignal=INT

[program:celery.worker.default]
; 指定运行目录
directory=%(here)s/
; 运行目录下执行命令
command=celery -A DjangoProject worker –loglevel info –logfile log/celery_worker.log -Q default -n %%h-%(program_name)s-%(process_num)02d
process_name=%(process_num)02d

; 启动设置
numprocs=2 ; 进程数
autostart=true ; 当 supervisor 启动时, 程序将会自动启动
autorestart=true ; 自动重启

; 停止信号, 默认 TERM
; 中断:INT (类似于 Ctrl+C)(kill -INT pid),退出后会将写文件或日志 (推荐)
; 终止:TERM (kill -TERM pid)
; 挂起:HUP (kill -HUP pid), 注意与 Ctrl+Z/kill -stop pid 不同
; 从容停止:QUIT (kill -QUIT pid)
stopsignal=INT

[program:uwsgi]
; 指定运行目录
directory=%(here)s/
; 运行目录下执行命令
command=uwsgi -i conf/uwsgi/uwsgi9090.ini

; 启动设置
numprocs=1 ; 进程数
autostart=true ; 当 supervisor 启动时, 程序将会自动启动
autorestart=true ; 自动重启

; 停止信号, 默认 TERM
; 中断:INT (类似于 Ctrl+C)(kill -INT pid),退出后会将写文件或日志 (推荐)
; 终止:TERM (kill -TERM pid)
; 挂起:HUP (kill -HUP pid), 注意与 Ctrl+Z/kill -stop pid 不同
; 从容停止:QUIT (kill -QUIT pid)
stopsignal=INT
使用
启动 supervisor 输入如下命令,使用具体的配置文件执行:
supervisord -c supervisord.conf
关闭 supervisord 需要通过 supervisor 的控制器:
supervisorctl -c supervisord.conf shutdown
重启 supervisord 也是通过 supervisor 的控制器:
supervisorctl -c supervisord.conf reload
一些特殊的变量
%(here)s 配置文件所在路径
(program_name)s program 的名字
%(process_num)02d 多进程时的进程号
注意:command 中如果含有 %,需要进行转义 %%
多进程时如果不指定 process_name 会遇到如下错误
Error: Format string ‘celery -A INTProject worker –loglevel info –logfile log/celery_worker.log -Q diff_task,caller_task -n %h’ for ‘program:celery.worker.mac.command’ is badly formatted: incomplete format in section ‘program:celery.worker.mac’ (file: ‘supervisord.conf’)
中间可能遇到的坑
*8107 recv() failed (104: Connection reset by peer) while reading response header from upstream, client 错误
使用 django+uwsgi+nginx,发现如下报错
2018/10/08 14:34:33 [error] 12283#0: *8107 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 9.19.161.66, server: 132.232.50.225, request: “GET /auth/info?token=ZXlKaGJHY2lPaUprWldaaGRXeDBJaXdpZEhsd0lqb2lTbGRRSW4wOjFnOVA3aDp0bVZYcmg3XzJPR3RXSHJrbXFLRVdCZEpUdXc_ZXlKMWMyVnlibUZ0WlNJNkltVjBhR0Z1Wm1GdUlpd2lhV0YwSWpveE5UTTRPVGd3TkRjekxqZzVNekk1TVgwOjFnOVA3aDpMVXRHZkFiQkhrRTNaenFnS3NuS1RvOHBOMGM_3bdf34e6de16096f9982015a2382d3c8 HTTP/1.1”, upstream: “uwsgi://127.0.0.1:9090”, host: “int.oa.com”, referrer: “http://int.oa.com/”
I finally found a reference to fastcgi and a 502 bad gateway error (https://support.plesk.com/hc/…). That lead me to look for a buffer size limit in the uwsgi configuration which exists as buffer-size. The default value is 4096. From the documentation, it says: If you plan to receive big requests with lots of headers you can increase this value up to 64k (65535).
意思是 uwsgi 中有一项配置是 buffer-size,表明收到的最大请求 size,默认是 4096,可以将其改成 65535
buffer-size=65535
此文已由作者授权腾讯云 + 社区发布

正文完
 0