1.环境信息
-
服务器为centos7
2.安装supervisor
-
yum install supervisor
-
友情提示:如果安装失败按照以下三步走,然后再次安装
第一步:直接更换镜像源,别看网上那些没用的(如果你想重蹈覆辙的话)
第二步:安装EPEL源
yum -y install epel-release第三步:更新yum源
yum --skip-broken update
yum clean all
yum -y upgrade
3.更换镜像源
-
如果你上一步安装没有问题,那就跳过该步骤
1.进入到yum的源目录下
cd /etc/yum.repos.d/
2.将原来的CentOS-Base.repo进行备份
mv CentOS-Base.repo CentOS-Base.repo_back
3.下载阿里源
wget http://mirrors.aliyun.com/repo/Centos-7.repo
4.改变名字
mv Centos-7.repo CentOS-Base.repo
5.更新
yum --skip-broken update
6. 清除缓存
yum clean all
7. 升级
yum -y upgrade
8.生成缓存
yum makecache
4. 查看supervisor配置文件
-
vi /etc/supervisord.conf
; Sample supervisor config file. [unix_http_server] # socket通讯相关配置 ... ;[inet_http_server] # Web Server配置,如果想使用web界面管理的话,可以去掉前面的;号。port写你服务器的ip,端口可以改称自己喜欢的,默认9001, 建议打开用户名密码验证, 生产环境不建议打开web界面管理。 ... [supervisord] # 服务端程序 ... [rpcinterface:supervisor] # 这个选项是给XML_RPC用的,当然你如果想使用supervisord或者web server 这个选项必须要开启的 ... [supervisorctl] # client端程序 ... ;[program:theprogramname] # 要管理的子进程 ... ;[eventlistener:theeventlistenername] # 和program的地位是一样的,也是suopervisor启动的子进程,不过它干的活是订阅supervisord发送的event。他的名字就叫listener了。我们可以在listener里面做一系列处理,比如报警等等 ... ;[group:thegroupname] # 给programs分组,划分到组里面的program。我们就不用一个一个去操作了我们可以对组名进行统一的操作。 注意:program被划分到组里面之后,就相当于原来的配置从supervisor的配置文件里消失了。。。supervisor只会对组进行管理,而不再会对组里面的单个program进行管理了 ;programs=progname1,progname2 # 组成员,用逗号分开 ;priority=999 # 优先级,相对于组和组之间说的 ... [include] files = supervisord.d/*.ini
- 我们只需要关心最后的
include
,此处告诉我们,手动创建的环境管理配置文件应该放在/etc/supervisord.d
目录下,并且文件名必须以.ini
结尾。
- 我们只需要关心最后的
5. 新建supervisor配置文件
-
最好一个服务启动命令新建一个配置文件
1. 新建
django
服务启动配置vi /etc/supervisord.d/django.ini
[program:django] ; 使用daphne启动 ; command=/usr/local/python3/bin/daphne -b 0.0.0.0 -p 8888 ECloudBM.asgi:application ; 不使用daphne启动 command=/root/.pyenv/versions/qingyun/bin/python3 manage.py runserver 0.0.0.0:8888 ; 项目路径 directory=/root/projects/ECloud-BM ; 启动优先级(越小越优先) priority=9999 ; 启动 5 秒后没有异常退出,就当作已经正常启动了 startsecs = 5 ; 程序异常退出后自动重启 autorestart = true ; 启动失败自动重试次数,默认是 3 startretries = 3 ; 标准输出日志 stdout_logfile = /var/log/supervisor.log
2.启动
supervisord -c /etc/supervisord.conf 或者 systemctl status supervisord.service
- 查看状态
supervisorctl status django
- 停止
supervisorctl stop django
- 启动
supervisorctl start django
- 重启
supervisorctl restart django
3. 新建
celery-worker
异步任务启动配置文件vi /etc/supervisord.d/celery_worker.ini
[program:celery_worker] ; 启动项目时运行的命令 command=/root/.pyenv/versions/qingyun/bin/celery -A ECloudBM worker -l info ; 项目绝对路径 directory=/root/projects/Ecloud-BM ; 是否自动启动 autostart=true ; 程序意外退出是否自动重启 autorestart=true ; 自动重启间隔 startsecs=10 ; 杀进程的信号 stopsignal=QUIT ; 向进程发出stopsignal后等待OS向supervisord返回SIGCHILD 的时间。若超时则supervisord将使用SIGKILL杀进程 stopwaitsecs=60 ; 子进程的stdout的日志路径 输出日志文件 stdout_logfile= /var/log/supervisor/celery_worker.log ; 错误日志文件 当redirect_stderr=true。这个就不用 stderr_logfile= /var/log/supervisor/celery_worker_error.log ; 优先级 priority=1000
4. 新建
celery-beat
定时任务启动配置文件vi /etc/supervisord.d/celery_beat.ini
[program:celery_beat] ; 启动项目时运行的命令 command=/root/.pyenv/versions/qingyun/bin/celery -A ECloudBM beat -l info ; 项目绝对路径 directory=/root/projects/Ecloud-BM ; 是否自动启动 autostart=true ; 程序意外退出是否自动重启 autorestart=true ; 自动重启间隔 startsecs=10 ; 杀进程的信号 stopsignal=QUIT ; 向进程发出stopsignal后等待OS向supervisord返回SIGCHILD 的时间。若超时则supervisord将使用SIGKILL杀进程 stopwaitsecs=60 ; 子进程的stdout的日志路径 输出日志文件 stdout_logfile= /var/log/supervisor/celery_beat.log ; 错误日志文件 当redirect_stderr=true。这个就不用 stderr_logfile= /var/log/supervisor/celery_beat_error.log ; 优先级 priority=1001
6. 新建
celery-flower
启动配置文件(用于查看异步任务资源占用率以及执行情况)[program:flower] ; 启动命令 command=/root/.pyenv/versions/qingyun/bin/flower -A ECloudBM --address=10.10.8.179 --port=5555 --basic_auth=admin:password@ ; 项目目录 directory=/root/projects/Ecloud-BM ; 启动优先级 priority=1002 ; the relative start priority (default 999) ; 启动 5 秒后没有异常退出,就当作已经正常启动了 startsecs = 5 ; 程序异常退出后自动重启 autorestart = true ; 启动失败自动重试次数,默认是 3 startretries = 3 ; 错误日志 stdout_logfile = /var/log/supervisor/celery_flower.log ; 标准输出日志 stderr_logfile= /var/log/supervisor/celery_flower_error.log
5. 新建
uwsgi
启动配置文件(后面结合nginx进行并发处理,注意,此处如果使用uwsgi启动django项目,则去掉django.ini这个启动配置)uwsgi.ini
(建议放在项目根目录下,与manage.py同级别),内容如下:
[uwsgi] ; 使用nginx连接时使用 ; socket = 10.10.8.179:10000 ; 直接做web服务器使用,指定要监听的ip和端口号,即我们运行项目时的ip和端口 http = 10.10.8.179:9000 ; 项目目录 chdir = /root/projects/Ecloud-BM ; 项目中的wsgi.py文件的目录,相对于项目目 = Ecloud-BM.wsgi module = ECloudBM.wsgi:application ; 静态文件映射,测试uwsgi配置时为了能够访问到静态资源,所以加上这个配置。在使用nginx时,需要注销掉这个配置,改用nginx来代理静态资源访问 ; 可使用 python manage.py collectstatic static-map=/static=/root/projects/Ecloud-BM/static ; 指定启动的工作进程数 processes = 4 ; 指定每个进程中的线程数 threads = 2 ; 指定在工作进程中存在一个主进程 master = True ; 服务停止时自动移除unix Socket和pid文件 vacuum = True ; 保存启动之后主进程的进程号 pidfile = uwsgi.pid ; 设置uwsgi后台运行,运行信息保存在uwsgi.log(使用supervisor托管时此处一定要注释调) ; daemonize = uwsgi.log ; 单个日志的大小 buffer-size=32768 ; 设置每个工作进程处理请求的上限,达到上限时,将回收(重启)该进程。可以预防内存泄漏 max-requests=5000 ; 虚拟环境所在目录 home=/root/.pyenv/versions/qingyun/ PYTHONHOME = /root/.pyenv/versions/qingyun/bin/
- 使用supervisor管理
uwsgi
服务,内容如下:
[program:uwsgi] ; 启动项目时运行的命令 command=/root/.pyenv/versions/qingyun/bin/uwsgi uwsgi.ini ; 项目绝对路径 directory=/root/projects/Ecloud-BM ; 是否自动启动 autostart=true ; 程序意外退出是否自动重启 autorestart=true ; 自动重启间隔 startsecs=10 ; 杀进程的信号 stopsignal=QUIT ; 向进程发出stopsignal后等待OS向supervisord返回SIGCHILD 的时间。若超时则supervisord将使用SIGKILL杀进程 stopwaitsecs=60 ; 子进程的stdout的日志路径 输出日志文件 stdout_logfile= /var/log/supervisor/uwsgi.log ; 错误日志文件 当redirect_stderr=true。这个就不用 stderr_logfile= /var/log/supervisor/uwsgi_error.log ; 优先级 priority=1003
6. 新建
asgi
启动配置文件(用于channels通信)- 如果
/run/daphne
该路径不存在则需要手动创建
[program:asgi] ; channels通信地址 socket=tcp://10.10.8.179:8889 ; 项目目录 directory=/root/projects/Ecloud-BM/EcloudBM ; 启动命令(我使用此命令启动报错,网上也没找到解决办法,如果你也一样,可以使用下面命令启动) command=/root/.pyenv/versions/qingyun/bin/daphne -u /run/daphne/daphne%(process_num)d.sock --fd 0 --access-log - --proxy-headers ECloudBM.asgi:application ; command=/root/.pyenv/versions/qingyun/bin/daphne -b 10.10.8.179 -p 8889 --proxy-headers ECloudBM.asgi:application ; 进程数 numprocs=4 ; 进程名 process_name=asgi%(process_num)d ; 自动启动 autostart=true ; 自动重启 autorestart=true ; 错误日志 stdout_logfile=/var/log/supervisor/asgi.log ; 标准输出日志 stderr_logfile=/var/log/supervisor/asgi_error.log ; 日志保存上限 stdout_logfile_maxbytes = 20MB
6.使用supervisorctl进行管理
-
1.查看所有子服务
(qingyun) [root@localhost supervisord.d]# supervisorctl status asgi:asgi0 STARTING asgi:asgi1 STARTING asgi:asgi2 STARTING asgi:asgi3 STARTING celery_beat STARTING celery_worker STARTING flower STARTING uwsgi STARTING supervisor>
- 如果使用
supervisorctl
管理命令报以下错误:
(qingyun) [root@localhost ~]# supervisorctl unix:///var/run/supervisor/supervisor.sock no such file
- 请执行如下代码
(qingyun) [root@www Ecloud-BM]# supervisorctl asgi:asgi0 RUNNING pid 21529, uptime 0:00:01 asgi:asgi1 STARTING asgi:asgi2 RUNNING pid 21492, uptime 0:00:03 asgi:asgi3 RUNNING pid 21505, uptime 0:00:01 celery_beat RUNNING pid 12319, uptime 0:28:09 celery_worker RUNNING pid 12334, uptime 0:28:07 flower RUNNING pid 25468, uptime 1:23:50 uwsgi RUNNING pid 25469, uptime 1:23:50 supervisor>
- 如果使用
-
2.查看可用命令
supervisor> supervisor> help default commands (type help <topic>): ===================================== add exit open reload restart start tail avail fg pid remove shutdown status update clear maintail quit reread signal stop version supervisor>
-
3.示例如下
- 查看单个服务错误日志
supervisor> help tail # 查看命令使用方式 tail [-f] <name> [stdout|stderr] (default stdout) Ex: tail -f <name> Continuous tail of named process stdout Ctrl-C to exit. tail -100 <name> last 100 *bytes* of process stdout tail <name> stderr last 1600 *bytes* of process stderr supervisor> supervisor> supervisor> tail -200 django stderr Listen failure: Couldn't listen on 0.0.0.0:8888: [Errno 98] Address already in use. supervisor>
- 停止所有服务
supervisor> stop all asgi:asgi1: stopped asgi:asgi0: stopped asgi:asgi3: stopped celery_beat: stopped asgi:asgi2: stopped uwsgi: stopped celery_worker: stopped flower: stopped supervisor>
- 启动所有服务
supervisor> start all asgi:asgi1: started asgi:asgi0: started asgi:asgi3: started asgi:asgi2: started flower: started celery_worker: started celery_beat: started uwsgi: started supervisor>
- 查看服务状态
supervisor> status asgi:asgi0 STARTING asgi:asgi1 RUNNING pid 25414, uptime 0:00:03 asgi:asgi2 RUNNING pid 25417, uptime 0:00:02 asgi:asgi3 RUNNING pid 25416, uptime 0:00:02 celery_beat RUNNING pid 21789, uptime 0:12:03 celery_worker RUNNING pid 21788, uptime 0:12:03 flower RUNNING pid 21790, uptime 0:12:03 uwsgi RUNNING pid 21791, uptime 0:12:03 supervisor>
- 退出
supervisor> quit
7.使用web界面管理服务
-
1.修改配置文件
vi /etc/supervisord.conf
-
2.将以下内容前面的;去掉
[inet_http_server] ; inet (TCP) server disabled by default port=10.10.8.179:9001 ; ip(你服务器的ip地址) + 端口号(根据你的爱好指定) username=user ; web端登录用户名 password=password ; web端登录密码
-
3.重载supervisorctl配置
supervisorctl reload
8.配置开机自启
-
1.修改配置文件
vi /lib/systemd/system/supervisord.service
-
2.将以下内容加入到Service下
ExecStop=/usr/bin/supervisord shutdown ExecReload=/usr/bin/supervisord reload killMode=process Restart=on-failure RestartSec=42s
-
3.执行开机自启命令
systemctl enable supervisord
9.项目部署(nginx + vue + uwsgi)
-
项目结构
-
目录说明:
frontend目录(需要自己创建名称随意,也可以不放在项目内)将前端vue打包生成的dist直接拷贝进来就(nginx配置时写绝对路径到该dist目录)
将settings.py配置文件DEBUG改为False
-
1.安装nginx
yum install nginx
-
2.新建项目配置文件(重点)
- 说在前面:此时要通过nginx进行部署,所以一定要修改uwsgi代理的连接方式为socket
# 这是nginx原生配置文件所包含配置信息的目录(它建议将项目配置文件放在此处,而不是在原生配置文件上进行改动) cd /etc/nginx/conf.d/ # 文件名随意, 但必须以.conf结尾 vi xxx.conf
upstream qingyun { server 10.10.8.179:10000; # 与uwsgi服务端口保持一致 } upstream channels-backend { server 10.10.8.179:8889; # 与asgi服务端口保持一致 } # 将80端口转发到vue,然后请求接口以api|base|vserver|setup开头则转发到10000端口的uwsgi服务上,将请求接口以ws开头的websocket连接转发到asgi服务上 server { listen 80; server_name 10.10.8.179; # 你的访问地址, 有域名的话直接写域名 proxy_set_header Cookie $http_cookie; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-real-ip $remote_addr; location / { try_files $uri $uri/ /index.html; # 此处是重点(指向dist目录下的index.html),如果不配置会自动转发到nginx默认主页 root /root/projects/Ecloud-BM/frontend/dist; # 这是前端静态文件目录路径 } location ~(api|base|vserver|setup)/ { # 此处则是前台项目转发给后端的请求接口(即你的项目url可能的开头,以此来进行匹配) uwsgi_pass qingyun; # uwsgi(通用网关接口)转发django请求 include /etc/nginx/uwsgi_params; } location ~(ws)/ { # # 此处则是前台项目转发给后端websocket的请求接口(routing可能的开头,以此来进行匹配) try_files $uri @proxy_to_app; # channels通信转发,需要用到asgi(异步网关协议接口) } location @proxy_to_app { proxy_pass http://channels-backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $server_name; } }
说明:
项目总urls.py示例如下(可能的开头有 base vserver api setup)
对应配置如下:location ~(api|base|vserver|setup)/ { ... }
项目总routing.py示例如下(可能的开头有 ws)
对应配置如下:location ~(ws)/ { ... }
- 说在前面:此时要通过nginx进行部署,所以一定要修改uwsgi代理的连接方式为socket
-
3. 检查配置文件是否正确
-
4. 重新加载配置文件
-
5. 配置nginx开机自启
-
1.在系统服务目录里创建nginx.service文件
vi /usr/lib/systemd/system/nginx.service
-
2.在 [Service] 下加入以下内容
ExecStart=/usr/sbin/nginx ExecReload=/usr/sbin/nginx -s reload ExecStop=/usr/sbin/nginx -s quit
-
3.设置开机自启动
systemctl enable nginx.service
-
10.访问
11. 使用nginx部署项目中遇到的问题
-
1. failed (13: Permission denied)
-
可能性一:
解决: cd /etc/nginx/ # 进入nginx目录 vim nginx.conf # 编辑nginx.conf 将user xxxx; 修改为 user root; # 命令重新加载配置 nginx -s reload
-
可能性二:
查看SELinux状态: 1、/usr/sbin/sestatus -v ##如果SELinux status参数为enabled即为开启状态 SELinux status: enabled 2、getenforce ##也可以用这个命令检查 关闭SELinux: 1、临时关闭(不用重启机器): setenforce 0 ##设置SELinux 成为permissive模式 ##setenforce 1 设置SELinux 成为enforcing模式 2、修改配置文件需要重启机器: 修改/etc/selinux/config 文件 将SELINUX=enforcing改为SELINUX=disabled 重启机器即可
-
-
2. 配置了80端口转发,却依然指向默认地址,显示Welcome to nginx界面
# location没有写index index.html index.htm;导致项目无法实现重定向 location / { ... index index.html index.htm; } # 命令重新加载配置 nginx -s reload