Centos下部署Nginx+uwsgi+Flask

本文将从头到尾详细讲述作者配置时遇到的所有问题及心得,如有困惑可以留言

如果你还不清楚Nginx、uwsgi和Flask的关系,可以看作者的上一篇文章

1.系统简介

首先本人的Centos版本是2.6,所以自带的Python版本也是2.6,但是作者的项目是在Python2.7下写的,所以第一步需要在Centos下安装Python2.7的版本,并切换到2.7版本下。为后面的安装其他的第三方安装包做好铺垫

 注意:这里的2.6版本的Centos将会给后面的安装部署带来一定的麻烦,请继续往后面看

2.uwsgi的安装和配置

uWSGI是一个由python实现的web容器,可以兼容性比较好地发布Django,Flask等pythonweb框架的应用。因为本质上来说uwsgi是python的一个模块,所以可以用pip install uwsgi直接来安装它。

注:这里最好用pip来安装,后来我在阿里云centos7.4下直接用yum安装,后来启动uwsgi的时候一直报错

Centos下部署Nginx+uwsgi+Flask_第1张图片

 

Centos下部署Nginx+uwsgi+Flask_第2张图片

理论上说报错no app loaded 应该是uwsgi配置中callable配置有问题,但是这次我反复确认了的确没问题,还是报错,然后就找启动uwsgi的日志,发现里面并没有python被加载,后来删除了yum安装的uwsgi,用pip重新安装uwsgi,就成功了。

yum卸载安装的软件    yum remove uwsgi

pip 安装软件   pip install uwsgi

安装完成之后可以在一个合适的目录建立一个uwsgi服务器的配置文件。比如我选择在项目的根目录建立了一个uwsgi.ini的文件。顺便一提,除了ini格式的配置,uwsgi还支持json,xml等多种多样的配置格式。这里以ini格式为例。

注意:这里会出现一个误区,作者的Centos专安装了yum,所以一开始就直接yum install uwsgi,这样安装的话uwsgi就默认安装到了默认的Centos下自带的Python版本中,这就导致在启动uwsgi之后在日志文件中发现Python版本是2.6,所以我的python项目中很多的import 都会报错(例如:ImportError : no module named MySQLdb.cursors)

Centos下部署Nginx+uwsgi+Flask_第3张图片

上图就是作者遇到的问题截图,uwsgi运行后日志里面的看到的python版本是2.6,所以大家在安装 uwsgi的时候要注意是在哪个Python版本下使用。

首先进入项目根目录 

       cd /ZGL/JinlinSoft.ZGLRemoteControl

然后创建uwsgi.ini

       vi uwsgi.ini

作者的uwsgi配置如下:


[uwsgi]
socket = /ZGL/JunlinSoft.ZGLRemoteControl/uwsgi.sock
#socket = 127.0.0.1:8080
#http = 127.0.0.1:8080
chdir = /ZGL/JunlinSoft.ZGLRemoteControl
processes = 4
threads = 2
pythonpath = /usr/lib/python2.7/site-packages
callable = app
pidfile = /var/run/uwsgi.pid
daemonize = /var/log/uwsgi.log
module = main
chmod-socket = 666

 依次解释一下这些配置项。

  •  socket指出了一个套接字,相当于为外界留出一个uwsgi服务器的接口。这里我用的是sock文件,没有用IP:端口是因为作者在后面运行遇到了错误,请看后面描述,如果只用了uwsgi,没有配合Nginx一起,这里就可以配置成http.
  •  pythonpath指出了python的目录.
  • module指出了项目启动脚本的名字.
  • wsgi-file指出了真正的脚本的文件名.
  • callable指出的是具体执行.run方法的那个实体的名字,一般而言都是app=Flask(__name__)的所以这里是app。
  • processes和threads指出了启动uwsgi服务器之后,服务器会打开几个并行的进程,每个进程会开几条线程来等待处理请求,显然这个数字应该合理,太小会使得处理性能不好而太大则会给服务器本身带来太大负担。
  • daemonize项的出现表示把uwsgi服务器作为后台进程启动,项的值指向一个文件表明后台中的所有输出都重定向到这个日志中去。
  • chmod-socket或chmod  unix socket是个文件,所以会受到unix系统的权限限制。如果你的uwsgi客户端没有权限访问uWSGI socket,你可以用这个选项设置unix socket的权限
  • pidfile 在失去权限前,将pid写到指定的pidfile文件中。

  • chdir 在失去权限前,使用chdir()到指定目录。

  以上这些配置项都是一些最为常见的配置项,实际上uwsgi还有很多很多配置。。除了写一个配置文件的启动方式之外,还有命令行的启动方式,这里就不多说了。请需要的自己百度uwsgi配置

  此外上面也说到这次碰到的一个坑,就是关于socket和http的差别。从概念上来说,socket本身不是协议而是一种具体的TCP/IP实现方式,而HTTP是一种协议且基于TCP/IP。具体到这个配置这里来,如果我只配了socket = 127.0.0.1:5051的话,通过浏览器或者其他HTTP手段是无法成功访问的。而在uwsgi这边的日志里会提示请求包的长度超过了最大固定长度。另一方面,如果配置的是http = 127.0.0.1:5051的话,那么就可以直接通过一般的http手段来访问到目标。但这会引起nginx无法正常工作。正确的做法应该是,如果有nginx在uwsgi之前作为代理的话应该配socket,而如果想让请求直接甩给uwsgi的话那么就要配http。

  配置完成之后就可以键入 uwsgi 配置文件.ini来启动uwsgi,再查看日志(如果配置了daemonize的话)如果最终没有报错,ps也能看到processes指定个数的uwsgi进程在跑的话说明成功启动。如果直接把uwsgi作为留给外部的连接接口发布应用的话当然也可以,但是一般而言我们肯定还要在uwsgi前面再加上一个nginx。nginx的好处在于可以进行安全过滤,防DDOS攻击,多台机器的负载均衡等工作。

  关于uwsgi服务器的停止,官方文档说可以uwsgi -HUP之类的命令操作,但是这需要找到这个uwsgi的pid,目前为止我都还是很粗暴地killall -9 uwsgi了。。

