线上项目部署
Posted 孟郊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线上项目部署相关的知识,希望对你有一定的参考价值。
centos7下部署Django(nginx+uwsgi+python3+django)
先连接服务器,使用命令行里面的ssh root@xxx 即可连接,这里的“xxx”就是服务器IP地址,会车后会提示输入密码,密码输入的时候是被隐藏的,输完即可连接服务器,然后进行命令行操作。
我们的python有现成的部署虚拟环境,这个东西,你下载好之后,不同的项目用到的是不一样的环境版本配置,为了更好的做隔离,需要用这个虚拟环境做区分。
这个虚拟环境是需要安装的,要安装到服务器中之后,才能基于它,使用下面的命令,然后配置你所需要的文件。我这里没有写安装过程,日后补上。
virtualenv
linux下virtualenv其它命令
列出虚拟环境列表
workon
也可以使用lsvirtualenv
新建虚拟环境
mkvirtualenv [虚拟环境名称]
启动/切换虚拟环境
workon [虚拟环境名称]
删除虚拟环境
rmvirtualenv [虚拟环境名称]
我们项目部署需要用到uwsgi,它可以开启多进程,启动多个uwsgi实例,然后让nginx来做静态文件处理,以及负载均衡和反向代理.
{启动多个uwsgi通过nginx做集群,静态文件放到nginx,静态请求通过nginx直接相应,动态请求转发给uwsgi,如果在Windows上开发的话,配置了虚拟环境,否则安装一些python包和依赖会有问题}
接上面的虚拟环境virtualenv
yum install lrzsz
nginx里面可以做反向代理,负载均衡(LVS更大平台做做负载均衡,haproxy也是),处理静态文件,
uwsgi处理动态请求
linux里面命令后加上&符号都是在后台运行
tornado里面部署只需要用nginx就可以,
在安装python前先安装各类基础模块
yum install gcc-c++
yum install wget openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel
yum install libxml*
yum -y install zlib*
yum remove lrzsz -y
yum install lrzsz -y
关闭防火墙
systemctl stop firewalld
———————————————————————————————-
编译安装python3
mkdir /application/
cd /application/
wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz
tar xf Python-3.6.3.tgz -C /usr/local/src/
cd /usr/local/src/Python-3.6.3/
./configure –prefix=/usr/local/python3
make && make install
连上服务器之后先进入为项目新建的虚拟环境中,然后在git上把项目拉下来,这里用git是比较方便的,用其他方法也行,比如硬拖拽也可以,下一些依赖包即可。
然后在服务器的虚拟环境中生成requirements.txt文件,建议使用
pipreqs <path>
path是项目路径,在当前路径就用
pipreqs ./
一般就能直接生成,我自己遇到过报错,提示ascii编码有问题,后来发现是iTerm编辑器不能显示中文,后来改了iTerm的编码就可以运行了
然后下载项目所需要的包和依赖,在当前路径下载,或者把requirements文件的路径贴到-r后面也一样
pip install -r requirements.txt
然后把数据库连接做好,要连上服务器的数据库,ip,端口,库名,数据库用户名,数据库用户密码。
还要做数据库迁移,
python manage.py makemigrations & python manage.py migrate
然后启动文件
python manage.py runserver 0.0.0.0:8000
此时应该可以访问到你的项目地址了
如果有报错,就需要你去排查项目本身的问题了。
再来配置uwsgi
pip install uwsgi
然后创建一个uwsgi.ini 文件,可以在任何地方,前提是你必须要记住它的绝对路径,它是启动uwsgi服务的启动文件,必须要能清晰地找到它的绝对路径
我是创建在跟项目同级的目录下的
项目目录地址:/data/oldboy/
目录结构如下:
-oldboy
-app01
-app02
-oldboy
-setting
-url
-wsgi.py
-static
-templete
创建uwsgi文件,
cd /data/
mkdir script
cd script/
touch uwsgi.ini
然后在里面加上参数:
先上一个简单版本:
http = 0.0.0.0:9005 # ip:端口 chdir = /data/oldboy/ # 项目根目录 项目名称(oldboy) wsgi-file = oldboy/wsgi.py # 项目名称(oldboy)/wsgi.py --->这里的wsgi.py是Django项目的启动文件(固定的),凡是Django项目,找到setting文件,它同级的有一个wsgi文件,就是它
# 如果是flask项目,就把flask项目的启动文件放这里,因为flask的目录是自定义的,找到Flask类实例化出来的变量名(例“app”),有app.run()这一行命令的文件,它就是启动文件,放到这个参数即可 # flask启动文件也要带上路径
processes = 4 # uwsgi的启动进程数量
还需要补充的一点就是module参数,它跟wsgi-file是可以互换的,两者取其一
module=oldboy.wsgi # 跟上面的wsgi-file写法不同,但是格式是一样的,Django项目专用写法。
flask写法:
app = hello # 这里是写有“app.run()” 的那个启动文件的文件名
module = %(app) # 然后这里跟上一行同时存在。这个配置还没有试过,先留着。也许有坑。
还有一种配置文件参数要更多一些:
[uwsgi] # 项目目录 chdir=/data/oldboy# 启动uwsgi的用户名和用户组 uid=root gid=root # 指定项目的application module=pro.wsgi # 指定sock的文件路径,这是跟nginx配合使用的,如果先配置好uwsgi想试一下效果,就把它先注释掉。 socket=/data/script/uwsgi.sock # 启用主进程 master=true # 进程个数 workers=5 pidfile=/data/script/uwsgi.pid # 自动移除unix Socket和pid文件当服务停止的时候 vacuum=true # 序列化接受的内容,如果可能的话 thunder-lock=true # 启用线程 enable-threads=true # 设置自中断时间 harakiri=30 # 设置缓冲 post-buffering=4096 # 设置日志目录 (这里遇到坑了,如果还没有配nginx,建议先注释掉,我试过如果不注释掉无法启动uwsgi,按理说逻辑不应该是这样的,解释不通,但是现象如此,大家可以多试试。nginx配好打开注释即可) daemonize=/data/script/uwsgi.log ########################################
我们这里有提示过,daemonize和socket这两个参数先注释掉,然后启动uwsgi服务。此时可以关掉上面python manange.py runserver的服务了。
进入到上面的uwsgi.ini文件的目录下面,执行启动服务命令
uwsgi --ini uwsgi.ini
停止服务命令,同上也要在该文件的路径下才可以执行如下命令
uwsgi –stop uwsgi.pid
查看uwsgi日志 # 前提是有日志配置能生成日志 tail -f /data/script/uwsgi.log
就能看到如下提示:
“
*** Starting uWSGI 2.0.17.1 (64bit) on [Mon Mar 25 19:18:37 2019] ***
”
然后我们在浏览器url里面输入指定的IP端口以及项目中的地址和参数,就可以访问服务了,跟python manage.py runserver一样的效果,页面可以正常访问。
同时我们在项目目录中会看到生成了一个新的文件夹“static_all”,里面是我们的项目里面的静态文件。注意:不能用Django项目自带的static目录,要另外建立一个,不要同名。
到此,uwsgi配置就完成了,主要就是把Django项目静态文件路径加一行配置,然后下载uwsgi模块,创建一个uwsgi.ini文件,然后把必须的参数配好放进去,就能启动uwsgi服务了。
接下来就是配置nginx了。后续会补充docker的配置,以及flask项目的配置。
先查看有没有装nginx
nginx -v
如下显示:说明有
nginx version: nginx/1.15.10
没有的话有简易安装方法,用yum
yum install -y nginx
————————————————————————————————- 编译安装nginx cd /application/ wget http://nginx.org/download/nginx-1.10.3.tar.gz yum install pcre-devel openssl-devel -y tar xf nginx-1.10.3.tar.gz cd nginx-1.10.3 useradd -s /sbin/nologin -M www ./configure make &&make install ————————————————————————————————-
编译安装的话,启动命令跟非编译安装是不一样的,小心有坑。
先找到配置文件地址
cd /etc/nginx
ls
找到nginx.conf,然后进行编辑。
如果不想用默认的进行编辑,也可以自己新建立一个文件,放到任何位置都行,重新配置也可以的(不过前提是要把默认的这个文件备份后删除原件,备份的时候另外起个文件名)。
这里是用的原文件编辑的
vim nginx.conf
具体参数如下:user root; # 这里用户要写成root,如果写成nobody,有坑,我踩过,改成root就能启动。worker_processes 4; # 进程数
user root; # 这里的user参数必须要设成root,否则会无法启动nginx服务,
worker_processes 4;
events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; log_format main \'$remote_addr - $remote_user [$time_local] "$request" \' \'$status $body_bytes_sent "$http_referer" \' \'"$http_user_agent" "$http_x_forwarded_for"\'; server { listen 80; server_name www.phno2.xyz; # 这里是你项目的url地址,或者写成 localhost 也行。 access_log /etc/nginx/logs/django.log; # 这是自己设定的nginx正常输出日志的日志地址 error_log /etc/nginx/logs/errordjango.log; # 也是自己设定的,nginx错误日志地址 charset utf-8; gzip on; error_page 404 /404.html; error_page 500 502 503 504 /50x.html; # 指定项目路径uwsgi location / { include /etc/nginx/uwsgi_params; # 这里的uwsgi_params是系统自带的,路径都是一样的,把路径写完整即可。 uwsgi_connect_timeout 30; uwsgi_pass unix:/data/script/uwsgi.sock; #*****这里是五颗星,必须要改动的,而且是起关键作用的参数。unix: 是固定语法,
# 它后面是uwsgi配置的时候,socket参数后面的值,一定要跟uwsgi配置文件的socket参数保持一致,要一模一样。我这里都是用的sock文件路径,可以直接写IP:port,要写IP:port的话,就uwsgi和nginx
# 在相应的位置都写上IP:port,而且必须是一样的值。
} # 指定静态文件路径 location /static/{ # 这里的static是我们自己后来加上的,用于处理静态文件,这都是固定语法, root /data/oldboy/; # root是必须要写的,之前试过用alias替代root,会报错,找不到静态文件。还有一点是这里只需要写到项目的根目录即可,项目下一级的目录就不必写了,
# 因为在Django配置里面还要加上静态文件的路由分发,如果多写一层会报错,浏览器会找不到静态文件的。亲测有效,都是自己踩过的坑。 } } }
Django项目的setting文件需要在文件末尾加一条配置项:
STATIC_ROOT = os.path.join(BASE_DIR, "allstatic")
这是把Django所有的静态文件都收集到了这个文件里面---allstatic,让nginx集中处理用,还要执行下面的命令
cd /data/oldboy/oldboy/ # 找到项目目录下有manage.py文件的那个位置,执行这一条。
python3 manage.py collectstatic
然后查看项目,会自动生成一个名为“allstatic”的文件夹。
自此,nginx配置完成。
可以启动项目了。
上面已经启动了uwsgi,这里把uwsgi重新启动,之后,启动nginx
nginx
这就是启动命令,我是用yum安装的,用它就能启动(这个命令敲完,屏幕没有任何提示信息,即成功启动,可以去访问项目了,若是有提示信息就是报错了,查日志排错)
如果是编译安装就不是这个命令了,小心有坑。
查看nginx的进程
ps -ef |grep nginx
root 16293 14550 0 18:57 pts/1 00:00:00 grep --color=auto nginx # 这一条不是进程,是你输入上面的命令,系统提示给你的反馈,忽律即可。
root 32466 1 0 13:27 ? 00:00:00 nginx: master process nginx # master process是主进程,杀进程杀它即可停掉所有的nginx服务
root 32467 32466 0 13:27 ? 00:00:00 nginx: worker process
root 32468 32466 0 13:27 ? 00:00:00 nginx: worker process
root 32469 32466 0 13:27 ? 00:00:00 nginx: worker process
root 32470 32466 0 13:27 ? 00:00:00 nginx: worker process
停止nginx服务就杀进程即可(uwsgi服务也能杀进程停止服务)
kill 32466
在服务器(centos)中nginx默认日志路径
/var/log/nginx/
我们用yum装的许多插件,配置文件中默认日志路径就是在
/var/log/
还有一个类似启动文件的文件夹
/var/run/
这个var路径要记住,会很常用,日志在开发过程中,起到很关键的作用。
经常在部署时会遇到端口占用问题,这里查询端口占用情况,命令如下
netstat -tunlp |grep 27017
总结,核心点就是创建uwsgi配置文件,把核心参数配置好,module/wsgi-file(项目启动文件),chdir(项目根目录),然后设置nginx的配置文件核心参数,uwsgi_pass(跟uwsgi的socket相应的参数值,还有root,以及固定的unix:语法),location /static/ (静态文件路径),user(参数值必须要是root),项目的setting文件再加一个静态文件路径分发,再无其他,项目本身能运行,就已经完成了Django+uwsgi+nginx的所有配置。
PS:如果nginx还有media文件需要配置,参考static,逻辑一样。
gunicorn 部署
配置文件gunicorn.conf.py
import os base = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) bind = "0.0.0.0:80" workers = 2 accesslog = os.path.join(base, "check_list_app/flask_logs/access_guni.log") errorlog = os.path.join(base, "check_list_app/flask_logs/error_guni.log") pid = os.path.join(base, "check_list_app/flask_logs/pid_guni.log") daemon = True
如果用配置文件启动服务,命令如下
gunicorn -c/--config gunicorn.conf.py manage:app
或者写成shell脚本
gunicorn.sh
#!/bin/bash gunicorn --bind 0.0.0.0:8080 --workers 2
--access-logfile ./flask_logs/gunicorn_access.log
--error-logfile ./flask_logs/gunicorn_error.log
--pid ./flask_logs/gunicorn_pid.log manage:app &
写成脚本,需要加上权限设置,
chmod u+x gunicorn.sh
直接执行脚本即可
最简单的命令行启动服务
gunicorn -b 0.0.0.0:80 manage:app
这里的manage是文件manage.py的名字,这个文件是启动文件,如果你的项目启动文件是run.py ,那么这里就是run:app;
这里的app是我们的项目实例化出来的对象,这里我用的是flask项目示例,所以Flask实例化对象我取名为app,如你的项目是abc = Flask(__name__),那么就替换app成为abc。
个人感觉用gunicorn比uwsgi要方便些。
flask部署uwsgi配置文件
[uwsgi] http=0.0.0.0:9000 chdir=/data/cad_project_service/ touch-reload=/data/cad_project_service/ callable=app wsgi-file=/data/cad_project_service/views.py
# 配置的时候这个参数可以重启uwsgi服务,用单纯的kill是无法杀死进程的 daemonize = /data/cad_project_service/logs/uwsgi.log
# 这个是pidfile的配置参数,启动uwsgi之后,会把主进程写入到这个文件中,文件需要自己touch一下,uwsgi才能写入进程id。这个文件是作为kill进程的窗口
# 写好这个,以后要kill进程的时候只需要在这个pidfile的路径下执行一条命令即可
pidfile = /data/script/uwsgi.pid
2020-06-12更新的最新版。亲测可用,在服务器测试过。
# stop 后面是pidfile的路径,这样就能直接杀死进程了
uwsgi --stop /data/script/uwsgi.pid
在uwsgi的配置文件中,如果没有配置pidfile,但是配置了daemonize参数,要杀死进程,就需要如下命令
ps aux|grep uwsgi
#kill pid会发送SIGTERM,只会导致重启,而不是结束掉。需要找到你的uwsgi文件路径,写入到INT后面才可以。如果不知道的话可以用命令查一下
# 查看uwsgi的文件路径
which uwsgi
# 如下是显示结果
/admin/.virtualenvs/py35_flask/bin/uwsgi
# 这样在killall就能杀死uwsgi进程了。需要再启动的话就还是用uwsgi --ini uwsgi.ini 命令即可。uwsgi.ini文件记得带上路径,或者就在该文件路径下执行此命令
killall -s INT /admin/.virtualenvs/py35_flask/bin/uwsgi
以上是关于线上项目部署的主要内容,如果未能解决你的问题,请参考以下文章