一、架构

首先浏览器发起 http 请求到 nginx 服务器,它们之间走的是 http 协议,nginx 根据接收到请求包,进行 url 分析,判断访问资源的类型。
如果是静态资源,直接读取静态资源返回给浏览器,如果请求的是动态资源就转交给 uWSGI 服务器。
因为 nginx 和 uWSGI 都懂 uwsgi 协议,uwsgi 为纯二进制的协议,不用去封装七层协议中的协议体中的各种状态位。效率比较快,所以 nginx 和 uWSGI 之间走 uwsgi 协议。此时 uWSGI 需要通过 socket 模式启动。【http 纯文本型协议(超文本传输),效率不是很高】
uWSGI 服务器根据自身的 WSGI 协议,找到对应的 Django 框架。
Django 框架下的应用进行逻辑处理后,将返回值发送到 uWSGI 服务器。
uWSGI 服务器再返回给 nginx,最后 nginx 将返回值返回给浏览器进行渲染显示给用户。

二、利用web框架(django、flask、web.py...)写一个wsgi的app
api.py文件:
#coding:utf-8
import web
# url映射
urls = (
'/(.*)', 'hello')
# url处理的类
class hello:
def GET(self, name):
print(web.ctx.env.items())#获取所有的headers
if not name:
name = 'World'
return 'Hello, ' + name + '!'
# 创建一个基于我们刚提交的URL列表的application。这个application会在这个文件的全局命名空间中查找对应类。
app = web.application(urls, globals())
application = app.wsgifunc() # 这两行放到外面
if __name__ == "__main__":
app.run() #启动web应用
直接执行这个py文件也可以启动web应用:python api.py。
三、通过gunicorn运行 app(wsgi application)
采用使用配置文件方式启动gunicorn,config.py:
#coding:utf-8
import logging
import logging.handlers
from logging.handlers import WatchedFileHandler
import os
import multiprocessing
bind = '0.0.0.0:8080' #绑定ip和端口号
backlog = 512 #最大挂起的连接数
chdir = '/home/mytest/' #gunicorn要切换到的目的工作目录
timeout = 30 #超时
workers = multiprocessing.cpu_count() * 2 + 1 #工作进程数
loglevel = 'info' #日志级别,这个日志级别指的是错误日志的级别,而访问日志的级别无法设置
access_log_format = '%(t)s %(p)s %(h)s "%(r)s" %(s)s %(L)s %(b)s %(f)s" "%(a)s"' #设置gunicorn访问日志格式,错误日志无法设置
accesslog = "gunicorn_access.log" #访问日志文件
errorlog = "gunicorn_error.log" #错误日志文件
注:
-
如果通过gunicorn(wsgi)运行web,那么就是gunicorn配置文件里面的bind = '0.0.0.0:8080。 如果写127.0.0.1,那么就只能在本机通过127.0.0.1:port来访问,如果写0.0.0.0,那就就可以用127.0.0.1:port、内网:port、外网:port来访问web接口。--- https://www.cnblogs.com/qiaoer1993/p/12102055.html
-
在项目目录(cd /home/mytest/ )下,直接使用命令gunicorn --config=config.py api:application也可启动web应用
四、supervisor管理子进程
[root@uap mytest]#vi /etc/supervisord.conf
[inet_http_server] #supervisor的web管理界面配置,http方式
port=0.0.0.0:19001
username=admin
password=123456
[supervisord] #不可少,管理服务本身的配置
pidfile=/var/run/supervisord.pid
logfile=/var/log/supervisord.log
logfile_maxbytes=50MB #日志切割大小,默认50M
logfile_backups=10 #切割的日志保留份数,默认10
loglevel=info
nodaemon=false #是否后台开启,默认false,true为前台开启
minfds=1024 #可以打开的文件描述符的最小值,默认1024
minprocs=200 #可以打开的进程数的最小值,默认200
[program:api]
autorestart=true
command= gunicorn --config=config.py api:application
directory=/home/mytest/ #切换到该目录
process_name=%(program_name)s
redirect_stderr=true
stdout_logfile=/var/log/di/%(program_name)s.log
注:直接执行命令/usr/bin/supervisord -c /etc/supervisord.conf可以启动web应用,但开机重启后因为supervisor没有启动导致web应用起不来,所以接下来要实现supervisor开机自启
五、supervisor开机自启
通过pip install supervisor 安装了supervisor,用来自动重启服务;但当机器重启后,supervisor却不能自启动,怎样解决呢??利用linux的service。思路: 在/etc/init.d目录下编写一个脚本,再用“ service 脚本名 start|stop|status|restart ”运行即可。chkconfig命令实现supervisor服务的开机自启动。
#!/bin/bash
#
# supervisord This scripts turns supervisord on
# description: supervisor is a process control utility. It has a web based
# xmlrpc interface as well as a few other nifty features.
# processname: supervisord
# config: /etc/supervisord.conf
# pidfile: /var/run/supervisord.pid
#
# source function library
. /etc/rc.d/init.d/functions
RETVAL=0
start() {
echo -n $"Starting supervisord: "
daemon " /usr/bin/supervisord -c /etc/supervisord.conf"
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/supervisord
}
stop() {
echo -n $"Stopping supervisord: "
killproc supervisord
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/supervisord
}
restart() {
stop
start
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart|force-reload|reload)
restart
;;
condrestart)
[ -f /var/lock/subsys/supervisord ] && restart
;;
status)
status supervisord
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}"
exit 1
esac
exit $RETVAL
2、设置脚本可执行权限
# chmod +x /etc/init.d/supervisor
3、设置服务开机自启动
# chkconfig supervisor on
五、重启机器验证
[root@zq di]# ps -ef| grep super
root 1960 1 0 23:01 ? 00:00:00 /usr/bin/python2 /usr/bin/supervisord -c /etc/supervisord.conf
root 3356 3085 0 23:19 pts/0 00:00:00 grep --color=auto super
2、验证web服务是否启动
[root@zq di]# ps -ef| grep api
root 2306 1960 0 23:01 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 2340 2306 0 23:01 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 2358 2306 0 23:01 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 2368 2306 0 23:01 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 2392 2306 0 23:01 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 2454 2306 0 23:01 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 2527 2306 0 23:01 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 2528 2306 0 23:01 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 3157 2306 0 23:06 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 3160 2306 0 23:06 ? 00:00:00 /usr/bin/python2 /bin/gunicorn --config=config.py api:application
root 3412 3085 0 23:21 pts/0 00:00:00 grep --color=auto api

七、nginx包装
1、安装nginx(yum install nginx)
2、修改nginx的配置文件nginx.conf:
[root@zq mytest]#vi /etc/nginx.nginx.conf
server {
listen 888; #需要在防护墙中打开888端口,否则nginx日志中会出现错误:nginx: [emerg] bind() to 0.0.0.0:888 failed (13: Permission denied)
location / {
client_max_body_size 2048M;
proxy_pass http://0.0.0.0:8080; #通过proxy_pass参数反向代理给运行在http://0.0.0.0:8080上的Gunicorn
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
3、重新加载nginx
nginx -s reload -c /etc/nginx/nginx.conf
注:若出现错误“nginx: [error] invalid PID number "" in "/run/nginx.pid"”,请执行以下两句命令启动nginx
sudo nginx -c /etc/nginx/nginx.conf
sudo nginx -s reload
4、访问web浏览器 ,端口888