Linux部署Python项目
项目部署
-
项目部署对于操作通常是由运维人员来进行统一管理装配的,但是对于一个开发人员来讲,基础的项目部署还是要会的。
-
这里我主要讲解python的项目是如何部署的,至于项目哪里来的,这就要看观众如何抉择了,可以把自己写好的项目部署,也可以......(此处省略。。。你懂的O.O)
-
最重要一点就是此篇随笔只是给初级的想部署自己小项目的开发人员看的,小打小闹,大神来此千万别认真,认真你就输了,这要是拿去公司部署,老板当天就能把你开掉,我毕竟不是专业运维人员,只是个草根开发。
一、部署前准备
部署有两种情况,线上部署,线下测试环境部署;线上部署就是指把自己的项目部署到远程的服务器上,类似阿里云,腾讯云或亚马逊这种服务器;线下部署就是指在自己电脑中安装一个VMware虚拟机(虚拟化技术:有效利用电脑中的未被占用的资源,高效利用服务器设备硬件资源,可以节省物理空间),VMWare让一个电脑中可以创建多个系统, 方便同时管理;
这里我讲解的是线上阿里云服务器部署,主要是现在我只有一台阿里云服务器,相对于本地的VMWare中安装Linux服务器,再阿里云中部署后,别人可以访问,更高大上一些。
我们需提前准备好一些部署所需要的东西
- 注册一个阿里云账号。购买一台阿里云服务器,推荐使用CentOS7,因为我所展示的就是CentOS7,至于为什么不推荐使用Ubuntu的原因是因为:相同的解释器相同的代码在这两个系统中不能直接运行,移植后都需要各种微调。至于服务器的购买步骤就去百度吧,对于学生来说是有学生机的,学生机相对于来说比较便宜一百元左右(至于学生这个概念阿里云上是有学生通道的认证时是看教育网上是否有你个人信息,但我和客服聊过,他说28岁以下都可以购买学生那种套餐,至于具体情况,可以和客服沟通);还有一种就是新注册用户的购买了,我个人认为还是一次性购买三年比较划算(不管是学生还是新用户);至于非新用户应该都是老司机,都懂的,可能我这部署人家都了解,只是偶尔进来看看。
- 购买域名,管局备案,公安备案,大概需要20天,不过的放心备案多久阿里云送多久,不过据说不管备案10天或者说20天,阿里云都是直接赠送30天的时长,只是听说我还真没注意。
- 购买免费赛门铁克,有一个0元一年的赛门铁克,赛门铁克是关于安全的东西,这个弄不弄都行,主要看你自己,因为看我这博客的应该都是些小白什么的来学习部署生产环境的,都是些自己编写的小项目。
- 下载Xshell和Xftp,这两个软件可以去官方网站上获取,社区版是免费的,尽量使用6版本,当然你想给人家当小白鼠也可已使用7,这两个软件前者是用来远程控制操作系统的,后者是文件传输用的,可以以图形界面的方式向远程的阿里云CentOS中上传文件。也就是把自己本地的项目上传到上面。
- 配置服务器安全组,开放80、8080、8000、443、6379、3306、这几个端口;
- 开放80端口外部才能通过Http访问服务器,
- 8080(也是一些WEB服务器的默认端口)和8000(djang默认启动端口)这两个端口主要是项目运行的时候常用到的,
- 443端口即网页浏览端口,主要是用于HTTPS服务,是提供加密和通过安全端口传输的另一种HTTP;
- 6379端口,缓存数据库redis的端口
- 如果需要使用多台服务器进行集群部署,负载均衡的时候是需要通过这些端口进行沟通访问的
二、安装关系型数据库
这里的数据库使用的是mariadb数据库。
MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可。
开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源的潜在风险,因此社区采用分支的方式来避开这个风险。
MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。
这个数据库是mysql开发者开发的另一款免费开源数据库。
-
首先在 RHEL/CentOS 和 Fedora 操作系统中添加 MariaDB 的 YUM 配置文件 MariaDB.repo 文件。
#编辑创建mariadb.repo仓库文件 vi /etc/yum.repos.d/MariaDB.repo
-
添加repo仓库配置
[mariadb] name = MariaDB baseurl = http://yum.mariadb.org/10.1/centos7-amd64 gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB gpgcheck=1
-
在Centos7中安装MariaDB数据库
# 当 MariaDB 仓库地址添加好后,你可以通过下面的一行命令轻松安装 MariaDB。 yum install MariaDB-server MariaDB-client -y
-
启动MariaDB的相关命令
systemctl start mariadb #启动MariaDB systemctl stop mariadb #停止MariaDB systemctl restart mariadb #重启MariaDB systemctl enable mariadb #设置开机启动 启动后正常使用mysql systemctl start mariadb
三、安装非关系型数据库
这里使用redis数据库,基本的redis使用方式请看博客:https://www.cnblogs.com/wylshkjj/p/12442412.html
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
-
安装redis
yum install redis -y 或者 wget http://download.redis.io/releases/redis-3.0.6.tar.gz tar xzf redis-3.0.6.tar.gz cd redis-3.0.6 make
-
启动redis,自己使用部署项目默认可以不配置,如若公司配置那就要设置配置文件
四、Nginx部署
1、web服务器和web框架的关系
web服务器(nginx):接收HTTP请求(例如www.pythonav.cn/xiaocang.jpg)并返回数据
web框架(django,flask):开发web应用程序,处理接收到的数据
2、Nginx
nginx是一个开源的,支持高性能,高并发的www服务和代理服务软件。它是一个俄罗斯人lgor sysoev开发的,作者将源代码开源出来供全球使用。
nginx比它大哥apache性能改进许多,nginx占用的系统资源更少,支持更高的并发连接,有更高的访问效率。nginx不但是一个优秀的web服务软件,还可以作为反向代理,负载均衡,以及缓存服务使用。安装更为简单,方便,灵活。nginx可以说是非常nb了
优点:
支持高并发,能支持几万并发连接
资源消耗少,在3万并发连接下开启10个nginx线程消耗的内存不到200M
可以做http反向代理和负载均衡
支持异步网络i/o事件模型epoll
3、nginx安装
-
下载源码包
wget -c https://nginx.org/download/nginx-1.12.0.tar.gz -
解压缩源码:tar -zxvf nginx-1.12.0.tar.gz
-
cd切换进入解压后文件夹nginx-1.12.0
-
配置、编译、安装 开启nginx状态监测功能
./configure --prefix=/opt/nginx1-12/ --with-http_ssl_module --with-http_stub_status_module
make && make install -
启动nginx,进入sbin目录,找到nginx启动命令
切换·目录:cd sbin
./nginx #启动
./nginx -s stop #关闭
./nginx -s reload #重新加载
4、安装完成后检测服务
netstat -tunlp |grep 80
curl -I 127.0.0.1
#如果访问不了,检查selinux,iptables
5、部署一个web站点
nginx默认站点是Nginx目录下的html文件夹,这里可以从nginx.conf中查到、
location /{
root html; #这里是默认的站点html文件夹,也就是 /opt/nginx1-12/html/文件夹下的内容
index index.html index.htm; #站点首页文件名是index.html
}
如果要部署网站业务数据,只需要把开发好的程序全放到html目录下即可
[root@centOS7 /tmp 11:34:52]#ls /opt/nginx1-12/html/
index.html jssts.jpeg lhy.mp4 man.jpg wget-log
因此只需要通过域名/资源,即可访问
http://www.pyyuc.cn/man.jpg
普通站点示例:
server {
listen 80;
server_name www.bzboy.info;
#只要用户访问www.bzboy.info:80/ 就走这个location匹配,反向代理给uwsgi;
location / {
# root html;
# index index.html index.htm;
include uwsgi_params;
uwsgi_pass 0.0.0.0:8000;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
#当用户请求时www.baboy.info/static/的时后
#就会进入这个locatoion匹配
#通过alias参数进行路径别名,让nginx去/opt/static底下找静态文件资源
location /static {
alias /opt/tracer/static;
}
}
6、Vue部署示例
server {
listen 80;
server_name luffy.bzboy.info;
location / {
root /opt/luffy/lufei_pc/dist;
index index.html;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 80;
server_name api.bzboy.info;
location / {
include uwsgi_params;
uwsgi_pass 0.0.0.0:9009;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location /static {
alias /opt/luffy/luffyapi/static;
}
}
五、安装Python
1、安装python解释器
在CentOS中默认有一个python2.7,但是对于我们现在,python2.7已经不足以满足市场需求了,一般情况除了好多大公司,尤其是金融公司的系统是比较老的,可能会出现python2.7外,几乎遇不到。我们现在开发都用python3版本,我这里使用的是python3.6.11版本和django1.11.9,这里有个坑,就是python3.6和django1版本是不会出现问题,但是当django2版本和python3.6版本一起使用时就会报一个错误:query = query.decode(errors='replace')
AttributeError: 'str' object has no attribute 'decode'
,
注:当出现这种报错时:打开文件:vim /root/Envs/drawer/lib/python3.7/site-packages/django/db/backends/mysql/operations.py的146行修改
把:query = query.decode(errors='replace')
改成:query = query # .decode(errors='replace')
或者改成:query = query.encode(errors='replace') # 推荐
还有就是urls.py文件的路径写法也有所变化:url -----> path ; url(正则) ---->re_path
-
下载之前要先下载依赖包:
yum install gcc patch libffi-devel python-devel zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel -y
-
下载python解释器:
wget https://www.python.org/ftp/python/3.6.11/Python-3.6.11.tar.xz
-
解压压缩包文件:
tar xvJf Python-3.6.11.tar.xz
-
cd切换到Python-3.6.11目录下
-
配置、编译、安装:
./configure --prefix=/opt/python
make && make install
-
加入python的启动环境变量,永久生效自动补全
只需要启动时执行一条命令即可 import rlcompleter, readline readline.parse_and_bind('tab:complete') 可以将上述的代码存于~/.pythonrc.py文件中。 然后,在~/.bashrc中设置 export PYTHONSTARTUP=~/.pythonrc.py 这样,每次启动终端,bash就会设置PYTHONSTARTUP这个环境变量,然后,python启动时就会使用这个变量指定的文件中的初始化代码。 在python解释器中,输入一个变量的一部分,或者变量后面加句点,再按TAB键就可以看到自动补全的威力。
-
配置环境变量
-
更改linux环境变量,输入命令查看环境变量:
echo $PATH
将python环境变量放在第一位:
PATH=/opt/python/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
-
永久生效path设置,添加到/etc/profile全局环境变量配置文件中
打开编辑文件 vim /etc/profile 最下方写入路径 PATH=/opt/python/bin/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
-
执行命令读取配置文件:
source /etc/profile
-
执行命令查看python路径:
which python3
-
2、安装配置virtualenv和virtualenvwrapper管理工具
在使用python开发的过程中,项目一多,管理起来就很麻烦,像不同的项目以来不同的版本库的问题,或者是不想当前的开发环境下充斥着各种各样又不需要的库,由此引发一些依赖报错问题。
这种情况下,就需要通过不同的工程使用不同的虚拟环境来保持开发环境以及宿主环境的清洁。
这时,我们就要使用virtualenv,它可以帮助我们管理不同的python环境,除了virtualenv还有一款工具叫anaconda这个工具里面内置了很多包,但是对于linux中生产环境的部署通常都使用virtualenv。
两者是有区别的:
- anaconda:anaconda里面自带python解释器,也可以通过anaconda的命令安装python解释器,由此来创建不同的虚拟环境
- virtualenv:virtualenv是依赖于python解释器的,也就是说他需要通过pip3 install命令来进行下载
- 两者的创建虚拟环境的命令使用方法和操作方法很像,具体命令操作可以看作者的另一篇博客:https://www.cnblogs.com/wylshkjj/p/13122349.html
安装命令
# 指定清华源下载pip的包,这种方式是临时换源,如果使用的是阿里云的服务器,是不需要换源的,里面是默认的阿里源,如果是虚拟机的话可以自行换源达到加快下载速度的目的,至于怎么换源,我想大家都懂的,我就不多说了
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple virtualenv
# 升级pip工具
pip3 install --upgrade pip
安装virtualenv:pip3 install virtualenv
注:虽然virtualenv很方便,但是他有一个大缺点
就是每次开启虚拟环境之前要去虚拟环境所在目录下的bin目录下source一下activate,所以这就需要我们记住每个虚拟环境所在的目录。但是人的记忆是会出错的,甚至由于时间过长直接就忘记了虚拟环境放在哪里了。所以我们需要使用virtualenvwrapper工具进行虚拟环境的管理,其实他就是统一管理虚拟环境的目录,并且省去了source的步骤。
安装virtualenvwrapper命令:pip3 install virtualenvwrapper
至于操作命令上面的博客链接里面写了基本的使用命令
配置virtualenvwrapper
把下面两行代码添加到 ~/.bashrc文件中
打开文件
vim ~/.bashrc
写入以下两行代码
RKON_HOME=~/Envs #设置virtualenv的统一管理目录
VIRTUALENVWRAPPER_VIRTUALENV_ARGS='--system-site-packages' # 添加virtualenvwrapper的参数,生成干净隔绝的环境
VIRTUALENVWRAPPER_PYTHON=/opt/python/bin/python3 # 指定python解释器
source /opt/python/bin/virtualenvwrapper.sh # 执行virtualenvwrapper安装脚本
读取文件,使得生效,此时已经可以使用virtalenvwrapper
source ~/.bashrc
3、下载所需包软件:
-
方式一:比较麻烦,一个一个手动下载
-
方式二:导包通过pip freeze 文件名,把所需下载的包打包成文件,传到服务器中直接执行下载:
pip3 freeze > requirements.txt
1.通过命令保证环境的一致性,导出当前python环境的包 pip3 freeze > requirements.txt 这将会创建一个 requirements.txt 文件,其中包含了当前环境中所有包及 各自的版本的简单列表。 可以使用 “pip list”在不产生requirements文件的情况下, 查看已安装包的列表。 2.上传至服务器后,在服务器下创建virtualenv,在venv中导入项目所需的模块依赖 pip3 install -r requirements.txt
4、安装uwsgi的web服务器
不配置uwsgi配置文件的基本使用
-
下载uwsgi
执行:pip3 install uwsgi
查看 uwsgi 版本:uwsgi --version
-
启动一个python的django项目,在项目根目录下执行命令
uwsgi --http :8000 --wsgi-file test.py
配置uwsgi配置文件
-
下载uwsgi
执行:pip3 install uwsgi
查看 uwsgi 版本:uwsgi --version
-
在项目根目录下创建uwsgi配置文件uwsgi.ini
[uwsgi] # 使用nginx连接时使用,Django程序所在服务器地址 socket=127.0.0.1:8000 # 直接做web服务器使用,Django程序所在服务器地址 # http=127.0.0.1:8000 # 项目中wsgi.py文件的目录,相对于项目目录 wsgi-file=luffycity/wsgi.py # 进程数 processes=4 # 线程数 threads=2 # uwsgi服务器的角色 master=True # 存放进程编号的文件 pidfile=uwsgi.pid # 日志文件,因为uwsgi可以脱离终端在后台运行,日志看不见。我们以前的runserver是依赖终端的 daemonize=uwsgi.log # 指定依赖的虚拟环境 virtualenv=/home/moluo/.virtualenvs/luffy
-
启动uwsgi服务器,必须在uwsgi.ini配置文件所在的目录中运行下面的命令
注意,在本地环境中必须先把runserver关闭
执行项目命令:
uwsgi --ini uwsgi.ini
-
关闭uwsgi(结束项目运行状态)
执行结束命令:
uwsgi --stop uwsgi.pid
关闭uwsgi:
结束项目:最笨但是最有效的方式直接执行 kill -9 进程ID号
或者强制删除杀死进程:sudo pkill uwsgi -9
**uWsgi热加载python程序 **
在启动命令后面加上参数
# 1.此命令应该在django项目目录下才可以,--module才能找到它的参数book_manage.wsgi uwsgi --http :8088 --module mysite.wsgi --py-autoreload=1# --py-autoreload=1 # 参数表示自动加载python配置 # 2.发布命令command= /home/venv/bin/uwsgi --uwsgi 0.0.0.0:8000 --chdir /opt/mysite --home=/home/venv --module mysite.wsgi # 此时修改django代码,uWSGI会自动加载django程序,页面生效
uWsgi配置文件基本参数
-
master = true
启动主进程,来管理其他进程,其它的uwsgi进程都是这个master进程的子进程,如果kill这个master进程,相当于重启所有的uwsgi进程。
-
chdir = /web/www/mysite
在app加载前切换到当前目录, 指定运行目录
-
module = mysite.wsgi
加载一个WSGI模块,这里加载mysite/wsgi.py这个模块
-
py-autoreload=1
监控python模块mtime来触发重载 (只在开发时使用)
-
lazy-apps=true
在每个worker而不是master中加载应用
-
socket = /test/myapp.sock
指定socket文件,也可以指定为127.0.0.1:9000,这样就会监听到网络套接字
-
processes = 2
启动2个工作进程,生成指定数目的worker/进程
-
buffer-size = 32768
设置用于uwsgi包解析的内部缓存区大小为64k。默认是4k。
-
daemonize = /var/log/myapp_uwsgi.log
使进程在后台运行,并将日志打到指定的日志文件或者udp服务器
-
log-maxsize = 5000000
设置最大日志文件大小
-
disable-logging = true
禁用请求日志记录
-
vacuum = true
当服务器退出的时候自动删除unix socket文件和pid文件。
-
listen = 120
设置socket的监听队列大小(默认:100)
-
pidfile = /var/run/uwsgi.pid
指定pid文件,直接写文件名就是在当前目录当前配置文件下同级目录下创建/指定pid文件。
-
enable-threads = true
允许用内嵌的语言启动线程。这将允许你在app程序中产生一个子线程
-
reload-mercy = 8
设置在平滑的重启(直到接收到的请求处理完才重启)一个工作子进程中,等待这个工作结束的最长秒数。这个配置会使在平滑地重启工作子进程中,如果工作进程结束时间超过了8秒就会被强行结束(忽略之前已经接收到的请求而直接结束)
-
max-requests = 5000
为每个工作进程设置请求数的上限。当一个工作进程处理的请求数达到这个值,那么该工作进程就会被回收重用(重启)。你可以使用这个选项来默默地对抗内存泄漏
-
limit-as = 256
通过使用POSIX/UNIX的setrlimit()函数来限制每个uWSGI进程的虚拟内存使用数。这个配置会限制uWSGI的进程占用虚拟内存不超过256M。如果虚拟内存已经达到256M,并继续申请虚拟内存则会使程序报内存错误,本次的http请求将返回500错误。
-
harakiri = 60
一个请求花费的时间超过了这个harakiri超时时间,那么这个请求都会被丢弃,并且当前处理这个请求的工作进程会被回收再利用(即重启)
5、对于Django的静态文件做收集
这种一般情况是drf项目部署时需要做的操作,django项目部署直接使用nginx指向static文件即可。
在settings中配置
STATIC_ROOT = os.path.join(BASE_DIR, 'static') # static是你所指向的存放静态文件的目录
然后在pycharm控制台(你自己的IDE控制台或者是cmd的项目目录下执行文件收集命令)
python manage.py collectstatic
六、进程管理工具
Supervisor 是一个用 Python 写的进程管理工具,可以很方便的用来在 UNIX-like 系统(不支持 Windows)下启动、重启(自动重启程序)、关闭进程(不仅仅是 Python 进程)
Supervisor 是一个 C/S 模型的程序,supervisord 是 server 端,supervisorctl 是 client 端
-
安装epel release
yum install epel-release
-
安装supervisor
yum install -y supervisor
-
配置项与检查命令
systemctl enable supervisord # 开机自启动
systemctl start supervisord # 启动supervisord服务systemctl status supervisord # 查看supervisord服务状态
ps -ef|grep supervisord # 查看是否存在supervisord进程 -
基本使用命令
可以通过supervisorctl -c /etc/supervisord.conf的服务台来进行服务任务管理
stop all # 停止所有
start drawer # 任务名
参数形式:
supervisorctl -c /etc/supervisord.conf stop all
supervisorctl -c /etc/supervisord.conf start wyl_drawer -
配置文件配置项
vim /etc/supervisord.conf 编辑配置进程守护
执行:shift+g 命令;跳转到文件最后一行,添加配置命令
[program:tracer]command=/root/Envs/tracer/bin/uwsgi /opt/tracer/uwsgi.inistopasgroup=truekillasgroup=true[program:luffy]command=/root/Envs/luffy/bin/uwsgi /opt/luffy/luffyapi/uwsgi.inistopasgroup=truekillasgroup=true
- stopasgroup=true # 默认为false,进程被杀死时,是否向进程组发送stop信号,包括子进程
- killasgroup=true # 默认为false,向进程组发送kill信号,包括子进程
-
另外有一个坑需要注意:如果修改了 /etc/supervisord.conf ,需要执行 supervisorctl reload 来重新加载配置文件,否则不会生效。。。