使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用

    写在开头

        第一次用Flask做Web(也是第一次用Python做Web),在部署的时候遇到了不少问题,现在将过程就下来,供在这方面也有疑惑的人参考.(PS:使用Apache+mod_wsgi部署模式的可以参考另一个博主的这篇文章:http://blog.elnmp.com/post/python/apache-mod_wsgi-flask-pipenvxiang-mu-bu-shu)


   项目及服务器环境

        Python版本:3.6.5

        Flask版本:1.0.2

        服务器版本:CentOS 7.4

        Nginx与Uwsgi版本皆为目前最新


        部署开始

        Web项目

        虚拟环境

        为了防止Python包的版本之间起冲突,我们需要使用虚拟环境将各个项目隔离开来,一般对于这种情况网上的教程都会选择用原生的virtualenv,但是这里推荐一个超好用的第三方工具,据说也是Python官方推荐的虚拟环境管理工具,名字叫pipenv,使用方法自行百度,安装方法如下:

    pip install pipenv

        安装完成后,进入Flask项目根目录,使用pipenv创建虚拟环境,值得一提的是,pipenv不一定要用正规的install命令来创建环境,使用进入虚拟环境shell的命令也一样可以,pipenv会自动在虚拟环境列表中匹配当前项目的虚拟环境,如果找不到则会自动帮你新创建一个,具体如下:

    [root@shenghun Fisher] pipenv shell
    Creating a virtualenv for this project…
    Using /usr/local/bin/python3.6 (3.6.5) to create virtualenv…
    Spawning environment shell (/bin/bash). Use 'exit' to leave.
    . /home/shenghun/.local/share/virtualenvs/Fisher-kuuv-2eR/bin/activate
    [root@shenghun Fisher] . /home/shenghun/.local/share/virtualenvs/Fisher-kuuv-2eR/bin/activate
    (Fisher-kuuv-2eR) [root@shenghun]

        之后,由于虚拟环境间相互独立.因此需要重新安装一下包否则Python找不到包会造成程序崩溃,另外,由于pipenv生成的包统一会放在一个地方,和原生的virtualenv直接放在项目根目录不一样,所以注意记录下虚拟环境的地址,之后在配置Uwsgi和Nginx的时候用的上,地址为".home/shenghun/.local/share/virtualenvs/Fisher-kuuv-2eR",问我在哪看?你猜啊(~ ̄▽ ̄)~ 

        Uwsgi

        Uwsgi是一个Web服务器,具体信息就不再赘述了,自己找度娘,要使用Uwsgi,首先需要安装Python中的Uwsgi包,最好在全局环境和虚拟环境中都装上(起码我是这样的,如果不都装上会发生什么我也不知道),但需要注意的一点是,Uwsgi需要一些其他环境的支持,因此在安装Uwsgi前要把先行条件准备好:

    yum -y install gcc  gcc-c++ zlib zlib-devel openssl openssl-devel pcre pcre-devel GeoIP gd libXpm libxslt sqlite-devel

        完成之后,再使用pip install uwsgi(虚拟环境中使用pipenv install)安装Uwsgi.

        装完Uwsgi,我们还要在项目根目录下创建一个Uwsgi配置文件,实际上Uwsgi可以用命令使其带参数启动,但有了配置文件就不用每次写一大串命令了,为了方便,我直接把文件命名为uwsgi.ini, 大致配置如下:

    [uwsgi]
    # Http access port. 
    # If this option comes into effect, we can visit our web site on http://[our IP]:[Port]
    # http=:5001

    # Uwsgi's ip and port when it is loaded by Nginx
     socket=127.0.0.1:5001
    
    # Point to the main directory of the Web Site
     chdir=/home/Servers_Nginx/Fisher/
    
    # Setting up a virtual environment
     virtualenv=/root/.local/share/virtualenvs/Fisher-e_ddg0zZ

    # Python startup file
     wsgi-file=fisher.py

    # The application variable of Python Flask Core Oject 
     callable=app

    # The maximum numbers of Processes
     processes=1

    # The maximum numbers of Threads
     threads=2 

        其他的配置没什么好说的,英语稍微有点水平的都能看懂写的什么,重点在http和socket上,这两个配置是不能同时存在的(起码在我印象中),http是用来使外网能直接访问Uwsgi的,而socket是用来和Nginx通信的,Nginx获取到外网的请求后,就通过这个地址转发给Uwsgi处理,socket的用法在下面Nginx的配置文件中会看到.

        配置好了之后,可以用uwsgi uwsgi.ini命令查看是否成功配置,如果没问题,则会有以下启动信息(只截取一部分,事实上有老大一串):

    [uWSGI] getting INI configuration from uwsgi.ini
    *** Starting uWSGI 2.0.17 (64bit) on [Tue Jul  3 22:42:15 2018] ***
    compiled with version: 4.8.5 20150623 (Red Hat 4.8.5-16) on 02 July 2018 14:12:13
    os: Linux-3.10.0-693.21.1.el7.x86_64 #1 SMP Wed Mar 7 19:03:37 UTC 2018
    nodename: shenghun
    machine: x86_64
    clock source: unix
    pcre jit disabled
    detected number of CPU cores: 1
    current working directory: /home/Servers_Nginx/Fisher
    detected binary path: /usr/bin/uwsgi
    uWSGI running as root, you can use --uid/--gid/--chroot options

        Ctrl+C结束运行,开始Nginx的安装与配置

        Nginx

        Nginx是什么

        虽然只有Uwsgi也可以直接部署项目,但是为了安全,需要Nginx来进行请求代理,众所周知类似于学校之类的内部计算机通过信息中心服务器访问外网的行为称为正向代理,所有的访问请求都由中央服务器代理,此时正常情况下外网是不知道你的计算机的地址的;而Nginx的作用就是实现反向代理,正向代理代理的是内部计算机,而反向代理代理的是内部服务器,正是有Nginx存在,Uwsgi的真正接口才不会暴露在网络上,服务器的安全才有了一定的保障(当然,恶意攻击另说),此外,Nginx还自带防DDoS攻击机制.可以说日常使用是非常省心了.

        Nginx安装

        关于Nginx的安装,有很多种方法,这里选择了yum源安装(其他linux发行版也有类似的安装方法).

        yum源配置

        首先在/etc/yum.repo.d/文件夹下添加yum源,名字就叫做Nginx.repo吧(为了方便懒得起名)

    [root@shenghun yum.repos.d] vim Nginx.repo

        输入以上命令进入文件编辑,完成相关配置,对于yum源的配置官方文档是这么说的:

使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用_第1张图片

        其中baseurl中的OS需要改成自己的系统名,OSRELEASE需要改成系统的发型版本号.完成之后配置文件如下:

    [Nginx]
    name=nginx repo
    baseurl=http://nginx.org/packages/centos/7/$basearch/
    gpgcheck=0
    enabled=1

        配置完成后还没完,需要使用一下命令重新加载yum源:

    [root@shenghun yum.repos.d] yum clear all
    [root@shenghun yum.repos.d] yum makecache

        出现以下信息即为成功:

使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用_第2张图片

        其他系统添加源方法可以到http://nginx.org/en/linux_packages.html中查看,我就不一一赘述了.

        yum源安装

        之后就很简单了,直接yum install nginx就行,如果不想提示是否继续可以再加上-y参数像这样:

[root@shenghun /] yum -y install nginx

        回车以后会自动安装nginx,稍等一会,等屏幕出现successful install nginx就可以了,由于我这里已经安装成功了,所以是这样的:

使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用_第3张图片

        另外说一下,我这里选择yum除了安装方便外,还有一个很重要的因素,那就是yum安装可以自动将Nginx加入系统服务,不用再傻傻地到安装目录下适用./nginx或者一大串路径启动了,直接用systemctl(CentOS 6使用service)的start,stop,restart就可以完成启动,停止,重载,甚至可以用systemctl status nginx就可以直接看到nginx启动状态,非常方便:

使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用_第4张图片

        


     Nginx配置

        Nginx安装完成后,接下来就需要配置虚拟主机用以部署项目了,进入nginx配置文件目录,如果不知道在哪的可以使用一下方法找到:

    [root@shenghun /] whereis nginx


        第一个路径是启动快捷键,第二个Nginx依赖的一下库,第四个是nginx项目目录,第五个看名字就知道应该是文档之类的,所以配置文件目录是/etc/nginx没跑了.

        查看文件夹目录:

使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用_第5张图片

        

        编辑主配置文件

        主配置文件就是nginx.conf,使用vim进入编辑:

使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用_第6张图片

        新文件的worker_processes的值是1,这里最好改成auto,这样nginx可以根据需要自动匹配工作进程数,其他的就不用动了,关于虚拟主机的配置在最后一行有,意思就是每次启动nginx的时候自动载入/etc/nginx/conf.d/下的全部.conf文件,至于这些.conf文件是什么,等下就知道了.

        

        新建虚拟主机

        进入conf.d文件夹后查看文件夹目录发现,这里只有一个default.conf,使用vim查看一下:

使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用_第7张图片

        原来这就是虚拟主机的配置文件,默认监听的是80端口,如果80端口已经有进程占用了会启动失败,遇到启动失败的情况可以试着更改一下监听端口,此时启动Nginx就已经可以访问到欢迎页面了,这里我们改成6000端口试试:

    [root@shenghun conf.d] systemctl restart nginx

        在浏览器中使用http://IP地址:端口号查看一下

使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用_第8张图片

        成功启动!

        接下来就是正式的虚拟机配置了,在conf.d文件夹下新建一个.conf文件,名字就用项目名吧(方便些),使用vim进入,配置如下:

    upstream flask{
        server 127.0.0.1:5001;
    }


    # Virtual host, with this option, we can visit our web site on server_name.
    # If the server_name is an ip address and we has configured a DNS, 
    # we can also use the corresponding domain name.

    server {

        listen              5000;

        # domain name or ip address
        server_name         www.shenghuntianlang.xin;

        charset             utf-8;


        # the web site resources path    
        location / {
            include         uwsgi_params;

            # The inner address whilch point to Uwsgi. all the requests will resend to Uwsgo to resolve.
            # If we has configured the upstream options, we can fill in the upstream name instead.
            uwsgi_pass      flask;

            # If the following options are already exists in 'Uwsgi.ini'.these options can be ignored.
            # Configure Uwsgi's running environment path.
            # uwsgi_param   UWSGI_PYHOME    /root/.local/share/virtualenvs/Fisher-e_ddg0zZ;

            # Configure the main directory of web site
            # uwsgi_param   UWSGI_CHDIR     /home/Servers_Nginx/Fisher;

            # Configure the Flask Core Object
            # uwsgi_param   UWSGI_SCRIPT    fisher:app;

            }
    }    

        每个选项的作用都写在注释中了,不过还是稍微解释一下吧,首先upstream是用来做负载均衡的Nginx在接收到请求后,会将请求转发到其中的服务器上,这里的每一个server就是一个服务器,另外,127.0.0.1:5001是不是有点熟悉?是滴,就是上面配置的Uwsgi的socket,Nginx通过socket连接Uwsgi把请求发送到Uwsgi服务器,Uwsgi处理后把响应反馈给Nginx再由Nginx转发给客户端,使用upstream时只需要将设置的upstream名(这里是flask)填入server中的location中的uwsgi_pass就可以了,另外也可以不配置upstream,直接把Uwsgi的socket填入uwsgi_pass也行得通,

        其次是server的location,其中的include是加载uwsgi_params文件(本身在Nginx配置目录/etc/nginx下就有一个,可以看上面的截图),这个文件是用来确定Uwsgi的运行信息的,由于Nginx配置目录下有现成的,所以就不用管了,直接指向那个文件即可(如果有需要需要置顶到特定文件则需要填入绝对地址),还有就是下面全部注释掉的配置信息,这些是用来额外配置Uwsgi的启动配置的,如果Uwsgi的.ini文件里面有相关配置(虚拟环境啊核心APP对象啊什么的)就不需要了,因此这里只给了两个配置,uwsg_params文件和Uwsgi的socket.

        到此虚拟环境就配置成功了,另外配置完Nginx之后可以使用nginx -t测试配置文件,如果成功就万事大吉,有错误的话会有相关信息弹出,之后使用systemctl restart nginx重启Nginx,就可以用配置的server_name加端口访问Nginx了.


        杂记

        ※查看端口号监听状态与关闭监听进程

        查看端口号

    [root@shenghun /] netstat -ntlp | grep 5000
    tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN      10316/nginx: master 

        通过pid关闭监听进程

    [root@shenghun /] kill -9 pid

        使用场景:端口被占用,服务起不来

        注:其中pid是监听进程的名字的'/'前面的那个数字


        ※查看服务名相关运行信息并关闭

        查看服务名相关运行信息

    [root@shenghun /] ps -ef | grep nginx
    root     10316     1  0 10:37 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
    nginx    10317 10316  0 10:37 ?        00:00:00 nginx: worker process
    root     10589  8661  0 11:22 pts/6    00:00:00 grep --color=auto nginx

        关闭此服务

    [root@shenghun /] pkill -9 nginx

        使用场景:同名服务已存在,需要重新启动新服务

        注:此方式是关闭此服务名下的所有进程,如果需要精准关闭,可以使用通过pid方式,此外,就算关闭所有进程,仍然会有一个名为'grep --color=auto nginx'的进程存在(Uwsgi以及其他一些服务也是),属于正常情况,不比特别在意


        ※Nginx和Uwsgi无法同时启动

        解决方法:Nginx的监听端口不要和Uwsgi的端口一样,不然会起冲突导致其中一个起不来.


        ※自定义执行命令

        编辑用户目录下的.bashrc可以自定义执行命令:

    [root@shenghun ~] vim .bashrc

            使用Nginx+Uwsgi在CentOS服务器上部署Python Flask应用_第9张图片

        编辑完成后保存退出,并使.bashrc生效:

    [root@shenghun ~] source .bashrc

        此后就可以使用新命令了,另外可以用alias临时定义执行命令,只不过是暂时的,退出终端之后就没了.


        ※※切换程序前后台并在退出终端(xshell之类的工具同理)后继续执行

        切换前后台

        执行一个命令:

    [root@shenghun Fisher] uwsgi uwsgi.ini

        此时Uwsgi会在前台执行,在当前终端中无法进行其他操作,

        切换到后台,先Ctrl+Z挂起程序

            

        然后使用:

    [root@shenghun Fisher] bg

            

        此时程序在后台执行,终端解锁,可以进行其他操作,使用fg可以将后台的程序调到前台

            

        其他用法可以自行找度娘

        此外,即使程序在后台运行,一旦退出终端,程序进程仍旧会被系统kill掉,可以使用tmux工具:

        创建新会话:

    [root@shenghun ~] tmux new -s 会话名(自定)

        之后会进入新回话,底部会有绿色提示


        在这里面运行程序程序执行后,使用Ctrl+b | d(先输入Ctrl+b,再输入单个d)退出当前会话,此时会回到前面的终端环境

            

        使用Ctrl+b | s可以查看所有会话

            

        进入先前会话

    [root@shenghun ~] tmux attach -t uwsgi-fisher
        

你可能感兴趣的:(Python)