本文将从头到尾详细讲述作者配置时遇到的所有问题及心得,如有困惑可以留言
如果你还不清楚Nginx、uwsgi和Flask的关系,可以看作者的上一篇文章
首先本人的Centos版本是2.6,所以自带的Python版本也是2.6,但是作者的项目是在Python2.7下写的,所以第一步需要在Centos下安装Python2.7的版本,并切换到2.7版本下。为后面的安装其他的第三方安装包做好铺垫
注意:这里的2.6版本的Centos将会给后面的安装部署带来一定的麻烦,请继续往后面看
uWSGI是一个由python实现的web容器,可以兼容性比较好地发布Django,Flask等pythonweb框架的应用。因为本质上来说uwsgi是python的一个模块,所以可以用pip install uwsgi直接来安装它。
注:这里最好用pip来安装,后来我在阿里云centos7.4下直接用yum安装,后来启动uwsgi的时候一直报错
理论上说报错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)
上图就是作者遇到的问题截图,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
依次解释一下这些配置项。
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)
callable指出的是具体执行.run方法的那个实体的名字,一般而言都是app=Flask(__name__)的所以这里是app。所以这里在配置的时候大家请注意了
uwsgi 的运行方式
正确的运行结果
直接 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)
截图如下
找了很多资料后,尝试了很多之后,发现就是代理的地址需要将端口换成sock进程文件,所以这里的uwsgi_pass 我用的是sock文件,没有用端口,所以相应的uwsgi.ini的配置中用的也是sock文件。
Nginx常用命令
注意事项:
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 就配置结束了,如果不对请大家纠正。