下面的错误是因为作者的uwsgi配置中callable配置错误报的错(no app loaded

Centos下部署Nginx+uwsgi+Flask_第4张图片

 

callable指出的是具体执行.run方法的那个实体的名字,一般而言都是app=Flask(__name__)的所以这里是app。所以这里在配置的时候大家请注意了

uwsgi 的运行方式

  • uwsgi --ini /ZGL/JunlinSoft.ZGLRemoteControl/uwsgi.ini

正确的运行结果

Centos下部署Nginx+uwsgi+Flask_第5张图片

3.Nginx的安装和配置

直接 python  -m pip install Nginx或者 yum install Nginx

安装完成后默认的nginx的配置文件位于/etc/nginx/conf.d/default.conf,可以直接修改了这个文件。在修改之前可以考虑先备个份。如果需要指定配置文件开启nginx可以加入-c参数。其实nginx默认读取的文件是/etc/nginx/nginx.conf,打开这个文件看看可以看到在其http块中有些include /etc/nginx/conf.d/*.conf,所以在那里的default.conf可以直接写server块。

上面的意思就是配置Nginx可以从两个文件中任选一个进行配置,我是在/etc/nginx/nginx.conf下面配置的,如下

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

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

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections  1024;
}


http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

   server {
        listen       80;            #默认的web访问端口
        server_name  127.0.0.1;     #服务器名
        #charset koi8-r;
        access_log  /var/log/nginx/access.log;    #服务器接收的请求日志,logs目录若不存在需要创建,否则nginx报错
        error_log  /var/log/nginx/error.log;         #错误日志

        location / {

            include        uwsgi_params;     #这里是导入的uwsgi配置

            uwsgi_pass     unix:/ZGL/JunlinSoft.ZGLRemoteControl/uwsgi.sock;   #需要和uwsgi的配置文件里socket项的地址
                                             #相同,否则无法让uwsgi接收到请求。

            uwsgi_param UWSGI_CHDIR   /ZGL/JunlinSoft.ZGLRemoteControl;     #项目根目录

            uwsgi_param UWSGI_SCRIPT main:app;     #启动项目的主程序(在本地上运行
                                                     #这个主程序可以在flask内置的
                                                     #服务器上访问你的项目)
       }
   }
}

主要需要我们配置的就是其中的server这一整块 ,listen监听的端口就是真正接收请求的接口。

注意:配置Nginx时作者遇到了一个问题,就是我配置好在运行的时候在nginx的access.log日志文件中发现了错误,

upstream prematurely closed connection while upstream prematurely closed connection while reading response header from upstream

截图如下

Centos下部署Nginx+uwsgi+Flask_第6张图片

 

找了很多资料后,尝试了很多之后,发现就是代理的地址需要将端口换成sock进程文件,所以这里的uwsgi_pass 我用的是sock文件,没有用端口,所以相应的uwsgi.ini的配置中用的也是sock文件。

Nginx常用命令

  • nginx   //启动
  • nginx   -s  stop/quit    //关闭
  • nginx   -s  reload    //重启加载配置

 

注意事项:

       1.nginx.conf和uwsgi.ini中使用的.sock文件是会自动生成的,必须保持两个配置文件的.sock文件保持一致

       2.配置过程中会用到的命令

                  打开某一个文件  :  vi    /var/log/uwsgi.log    //当没有这个文件的时候会自动创建,有的话就打开

                  编辑文件  : 打开文件后,按i,进入编辑模式,退出  ESC+Enter+wq

                  查看tcp端口使用情况 :netstat -ltunp

                  查看某类文件使用的进程  :ps -e|grep  uwsgi      ps -e|grep  uwsgi

                  杀死某个进程   :kill -9 66128(pid:进程号)

                  杀死某一类文件的进程:killall -9 uwsgi

                  清除日志文件:cat  /dev/null  > /var/log/uwsgi.log

至此Flask+uwsgi+Nginx 就配置结束了,如果不对请大家纠正。

你可能感兴趣的:(平台,系统运维,架构)