在上一篇博文中,向大家介绍了Users App和Index的前端部分的实现,以及前端与Django的通信部分。至此,我们的博客已经具备一个简单的雏形,可以将其部署在本地的服务器上了。目前较为流行的web服务器有apache,nginx等等,我们这里选择uwsgi+nginx的方式进行部署。
在部署博客之前,我们首先来看看Django、uwsgi和nginx三者之间的关系。Django为Web框架,它用于处理客户浏览器发送给web服务器的各种Http请求,并返回相关页面;而uwsgi则是一种uWSGI服务器提供的WSGI协议,该协议用于将发送给web服务器的各种请求转发给Web框架,诸如Django、Flask等。在nginx+uwsgi的架构中,uWSGI服务器仅作为中间件使用,若没有nginx作为web服务器,uWSGI自身也可以作为web服务器使用。在我们这里,采用nginx作为真正的web服务器,用于接收客户发送的各种Http请求,并通过uwsgi协议转发给Django相关的View函数。所以,三者的关系如下图所示:
浏览器的http请求首先发到nginx服务器,nginx服务器通过uwsgi协议将http请求按照一定的格式打包好后发送给Django,然后由Django处理这些请求并返回页面给浏览器。
使用nginx服务器的好处主要有两点:1.外部的http请求仅能发送给nginx服务器,而不能直接发送给内网,提升了网站的安全性;2. Django这种web框架比较适合用于处理动态请求,而用来处理静态文件如图片等会导致性能的浪费,因此可以将处理静态文件的工作交给nginx来处理;3. nginx提供了较好的高并发性,当访问量较大的时候不会有太大的性能问题。
了解了这三者的关系后,我们就可以开始部署了。首先是uwsgi和nginx的安装,在Ubuntu下,输入以下命令先后安装uwsgi和nginx:
- pip3 install uwsgi
pip3 install uwsgi
- sudo apt-get install nginx
sudo apt-get install nginx
在安装好这两个后,我们就可以对它们进行配置了。首先来看uwsgi的配置。
uwsgi的配置分为两部分:uwsgi的参数配置和uwsgi的启动配置。uwsgi的参数配置定义了uwsgi在运行中所需要的一些参数,而uwsgi的启动配置定义了uwsgi启动时要建立的进程数、线程数等等。首先来看uwsgi的参数配置,我们可以在myblog目录中建立名为uwsgi_params的文件,输入以下内容:
- uwsgi_params
- uwsgi_param QUERY_STRING $query_string;
- uwsgi_param REQUEST_METHOD $request_method;
- uwsgi_param CONTENT_TYPE $content_type;
- uwsgi_param CONTENT_LENGTH $content_length;
- uwsgi_param REQUEST_URI $request_uri;
- uwsgi_param PATH_INFO $document_uri;
- uwsgi_param DOCUMENT_ROOT $document_root;
- uwsgi_param SERVER_PROTOCOL $server_protocol;
- uwsgi_param REQUEST_SCHEME $scheme;
- uwsgi_param HTTPS $https if_not_empty;
- uwsgi_param REMOTE_ADDR $remote_addr;
- uwsgi_param REMOTE_PORT $remote_port;
- uwsgi_param SERVER_PORT $server_port;
- uwsgi_param SERVER_NAME $server_name;
- uwsgi_param UWSGI_SCRIPT myblog.wsgi;
- uwsgi_param UWSGI_CHDIR xxx/djangotest/myblog;
uwsgi_params uwsgi_param QUERY_STRING $query_string; uwsgi_param REQUEST_METHOD $request_method; uwsgi_param CONTENT_TYPE $content_type; uwsgi_param CONTENT_LENGTH $content_length; uwsgi_param REQUEST_URI $request_uri; uwsgi_param PATH_INFO $document_uri; uwsgi_param DOCUMENT_ROOT $document_root; uwsgi_param SERVER_PROTOCOL $server_protocol; uwsgi_param REQUEST_SCHEME $scheme; uwsgi_param HTTPS $https if_not_empty; uwsgi_param REMOTE_ADDR $remote_addr; uwsgi_param REMOTE_PORT $remote_port; uwsgi_param SERVER_PORT $server_port; uwsgi_param SERVER_NAME $server_name; uwsgi_param UWSGI_SCRIPT myblog.wsgi; uwsgi_param UWSGI_CHDIR xxx/djangotest/myblog;
这里的大多数配置都不需更改,我们只需根据自己的情况修改最后两行内容:uwsgi_param UWSGI_SCRIPT和uwsgi_param UWSGI_CHDIR。前者决定了uwsgi要调用哪个uwsgi模块,而后者决定了网站的路径。
uwsgi的启动配置可以通过三种方式来配置:xml文件、ini文件和json,主流方式多使用ini文件进行配置,因此我们也采用ini文件进行配置。我们在myblog/myblog目录下建立一个名为uwsgi.ini的文件,输入以下内容:
- # uwsgi.ini
- [uwsgi]
- # Django-related settings
- socket = 127.0.0.1:3031
- # the base directory (full path)
- chdir = 你自己的网站目录
- # Django s wsgi file
- #wsgi-file = wsgi.py
- module = myblog.wsgi:application
- # process-related settings
- # master
- master = true
- #daemonize = 自己的Log文件路径,如/log/xxx.log
- # maximum number of worker processes
- processes = 4
- threads = 2
- stats = 127.0.0.1:9191
- buffer-size = 65536
- plugins = python
# uwsgi.ini [uwsgi] # Django-related settings socket = 127.0.0.1:3031 # the base directory (full path) chdir = 你自己的网站目录 # Django s wsgi file #wsgi-file = wsgi.py module = myblog.wsgi:application # process-related settings # master master = true #daemonize = 自己的Log文件路径,如/log/xxx.log # maximum number of worker processes processes = 4 threads = 2 stats = 127.0.0.1:9191 buffer-size = 65536 plugins = python
下面解释一下该ini文件中各个参数的含义:
socket = 127.0.0.1:3031:uwsgi要连接到的端口,可以是ip+端口号,也可以是unix的socket,这里我们绑定本地的3031端口。
module = myblog.wsgi:application:要加载的python WSGI模块,这里的myblog.wsgi:application其实是myblog目录下的wsgi.py文件中的application,该文件由Django在建立工程时自动产生,如下所示:
- # myblog/wsgi.py
- import os
- from os.path import join,dirname,abspath
- import sys
- from django.core.wsgi import get_wsgi_application
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myblog.settings")
- application = get_wsgi_application()
# myblog/wsgi.py import os from os.path import join,dirname,abspath import sys from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myblog.settings") application = get_wsgi_application()
master = True:启动主进程
daemonize = log文件路径:在设定了daemonize选项后,uWSGI服务器会以后台方式运行,并把log记录在你指定的日志文件中。由于uWSGI设定为后台后不太好关闭,不利于新功能的调试工作,因此我在这里把它注释掉。
processes = 4:启动4个工作进程。
threads = 2:每个工作进程有2个工作线程。一般来说,threads和processes参数要配合使用,用threads参数为每个工作进程指定线程数。
stats = 127.0.0.1:9191:uWSGI提供一个Stats服务器机制,它会将uWSGI的状态以json的方式发送到这个服务器。这里对我们用途不大,可以不加。
buffer-size = 65535:接收请求的缓存大小。如果需要接收较大的请求,可以将其设的大一些。
plugins = python:指定python的版本
在配置好uwsgi后,我们就可以去配置nginx了。nginx的默认安装路径在/etc/nginx下,其配置文件为该路径下的nginx.conf,而其服务器程序放在/etc/init.d中。为了以后操作方便,我们可以用alias为其添加一个快捷命令:
- alias nginx = 'sudo /etc/init.d/nginx'
alias nginx = 'sudo /etc/init.d/nginx'
然后我们将目录切到/etc/nginx下,然后输入以下命令打开gedit,修改nginx.conf:
- sudo gedit nginx.conf
sudo gedit nginx.conf
该文件大体可分为http和mail两大部分,如下所示:
- nginx.conf
- user www-data;
- worker_processes auto;
- pid /run/nginx.pid;
- events {
- worker_connections 768;
- # multi_accept on;
- }
- http {
- ##
- # Basic Settings
- ##
- sendfile on;
- tcp_nopush on;
- tcp_nodelay on;
- keepalive_timeout 65;
- types_hash_max_size 2048;
- # server_tokens off;
- # server_names_hash_bucket_size 64;
- # server_name_in_redirect off;
- include /etc/nginx/mime.types;
- default_type application/octet-stream;
- ##
- # SSL Settings
- ##
- #ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
- #ssl_prefer_server_ciphers on;
- ##
- # Logging Settings
- ##
- access_log 自己的访问日志路径
- error_log 自己的错误日志路径
- ##
- # Gzip Settings
- ##
- gzip on;
- gzip_disable "msie6";
- server {
- listen 80;
- client_max_body_size 75M;
- }
- # gzip_vary on;
- # gzip_proxied any;
- # gzip_comp_level 6;
- # gzip_buffers 16 8k;
- # gzip_http_version 1.1;
- # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
- ##
- # Virtual Host Configs
- ##
- #include /etc/nginx/conf.d/*.conf;
- #include /etc/nginx/sites-enabled/*.conf;
- }
- #mail {
- # 省略此部分内容
- #}
nginx.conf user www-data; worker_processes auto; pid /run/nginx.pid; events { worker_connections 768; # multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL Settings ## #ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE #ssl_prefer_server_ciphers on; ## # Logging Settings ## access_log 自己的访问日志路径 error_log 自己的错误日志路径 ## # Gzip Settings ## gzip on; gzip_disable "msie6"; server { listen 80; client_max_body_size 75M; } # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ## # Virtual Host Configs ## #include /etc/nginx/conf.d/*.conf; #include /etc/nginx/sites-enabled/*.conf; } #mail { # 省略此部分内容 #}
由于nginx不仅可以作为web服务器使用,也可以作为邮件服务器使用,所以其配置文件会分为http部分和mail部分。我们在这里只需使用到http部分的内容,故将mail部分省略。
对于http部分,我们基本不用动它的默认配置,只是要把access_log和error_log配置成自己的路径,以便当服务器错误时查看对应的日志。我们要做的是在http中的server块中添加一些配置,使nginx与刚才配置好的uwsgi绑定在一起,并且还要设置前几篇博文中提到的图片目录,实现nginx处理静态文件请求的目的。
加好的server块内容如下:
- nginx.conf http/server块
- server {
- listen 80;
- client_max_body_size 75M;
- location / {
- include uwsgi_params文件路径;
- uwsgi_pass 127.0.0.1:3031;
- index index.html index.htm;
- }
- location /media/logoimages/ {
- alias /media/logoimages/的绝对路径;
- }
- location /static/ {
- alias static/的绝对路径;
- }
- }
nginx.conf http/server块 server { listen 80; client_max_body_size 75M; location / { include uwsgi_params文件路径; uwsgi_pass 127.0.0.1:3031; index index.html index.htm; } location /media/logoimages/ { alias /media/logoimages/的绝对路径; } location /static/ { alias static/的绝对路径; } }
listen 80:在nginx服务器启动后,nginx要监听的端口号
location块:location块用于与请求的URI进行比较,若URI与对应的location相匹配,则进入对应的location块进行操作。
location /块:当访问网站主页,即127.0.0.1:80时,即会匹配到/块。这个块主要执行了三个操作:使用include参数将之前定义好的uwsgi_params文件包含进来;用uwsgi_pass参数配置接收uwsgi发送请求的端口号,从而实现接收uwsgi转发的请求;用index参数指定了主页的html文件。
location /media/logoimages/块:用alias命令将media/logoimages/指向一个绝对路径,这样当nginx接收到如127.0.0.1/media/logoimages/xxx.jpg文件的请求时,它就会到alias指定的目录中去取得图片并显示出来,否则就会产生一个404错误,图片无法显示。
location /static块:与/media/logoimages/块类似。
在修改好相关文件后,我们就可以依次启动uwsgi和nginx了!
首先回到刚才编写uwsgi.ini的路径下,输入以下命令:
- uwsgi uwsgi.ini
uwsgi uwsgi.ini这样便启动了一个uWSGI服务器,由于我们刚才没有设置后台执行,它会在控制台上显示出一些系统的基本信息,以及我们刚才的配置信息等。接下来,让我们启动nginx。如果刚才为nginx设置了别名的话,我们可以输入以下命令来启动nginx:
- nginx start
nginx start
此时,我们打开浏览器,输入12.7.0.0.1,应该就可以看到我们的index主界面了。
在nginx配置好后,我们可能会根据需要向nginx里添加新的location块。当我们修改好之后,我们可以使用以下命令让nginx重新加载修改好的配置文件,而无需重启nginx:
- nginx reload
nginx reload
此外,当我们以后对Django的程序进行修改时,都需重启uwsgi服务器,以使得服务器能使用新的Django程序。
好了,我们终于把博客的雏形部署在了本地的nginx服务器上。在下一篇博文中,将陆续介绍blogs App的实现,这里可以提前放个提纲:
1. blogs App Model的建立
2. blogs App功能实现:发布博客、发布评论、博客管理、存储草稿等
3. blogs App 前端部分的实现:ckeditor富文本编辑器的使用、Ajax定时及手动存储草稿
4. 陆续添加的其他功能