项目部署流程
项目部署
http://blog.51cto.com/ljmict
项目部署流程:
买服务器, 服务器租用
选择操作系统的版本,安装系统
-
在开发环境中把项目需要的pip包写到一个文件 pip freeze . requirements
.txt
把项目上传到服务器
-
部署项目, 安装需要的环境
- pyhton3解释器
- 虚拟环境
- 数据库
- nginx, uwsgi
服务器
nginx
mysql
redis
uwsgi
celery
docker
网站流量参考
网站流量度量
pv:独立访客
ip:独立ip
uv:独立访客
并发:
每秒响应的最大连接数
web服务器每秒能够接受的用户连接数
web服务器每秒能接受最大用户连接数
web服务器单位时间能够处理的最大连接数
django前后端分离项目部署
介绍
技术栈 nginx+uwsgi+celery+supervisor
本教程 实现了负载均衡、反向代理、动静分离,还实现了根据客户端设备user-agent进行转发,也就是移动端和pc端访问的页面不一样。
前期准备
1. 项目部署逻辑图
2. 环境准备
服务器:6台vm
操作系统:centos7
lb、www、wap:安装nginx
uwsgi1、uwsgi2:安装nfs-utils、python3解释器、virtualenv
nfs:安装nfs
mrcs:安装mysql、redis、virtualenv
centos安装nginx
镜像下载地址 http://isoredirect.centos.org/centos/7/isos/x86_64/centos-7-x86_64-dvd-1804.iso
centos 服务器部署遇到的常见问题
centos不能联网
进入目录
cd /etc/sysconfig/network-scripts/
输入ls查看文件列表, 找到网卡配置文件,如下图,我虚拟机的网卡名称为ens33
编辑
vi
按i进入编辑模式, 编辑ifcfg-ens33文件的最后一行,将onboot=no改为onboot=yes,
按esc退出编辑模式, 输入:wq保存退出
重启network:
$ server network restart
pingi下百度能不能ping通
$ ping www.baidu.com
如果能ping通, 说明网络已经可以连接了
centos没有ifconfig命令的解决办法
全新安装centos的时候,运行ifconfig准备查看服务器ip的时候, 发现会报错
-bash:command not found
网上搜了下, 原因可能是最小化安装centos等linux发行版的时候会默认不安装ifconfig等命令
解决的办法: yum安装ifconfig这个包
首先搜索下
$ yum search ifconfig
发现ifconfig所属的命令包是net-tools.x86_64
安装
$ yum install net-tools.x86_64
中途会询问“is this os [y/d/n]”,按y回车,complete完成安装。
安装完之后就可以输入ifconfig查看网卡信息了
centos修改终端输出语言
远程连接centos服务器的时候, 发现有些字符会乱码
在网上搜了下, 发现是默认语言设置的问题. 输入echo $lang
和locale
查询, 结果如下
修改默认语言, 编辑配置文件
$ vi /etc/locale.conf
添加下面字段, wq保存
lang=”zh_cn.utf-8”
应用配置文件, 使其生效
$ source /etc/locale.conf
问题解决
centos编译安装nginx
1. 环境准备
# 更换yum源,centos默认源是国外的网站,下载会比较慢 curl -o /etc/yum.repos.d/centos-base.repo http://mirrors.aliyun.com/repo/centos-7.repo yum makecache # 安装编译环境,如果安装过了,就不需要再安装了 yum -y install gcc*
2. 安装pcre库,如果不安装pcre库,nginx无法使用rewrite模块,在编译安装过程也会报错
# 查询pcre库是否安装 rpm -qa|grep pcre yum -y install pcre pcre-devel # 安装完之后查询一下是否安装成功,如果能够看到pcre和pcre-devel包就可以了 rpm -qa|grep pcre
3. 安装nginx
# 创建一个software/目录用来放软件包 mkdir -p /opt/software # 创建安装目录 mkdir -p /application/nginx-1.14.0 # 下载nginx安装包 cd /opt/software wget -q http://nginx.org/download/nginx-1.14.0.tar.gz # 创建一个nginx用户 useradd nginx -s /sbin/nologin -m //创建一个nginx用户 # 解压 tar xvf nginx-1.14.0.tar.gz cd nginx-1.14.0 # 安装 ./configure --user=nginx --group=nginx --prefix=/application/nginx-1.14.0 --with-http_stub_status_module --with-http_ssl_module # 如果安装报./configure: error: ssl modules require the openssl library 需要安装openssl-devel,安装完之后再执行一下上一条命令 yum -y install openssl-devel make && make install # 创建软链接是为了以后如果要升级,应用程序中如果有引用nginx路径,不需要做任何更改,访问的还是原来的路径/application/nginx ln -s /application/nginx-1.14.0/ /application/nginx # 查看链接状态 ls -l /application/nginx
注意:编译安装nginx软件时,还可以使用./configure --help
查看相关参数帮助
4. 检查安装结果
# 启动nginx服务 /application/nginx/sbin/nginx netstat -lntup|grep 80
5. 在浏览器里面输入nginx服务器ip地址
发现并没有成功,原因是被centos防火墙拦截了, 这个时候, 我们需要关闭防火墙
6. 关闭防火墙
centos7版本后防火墙默认使用firewalld,因此在centos7中关闭防火墙使用以下命令,
# 临时关闭 $ systemctl stop firewalld # 禁止开机启动 $ systemctl disable firewalld removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service. removed symlink /etc/systemd/system/dbus-org.fedoraproject.firewalld1.service.123456
当然,如果安装了iptables-service,也可以使用下面的命令,
$ yum install -y iptables-services # 关闭防火墙 $ service iptables stop redirecting to /bin/systemctl stop iptables.service # 检查防火墙状态 $ service iptables status redirecting to /bin/systemctl status iptables.service iptables.service - ipv4 firewall with iptables loaded: loaded (/usr/lib/systemd/system/iptables.service; disabled; vendor preset: disabled) active: inactive (dead)
重新访问就能成功访问了
centos 安装nfs服务
0.准备工作
在之前安装好的服务器克隆一个副本
先把centos关机, 然后如图所示, 创建完整的克隆, 克隆一个副本
安装nfs服务,需要安装nfs-utils和rpcbind,nfs的rpc服务,在centos5.x下名称为portmap,在centos6.x下名称为rcpbind。
1.查询nfs服务和rpc服务是否安装
[root@localhost ~]# rpm -qa|grep nfs [root@localhost ~]# rpm -qa|grep rpcbind
2.使用yum安装nfs和rpcbind
[root@localhost ~]# yum install -y nfs-utils
3.启动nfs服务,在启动nfs服务之前,一定要先启动rpcbind,然后再启动nfs
[root@localhost ~]# service rpcbind start redirecting to /bin/systemctl start rpcbind.service
查看rpc信息
[root@localhost ~]# rpcinfo -p localhost program vers proto port service 100000 4 tcp 111 portmapper 100000 3 tcp 111 portmapper 100000 2 tcp 111 portmapper 100000 4 udp 111 portmapper 100000 3 udp 111 portmapper 100000 2 udp 111 portmapper
[root@localhost ~]# service nfs start starting nfs services: [ ok ] starting nfs quotas: [ ok ] starting nfs mountd: [ ok ] starting nfs daemon: [ ok ] starting rpc idmapd: [ ok ]
启动nfs服务以后,再查看rpcinfo信息。
[root@localhost ~]# rpcinfo -p program vers proto port service 100000 4 tcp 111 portmapper 100000 3 tcp 111 portmapper 100000 2 tcp 111 portmapper 100000 4 udp 111 portmapper 100000 3 udp 111 portmapper 100000 2 udp 111 portmapper 100011 1 udp 875 rquotad 100011 2 udp 875 rquotad 100011 1 tcp 875 rquotad 100011 2 tcp 875 rquotad 100005 1 udp 35606 mountd 100005 1 tcp 38238 mountd 100005 2 udp 33761 mountd 100005 2 tcp 41083 mountd 100005 3 udp 47608 mountd 100005 3 tcp 35056 mountd 100003 2 tcp 2049 nfs 100003 3 tcp 2049 nfs 100003 4 tcp 2049 nfs 100227 2 tcp 2049 nfs_acl 100227 3 tcp 2049 nfs_acl 100003 2 udp 2049 nfs 100003 3 udp 2049 nfs 100003 4 udp 2049 nfs 100227 2 udp 2049 nfs_acl 100227 3 udp 2049 nfs_acl 100021 1 udp 34627 nlockmgr 100021 3 udp 34627 nlockmgr 100021 4 udp 34627 nlockmgr 100021 1 tcp 46375 nlockmgr 100021 3 tcp 46375 nlockmgr 100021 4 tcp 46375 nlockmgr
4.配置共享目录/share,允许192.168.25.*访问
[root@localhost ~]# mkdir /share //创建共享目录 [root@localhost ~]# ll -d /share/ //查看目录信息 drwxr-xr-x. 2 root root 4096 dec 30 13:55 /share/ [root@localhost ~]# chown -r nfsnobody:nfsnobody /share/ //更改目录所属用户和所属组 [root@localhost ~]# ll -d /share/ drwxr-xr-x. 2 nfsnobody nfsnobody 4096 dec 30 13:55 /share/ [root@localhost ~]# vi /etc/exports /share 192.168.25.*(rw,sync) # 添加此字段 wq保存 ///share 192.168.25.* 本机ip网段
5.查看nfs共享目录信息
[root@localhost ~]# showmount -e 192.168.25.231 //本机ip export list for 192.168.25.231: /share 192.168.25.*
6.nfs客户端挂载共享目录/share
[root@localhost ~]# mount -t nfs 192.168.25.231:/share /mnt [root@localhost ~]# df -h 文件系统 容量 已用 可用 已用% 挂载点 /dev/mapper/centos-root 17g 1.8g 16g 11% / devtmpfs 476m 0 476m 0% /dev tmpfs 488m 0 488m 0% /dev/shm tmpfs 488m 7.9m 480m 2% /run tmpfs 488m 0 488m 0% /sys/fs/cgroup /dev/sda1 1014m 130m 885m 13% /boot tmpfs 98m 0 98m 0% /run/user/0 192.168.25.231:/share 17g 1.8g 16g 11% /mnt
7.nfs客户端排错思路
试客户端与服务端网络是否可否,如在客户端使用ping ip地址
在服务端自己挂载看看是否能够正常挂载
检查服务端防火墙规则,初学者可以选择直接关闭防火墙
8.管理nfs共享目录
exportfs命令可以导出nfs服务器上的共享目录、显示共享目录,或者不导出共享目录。
命令语法:
exportfs [选项][目录]
选项 | 含义 |
---|---|
-a | 导出或不导出所有的目录 |
-v | 显示导出列表的同时,也显示导出选项的列表 |
-u | 不导出指定的目录。当和-a选项一起时,不导出所有的目录 |
-f | 指定一个新的导出文件,而不是/etc/exports文件 |
-r | 重新导出所有的目录 |
-o选项> | 指定导出选项列表 |
查看nfs共享目录信息
showmount [选项][nfs服务器]
选项 | 含义 |
---|---|
-a | 同时显示客户端的主机名或ip地址以及所挂载的目录 |
-e | 显示nfs服务器的导出列表 |
-d | 只显示已经被挂载的nfs共享目录信息 |
9.nfs配置文件权限参数说明
参数名称 | 参数用途 |
---|---|
rw | 共享目录具有读写权限 |
ro | 共享目录具有只读权限 |
sync | 请求或写入数据时,数据同步写入到nfs server硬盘中。数据安全不会丢,缺点,性能比不启用该参数要差。 |
async | 请求或写入数据时,先返回请求,再将数据写入到内存缓存和硬盘中,即异步写入数据。此参数可以提升nfs性能,但是会降低数据的安全。因此,一般情况下建议不用,如果nfs处于瓶颈状态,并且允许数据丢失的话可以打开此参数提升nfs性能。写入时数据会先到内存缓冲区,等硬盘有空档再写入磁盘,这样可以提升写入效率!风险为若服务器宕机或不正常关机,会损失缓冲区未写入硬盘的数据(解决办法:服务器主板电池或加ups不间断电源)! |
root_squash | root用户的所有请求映射成如nfsnobody(匿名)用户一样的权限 |
no_root_squash | 关闭root_squash |
all_squash | 映射所有的uid和gid为匿名用户 |
no_all_squash | 保留共享文件的uid和gid(默认) |
anonuid | 指定nfs服务器/etc/passwd文件中匿名用户的uid |
anongid | 指定nfs服务器/etc/passwd文件中匿名用户的gid |
secure | nfs通过1024以下的安全tcp/ip端口发送 |
insecure | nfs通过1024以上的端口发送 |
wdelay | 如果多个用户要写入nfs目录,则归组写入(默认) |
no_wdelay | 如果多个用户要写入nfs目录,则立即写入,当使用async时,不需要设置 |
subtree_check | 如果共享/usr/bin之类的子目录时,强制nfs检查父目录的权限 |
no_subtree_check | 和subtree_check相对,不检查父目录权限 |
hide | 在nfs共享目录中不共享其子目录 |
nohide | 共享nfs目录的子目录 |
mp | 如果它已经成功挂载,那么使得它只导出一个目录 |
fsid | nfs需要能够识别每个它导出的文件系统。通常情况下它会为文件系统使用一个uuid,或者该设备保持文件系统的设备号 |
负载均衡和反向代理服务器配置
在lb(负载均衡)服务器上面配置
(就是第一个创建的那个服务器)
编辑nginx.conf
vi /application/nginx/conf/nginx.conf
文件更改为
如果要写注释, 中文乱码的话, 可以临时配为utf8编码. 在vim的命令模式下输入
:set encoding=utf8
, 就可以输入中文了建议下载下来使用vscode装nginx插件进行编辑会比较方便
# 配置文件内容 worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; # 静态请求服务器池 upstream static_pools { server 192.168.25.150:80 weight=1; } # 动态请求服务器池 upstream dynamic_pool { server 192.168.25.151:8001 weight=1; server 192.168.25.152:8001 weight=1; } # 移动端服务器池 upstream mobile_pools { server 192.168.25.160:80 weight=1; } # 后端api服务器 server { listen 8080; server_name api.meiduo.site; location / { include uwsgi_params; uwsgi_pass dynamic_pool; } access_log off; error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } # 提供前端页面访问 server { listen 80; server_name www.meiduo.site; # 如果访问url为:http://www.meiduo.site/xadmin就交给meiduo池 location /xadmin{ include uwsgi_params; uwsgi_pass dynamic_pool; } # 如果请求url为:http://www.meiduo.site/cheditor就交给meiduo池 location /cheditor{ include uwsgi_params; uwsgi_pass dynamic_pool; } # 请求uri以/开头就交给这个location区块进行处理,例如:/static location / { # 如果客户端设备user_agent为iphone,就交给iphone_pools池 if ($http_user_agent ~* "iphone") { proxy_pass http://mobile_pools; } # pc端访问就交给static_pools池处理 proxy_pass http://static_pools; } access_log off; } }
启动nginx服务
/application/nginx/sbin/nginx
nfs 服务器配置
mkdir /project # 配置挂载目录 cat /etc/exports # 配置内容 /share 192.168.25.*(rw,sync) # 重启nfs服务 systemctl restart rpcbind systemctl restart nfs
配置完成之后把项目上传到/project目录里面
配置uwsgi和uwsgi2服务器
在uwsgi1和uwsig2服务器上操作:
# 创建虚拟环境 mkvirtualenv -p python3 meiduo # 切换到meiduo虚拟环境 workon mediuo # 安装uwsgi包 pip install uwsgi mkdir /project # 挂载nfs服务器/project目录到uwsgi服务器的/project mount -t nfs 172.16.1.14:/project /project # 查看当前服务器挂载情况 df -h # 输出 文件系统 容量 已用 可用 已用% 挂载点 /dev/mapper/centos-root 36g 2.4g 33g 7% / devtmpfs 226m 0 226m 0% /dev tmpfs 237m 0 237m 0% /dev/shm tmpfs 237m 8.8m 228m 4% /run tmpfs 237m 0 237m 0% /sys/fs/cgroup /dev/sda1 1014m 143m 872m 15% /boot tmpfs 48m 0 48m 0% /run/user/0 172.16.1.14:/project 17g 1.8g 16g 11% /project # 安装项目中用到的pip包 cd /project/meiduo/meiduo_mall pip install -r requirements.txt # 这个文件是在开发环境中通过pip freeze >requirements.txt生成的 cd /root # 创建uwsgi.ini文件 touch uwsgi.ini
uwsgi1配置
[uwsgi] #使用nginx连接时使用,django程序所在服务器地址 socket=172.16.1.11:8001 #直接做web服务器使用,django程序所在服务器地址 #http=172.16.1.11:8000 #项目目录 chdir=/project/meiduo/meiduo_mall #项目中wsgi.py文件的目录,相对于项目目录 wsgi-file=meiduo_mall/wsgi.py # 进程数 processes=4 # 线程数 threads=2 # uwsgi服务器的角色 master=true # 存放进程编号的文件 pidfile=uwsgi.pid # 日志文件,因为uwsgi可以脱离终端在后台运行,日志看不见。我们以前的runserver是依赖终端的 daemonize=uwsgi.log # 指定依赖的虚拟环境 virtualenv=/root/.virtualenvs/meiduo
uwsgi2配置
[uwsgi] #使用nginx连接时使用,django程序所在服务器地址 socket=172.16.1.12:8001 #直接做web服务器使用,django程序所在服务器地址 #http=172.16.1.12:8000 #项目目录 chdir=/project/meiduo/meiduo_mall #项目中wsgi.py文件的目录,相对于项目目录 wsgi-file=meiduo_mall/wsgi.py # 进程数 processes=4 # 线程数 threads=2 # uwsgi服务器的角色 master=true # 存放进程编号的文件 pidfile=uwsgi.pid # 日志文件,因为uwsgi可以脱离终端在后台运行,日志看不见。我们以前的runserver是依赖终端的 daemonize=uwsgi.log # 指定依赖的虚拟环境 virtualenv=/root/.virtualenvs/meiduo
uwsgi启动命令
# 启动uwsgi服务器 uwsgi --ini uwsgi.ini # 停止uwsgi服务器 uwsgi stop uwsgi.ini
5. www服务器
处理pc端静态文件请求
cat nginx.conf # 配置文件 worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; sendfile on; keepalive_timeout 65; server { listen 80; server_name www.meiduo.site; location / { root html/front_end_pc; # 相对路径,把前端文件夹放到nginx安装路径下html目录下,我这里的路径是/application/nginx/html index index.html index.htm; } access_log logs/access_www.log main; } }
启动nginx服务
/application/nginx/sbin/nginx
6. wap服务器
处理移动端静态文件请求
cd /application/nginx/html # 因为没有移动端前端页面,所以这里简单创建了一个测试页面 mkdir wap echo "mobile_page" > wap/index.html
nginx配置
cat nginx.conf worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; sendfile on; keepalive_timeout 65; server { listen 80; server_name www.meiduo.site; location / { root html/wap; # 相对路径,把前端文件夹放到nginx安装路径下html目录下,我这里的路径是/application/nginx/html index index.html index.htm; } access_log logs/access_www.log main; } }
启动nginx服务
/application/nginx/sbin/nginx
7. mrcs服务器(资源有限,所以把这些东西安装在一台服务器上面)
mkdir /project # 挂载nfs服务器/project目录到uwsgi服务器的/project mount -t nfs 172.16.1.14:/project /project # 查看当前服务器挂载情况 df -h # 输出 文件系统 容量 已用 可用 已用% 挂载点 /dev/mapper/centos-root 36g 2.4g 33g 7% / devtmpfs 226m 0 226m 0% /dev tmpfs 237m 0 237m 0% /dev/shm tmpfs 237m 8.8m 228m 4% /run tmpfs 237m 0 237m 0% /sys/fs/cgroup /dev/sda1 1014m 143m 872m 15% /boot tmpfs 48m 0 48m 0% /run/user/0 172.16.1.14:/project 17g 1.8g 16g 11% /project # 创建虚拟环境 mkvirtualenv -p python3 meiduo # 切换到meiduo虚拟环境 workon mediuo # 安装项目中用到的pip包 cd /project/meiduo/meiduo_mall pip install -r requirements.txt # 这个文件是在开发环境中通过pip freeze >requirements.txt生成的
配置supervisor
mkvirtualenv -p python2 supervisor # 这里创建python2的虚拟环境,因为supervisor不支持python3 workon supervisor pip install supervisor # 生成supervisor配置文件 echo_supervisord_conf > /etc/supervisord.conf # 创建日志目录 mkdir /var/log/celery
创建celery.ini文件
cat /etc/celery.ini # 配置内容 [program:celery] # celery命令的绝对路径 command=/root/.virtualenvs/meiduo/bin/celery -a celery_tasks.main worker -l info # 项目路径 directory=/project/meiduo/meiduo_mall # 日志文件路径 stdout_logfile=/var/log/celery/celery.log # 自动重启 autorestart=true # 如果设置为true,进程则会把标准错误输出到supervisord后台的标准输出文件描述符 redirect_stderr=true
修改/etc/supervisord.conf文件
[include] files = celery.ini
supervisor命令
# 以守护进程的形式运行一组应用程序。 supervisord # 更新新的配置到supervisord supervisorctl update # 查看正在守护的进程 supervisorctl
8. 访问测试
在hosts文件里面添加本地解析
windows系统hosts文件路径:系统盘\windows\system32\drivers\etc
linux系统和mac系统hosts文件路径:/etc/hosts
172.16.1.10 www.meiduo.site api.meiduo.site
pc端访问效果