部署

 

Python作为当前最火爆最热门,也是最主要的Web开发语言之一,在其二十多年的历史中出现了数十种Web框架,比如Django、Tornado、Flask、Twisted、Bottle和Web.py等,它们有的历史悠久,有的发展迅速,还有的已经停止维护。Django是一个开放源代码的Web应用框架,由Python写成, 它作为Python重量级选手中最有代表性的一个Web框架, 许多成功的网站和APP都基于Django。

线上的web环境准备用Nginx+Django部署, 下面分别实现了Nginx+Django的http方式Nginx+uwsgi+Django的sock方式 (并通过supervisor以守护进程方式管理uwsgi),在大并发情况下, 使用第二种方式性能会更好.  简单记录下操作过程:

一. Nginx+Django (http方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
操作系统为Centos7.5 (本机ip为172.16.60.211)
[root@web-node ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
   
关闭防火墙和selinux
[root@web-node ~]# systemctl disable firewalld
[root@web-node ~]# systemctl stop firewalld
   
[root@web-node ~]# setenforce 0
[root@web-node ~]# vim /etc/sysconfig/selinux
SELINUX=disabled
   
1)  安装Python3.6.1
系统默认的是python2.7, 需要升级到Python3.6.1 ( 该Django项目跑在Python3.6.1版本下)
[root@web-node ~]# python -V
Python 2.7.5
   
下载并安装Python3.6.1
[root@web-node ~]# yum install -y gcc gcc-c++
[root@web-node ~]# yum -y install epel-release
[root@web-node ~]# yum install zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel
[root@web-node ~]# cd /usr/local/src/
[root@web-node src]# wget wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tar.xz
[root@web-node src]# tar xf Python-3.6.1.tar.xz
[root@web-node src]# cd Python-3.6.1
[root@web-node Python-3.6.1]# ./configure --prefix=/usr/local/python3
[root@web-node Python-3.6.1]# make && make install
   
确认安装的Python下有pip3
[root@web-node Python-3.6.1]# ll /usr/local/python3/bin/python3
lrwxrwxrwx 1 root root 9 Dec 12 15:57 /usr/local/python3/bin/python3 -> python3.6
   
[root@web-node Python-3.6.1]# ll /usr/local/python3/bin/pip3
-rwxr-xr-x 1 root root 222 Dec 12 15:57 /usr/local/python3/bin/pip3
   
替换python
[root@web-node Python-3.6.1]# cd /usr/bin
[root@web-node bin]# mv python python.bak
[root@web-node bin]# ln -s /usr/local/python3/bin/python3.6 /usr/bin/python
[root@web-node bin]# python -V                                          
Python 3.6.1
   
设置系统环境变量
[root@web-node bin]# vim /etc/profile
PATH=$PATH:/usr/local/python3/bin
   
[root@web-node bin]# source /etc/profile
   
解决遗留问题
所有python相关的应用,如果使用/usr/bin/python开头的脚本,替换为/usr/bin/python2.7
[root@web-node ~]# vim /usr/bin/yum
#!/usr/bin/python2.7
   
[root@web-node ~]# vim /usr/libexec/urlgrabber-ext-down
#! /usr/bin/python2.7
   
2) 安装nginx
[root@web-node ~]# useradd www
[root@web-node ~]# cd /usr/local/src/
[root@web-node src]# wget http://10.0.8.50/software/nginx-1.12.2.tar.gz
[root@web-node src]# tar -zvxf nginx-1.12.2.tar.gz
[root@web-node src]# cd nginx-1.12.2
[root@web-node nginx-1.12.2]# ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream
[root@web-node nginx-1.12.2]# make && make install
   
配置nginx
[root@web-node nginx-1.12.2]# cd /usr/local/nginx/conf/
[root@web-node conf]# cp nginx.conf nginx.conf.bak
[root@web-node conf]# > nginx.conf
[root@web-node conf]# vim nginx.conf
user  www;
worker_processes  4;
        
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
        
#pid        logs/nginx.pid;
        
        
events {
    worker_connections  65535;
}
        
        
http {
    include       mime.types;
    default_type  application/octet-stream;
    charset utf-8;
              
    ######
    ## set access log format
    ######
    log_format  main  '$http_x_forwarded_for $remote_addr $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_cookie" $host $request_time';
        
    #######
    ## http setting
    #######
    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;
    keepalive_timeout  65;
    proxy_cache_path /var/www/cache levels=1:2 keys_zone=mycache:20m max_size=2048m inactive=60m;
    proxy_temp_path /var/www/cache/tmp;
        
    fastcgi_connect_timeout 3000;
    fastcgi_send_timeout 3000;
    fastcgi_read_timeout 3000;
    fastcgi_buffer_size 256k;
    fastcgi_buffers 8 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    fastcgi_intercept_errors on;
        
    #
    client_header_timeout 600s;
    client_body_timeout 600s;
   # client_max_body_size 50m;
    client_max_body_size 100m;
    client_body_buffer_size 256k;
        
    gzip  on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 9;
    gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
    gzip_vary on;
        
    ## includes vhosts
    include vhosts/*.conf;
}
   
[root@web-node conf]# mkdir /usr/local/nginx/conf/vhosts
[root@web-node conf]# mkdir -p /var/www/cache
[root@web-node conf]# ulimit 65535
   
[root@web-node conf]# vim vhosts/ng.conf
upstream py-8001 {
      ip_hash;
      server 127.0.0.1:8001  max_fails=3 fail_timeout=15s;
      server 127.0.0.1:8002  max_fails=3 fail_timeout=15s;
}
                 
  server {
      listen      80;
      server_name kevin.com www.kevin.com btc.kevin.com eth.kevin.com;
           
      access_log  /usr/local/nginx/logs/8001-access.log main;
      error_log  /usr/local/nginx/logs/8001-error.log;
           
 location / {
         proxy_pass http://py-8001;
         proxy_redirect off ;
         proxy_set_header Host $host;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_set_header REMOTE-HOST $remote_addr;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_connect_timeout 300;
         proxy_send_timeout 300;
         proxy_read_timeout 600;
         proxy_buffer_size 256k;
         proxy_buffers 4 256k;
         proxy_busy_buffers_size 256k;
         proxy_temp_file_write_size 256k;
         proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
         proxy_max_temp_file_size 128m;
         #proxy_cache mycache;                         
         #proxy_cache_valid 200 302 1h;
         #proxy_cache_valid 301 1d;
         #proxy_cache_valid any 1m;
        }
       
 location /static/ {
      alias /data/www/APPServer/staticfiles/;
}
}
   
接着配置禁止ip访问,  只能通过域名访问 (vhosts下有很多域名的conf配置,那么只需要创建创建一个文件,比如deny.ip.conf,输入下面五行内容,这样就全局禁止了ip访问,只能使用域名访问了!))
[root@web-node ~]# cat /usr/local/nginx/conf/vhosts/deny.ip.conf
server{
listen 80 default;
server_name _;
return 500;
}
  
检查nginx配置文件是否正确
[root@r1014001 ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
  
这样nginx下就只能使用域名访问了, 使用ip访问的话, 就会出现"500 Internal Server Error"的信息, 即禁止ip访问!
  
3) 安装django (项目中使用的mysql是阿里云上的rds)
[root@web-node ~]# yum install MySQL-python
[root@web-node ~]# pip3 install Django==1.11      //最好使用pip3的全路径, 即"/usr/local/python3/bin/pip3 install Django==1.11", 否则可能会报错 
[root@web-node ~]# pip3 install pymysql           //最好使用pip3的全路径, 即"/usr/local/python3/bin/pip3 install pymysql", 否则可能会报错
   
django项目存放路径: /data/www/APPServer
静态页存放路径: /data/www/APPServer/staticfiles/
静态页通过nginx访问展示(匹配static的路径), 动态页面通过nginx转发给python处理
   
将django项目代码拷贝到/data/www/APPServer 目录中
[root@web-node ~]# mkdir -p /data/www/APPServer/
[root@web-node ~]# chown -R www.www /data/www/APPServer
[root@web-node ~]# cd /data/www/APPServer/
[root@web-node APPServer]# ls
db.sqlite3  django_auth_example  manage.py  staticfiles  templates  users
[root@web-node APPServer]# ls django_auth_example/
__init__.py  __init__.pyc  __pycache__  settings.py  settings.pyc  urls.py  urls.pyc  wsgi.py
[root@web-node APPServer]# ll staticfiles/strategy/
total 1552
-rw-r--r-- 1 www www  51215 Dec 11 17:55 all.css
-rw-r--r-- 1 www www  67742 Dec 11 17:55 bootstrap.bundle.min.js
-rw-r--r-- 1 www www 144877 Dec 11 17:55 bootstrap.min.css
-rw-r--r-- 1 www www 717611 Dec 11 17:55 echarts.min.js
-rw-r--r-- 1 www www  31000 Dec 11 17:55 font-awesome.min.css
-rw-r--r-- 1 www www   5187 Dec 11 17:55 index.js
-rw-r--r-- 1 www www  86351 Dec 11 17:55 jquery-3.1.0.min.js
-rw-r--r-- 1 www www  86927 Dec 11 17:55 jquery.min.js
-rw-r--r-- 1 www www    721 Dec 11 17:55 main.css
-rw-r--r-- 1 www www      0 Dec 11 17:55 main.js
-rw-r--r-- 1 www www   5872 Dec 11 17:55 master.js
-rw-r--r-- 1 www www   9662 Dec 11 17:55 tuzi.ico
-rw-r--r-- 1 www www 351295 Dec 11 17:55 v3-4b631620.css
   
启动python程序, 由于是交互式的, 这里通过tmux终端复用工具
[root@web-node ~]# yum install tmux
   
编写python程序启动和关闭脚本
[root@web-node ~]# mkdir /data/script
[root@web-node ~]# cd /data/script
   
启动脚本 (这里我启动了两个python程序进程, 并通过nginx进行代理转发, 将请求负载转发到这两个python端口上. 其实一台机器最好启动一个python进程, 多台机器启动多个python进程并通过nginx转发)
[root@web-node script]# vim py_start.sh
#!/bin/bash
tmux new -d -s bobo_session && tmux send -t bobo_session 'python /data/www/APPServer/manage.py runserver  0.0.0.0:8001' ENTER
tmux new -d -s bobo1_session && tmux send -t bobo1_session 'python /data/www/APPServer/manage.py runserver  0.0.0.0:8002' ENTER
   
================================================================================
温馨提示:
上面的python程序启动时, 端口前面最好不要加ip了, 比如"/usr/local/python3/bin/python3 /data/www/APPServer/manage.py runserver 8001"
这样就只能通过nginx代理访问了, 即http://172.16.60.211, 使用http://172.16.60.211:8001和http://172.16.60.211:8002就不能访问了
================================================================================
   
关闭脚本
[root@web-node script]# vim py_stop.sh
#!/bin/bash
tmux kill-session -t bobo_session && tmux kill-session -t bobo1_session
   
授予脚本执行权限
[root@web-node script]# chmod 755 ./*
[root@web-node script]# ll
total 8
-rwxr-xr-x 1 root root 267 Dec 12 16:55 py_start.sh
-rwxr-xr-x 1 root root  85 Dec 12 16:55 py_stop.sh
   
启动nginx和python程序
[root@web-node ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
   
[root@web-node ~]# /usr/local/nginx/sbin/nginx
   
[root@web-node ~]# sh /data/script/py_start.sh
   
[root@web-node ~]# ps -ef|grep nginx
root      1322     1  0 16:56 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
www       1323  1322  0 16:56 ?        00:00:00 nginx: worker process
www       1324  1322  0 16:56 ?        00:00:00 nginx: worker process
www       1325  1322  0 16:56 ?        00:00:00 nginx: worker process
www       1326  1322  0 16:56 ?        00:00:00 nginx: worker process
www       1327  1322  0 16:56 ?        00:00:00 nginx: cache manager process
www       1328  1322  0 16:56 ?        00:00:00 nginx: cache loader process
root      1397 12945  0 16:56 pts/0    00:00:00 grep --color=auto nginx
   
[root@web-node ~]# ps -ef|grep manage
www       1327  1322  0 16:56 ?        00:00:00 nginx: cache manager process
root      1370  1341  3 16:56 pts/4    00:00:00 python /data/www/APPServer/manage.py runserver 0.0.0.0:8002
root      1371  1336  3 16:56 pts/2    00:00:00 python /data/www/APPServer/manage.py runserver 0.0.0.0:8001
root      1374  1370  6 16:56 pts/4    00:00:00 /usr/bin/python /data/www/APPServer/manage.py runserver 0.0.0.0:8002
root      1375  1371  5 16:56 pts/2    00:00:00 /usr/bin/python /data/www/APPServer/manage.py runserver 0.0.0.0:8001
root      1399 12945  0 16:56 pts/0    00:00:00 grep --color=auto manage
   
[root@web-node ~]# lsof -i:80
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
nginx   1322 root    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
nginx   1323  www    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
nginx   1324  www    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
nginx   1325  www    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
nginx   1326  www    7u  IPv4 68809825      0t0  TCP *:http (LISTEN)
   
[root@web-node ~]# lsof -i:8001
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
python  1375 root    4u  IPv4 68810914      0t0  TCP *:vcom-tunnel (LISTEN)
   
[root@web-node ~]# lsof -i:8002
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
python  1374 root    4u  IPv4 68811847      0t0  TCP *:teradataordbms (LISTEN)
   
[root@web-node ~]# tmux ls
bobo1_session: 1 windows (created Wed Dec 12 16:56:51 2018) [194x45]
bobo_session: 1 windows (created Wed Dec 12 16:56:51 2018) [194x45]
   
最后将nginx配置文件中指定的域名kevin.com, www.kevin.com, btc.kevin.com, eth.kevin.com 解析到本机ip
然后输入http://www.kevin.com 即可访问django的web项目.

二. Nginx+uwsgi+Django (socker方式)
Django的部署可以有很多方式,采用nginx+uwsgi的方式是Django生产环境部署中比较常见的一种方式

uwsgi介绍
uWSGI是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换。

这里一定要注意 WSGI , uwsgi , uWSGI 这三个概念的区分:
1) WSGI是一种Web服务器网关接口。它是一个Web服务器(如nginx,uWSGI等服务器)与web应用(如用Flask框架写的程序)通信的一种规范。
2) uwsgi是一种线路协议而不是通信协议,在此常用于在uWSGI服务器与其他网络服务器的数据通信。
3) uWSGI是实现了uwsgi和WSGI两种协议的Web服务器。

uwsgi协议是一个uWSGI服务器自有的协议,它用于定义传输信息的类型,每一个uwsgi packet前4byte为传输信息类型描述,它与WSGI相比是两样东西。uwsgi是一种线路协议而不是通信协议,在此常用于在uwsgi服务器与其他网络服务器的数据通信。uwsgi协议是一个uwsgi服务器自有的协议,它用于定义传输信息的类型。uwsgi实现了WSGI的所有接口,是一个快速、自我修复、开发人员和系统管理员友好的服务器。uwsgi代码完全用C编写,效率高、性能稳定。

uWSGI的主要特点如下
-  超快的性能;
-  低内存占用(实测为apache2的mod_wsgi的一半左右);
-  多app管理(终于不用冥思苦想下个app用哪个端口比较好了);
-  详尽的日志功能(可以用来分析app性能和瓶颈);
-  高度可定制(内存大小限制,服务一定次数后重启等);

uwsgi作用
Django 是一个 Web 框架,框架的作用在于处理 request 和 reponse,其他的不是框架所关心的内容。所以怎么部署 Django 不是 Django 所需要关心的。Django 所提供的是一个开发服务器,这个开发服务器,没有经过安全测试,而且使用的是 Python 自带的 simple HTTPServer 创建的,在安全性和效率上都是不行的而uwsgi 是一个全功能的 HTTP 服务器,他要做的就是把 HTTP 协议转化成语言支持的网络协议。比如把 HTTP 协议转化成 WSGI 协议,让 Python 可以直接使用。 
uwsgi 是一种 uwsgi 的内部协议,使用二进制方式和其他应用程序进行通信。

总之uwsgi真的是一个好东西, 用起来性能非常高. 如果使用nginx+uwsgi方式, nginx作为反向代理,和uwsgi间通过http交互。配置nginx和uwsgi通过socket结合的方式原理用户发送http请求到nginx,nginx通过socket把请求交给uwsgi,uwsgi拿到django的处理结果,通过socket返还给nginx,nginx通过http返回结果给用户。操作如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
安装uwsgi
[root@web-node ~]# pip3 install uwsgi
   
编写测试
[root@web-node ~]# vim /root/test.py
def application(env, start_response):
    start_response('200 OK', [('Content-Type','text/html')])
    return [b"Hello World"]
   
启动测试
[root@web-node ~]# uwsgi --http :9009 --wsgi-file test.py
   
接着访问http://172.16.60.211:9009/  , 即可看到"Hello World"的访问信息.
   
下面开始nginx+uwsgi的配置
[root@web-node ~]# ll /usr/local/nginx/conf/uwsgi*
-rw-r--r-- 1 root root 664 Dec 12 16:25 /usr/local/nginx/conf/uwsgi_params
-rw-r--r-- 1 root root 664 Dec 12 16:25 /usr/local/nginx/conf/uwsgi_params.default
   
手动编写uwsgi.ini配置文件 (由于这里我启动了两个python程序, 即8001和8002端口, 所以这里要编写两个uwsgi配置文件)
[root@web-node ~]# vim /usr/local/nginx/conf/uwsgi1.ini
[uwsgi]
#the local unix socket file than commnuincate to Nginx
socket = 127.0.0.1:8001
  
# the base directory (full path)
chdir = /data/www/APPServer
  
# Django's wsgi file
wsgi-file = django_auth_example/wsgi.py
  
# maximum number of worker processes
processes = 4
  
#thread numbers startched in each worker process
threads = 2
  
[root@web-node ~]# vim /usr/local/nginx/conf/uwsgi2.ini
[uwsgi]
#the local unix socket file than commnuincate to Nginx
socket = 127.0.0.1:8002
  
# the base directory (full path)
chdir = /data/www/APPServer
  
# Django's wsgi file
wsgi-file = django_auth_example/wsgi.py
  
# maximum number of worker processes
processes = 4
  
#thread numbers startched in each worker process
threads = 2
  
启动uwsgi (先关闭之前启动的python程序和nginx)
[root@web-node ~]# sh /data/script/py_stop.sh
[root@web-node ~]# /usr/local/nginx/sbin/nginx -s stop
   
[root@web-node ~]# uwsgi /usr/local/nginx/conf/uwsgi1.ini 
[root@web-node ~]# uwsgi /usr/local/nginx/conf/uwsgi2.ini
  
由于uwsgi启动也是交互式, 所以还是需要用到tmux工具, 编写uwsgi启动和关闭脚本
   
uwsgi启动脚本
[root@web-node ~]# vim /data/script/uwsgi_start.sh
#!/bin/bash
tmux new -d -s bobo_session && tmux send -t bobo_session 'uwsgi /usr/local/nginx/conf/uwsgi1.ini' ENTER
tmux new -d -s bobo1_session && tmux send -t bobo1_session 'uwsgi /usr/local/nginx/conf/uwsgi2.ini' ENTER
  
uwsgi关闭脚本
[root@web-node ~]# vim /data/script/uwsgi_stop.sh
#!/bin/bash
tmux kill-session -t bobo_session && tmux kill-session -t bobo1_session
ps -ef|grep uwsgi|grep -v grep|awk '{print $2}'|xargs kill -9  >/dev/null 2>&1
  
执行uwsgi启动
[root@web-node ~]# sh /data/script/uwsgi_start.sh
  
[root@web-node ~]# tmux ls
bobo1_session: 1 windows (created Wed Dec 12 22:49:49 2018) [136x29]
bobo_session: 1 windows (created Wed Dec 12 22:49:49 2018) [136x29]
  
[root@web-node ~]# lsof -i:8001
COMMAND   PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
uwsgi   21161 root    3u  IPv4 69341001      0t0  TCP localhost:vcom-tunnel (LISTEN)
uwsgi   21165 root    3u  IPv4 69341001      0t0  TCP localhost:vcom-tunnel (LISTEN)
uwsgi   21166 root    3u  IPv4 69341001      0t0  TCP localhost:vcom-tunnel (LISTEN)
uwsgi   21167 root    3u  IPv4 69341001      0t0  TCP localhost:vcom-tunnel (LISTEN)
  
[root@web-node ~]# lsof -i:8002
COMMAND   PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
uwsgi   21162 root    3u  IPv4 69341406      0t0  TCP localhost:teradataordbms (LISTEN)
uwsgi   21172 root    3u  IPv4 69341406      0t0  TCP localhost:teradataordbms (LISTEN)
uwsgi   21173 root    3u  IPv4 69341406      0t0  TCP localhost:teradataordbms (LISTEN)
uwsgi   21174 root    3u  IPv4 69341406      0t0  TCP localhost:teradataordbms (LISTEN)
  
[root@web-node ~]# ps -ef|grep uwsgi
root     21161 21128  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21162 21135  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21165 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21166 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21167 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21172 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21173 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21174 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21231 18304  0 22:50 pts/0    00:00:00 grep --color=auto uwsgi
  
接着进行nginx+uwsgi配置
[root@web-node ~]# vim /usr/local/nginx/conf/vhosts/ng.conf
upstream django {
    ip_hash;
    server 127.0.0.1:8001  max_fails=3 fail_timeout=15s;
    server 127.0.0.1:8002  max_fails=3 fail_timeout=15s;
}         
   server {
     listen      80;
     server_name kevin.com www.kevin.com btc.kevin.com eth.kevin.com;
     charset     utf-8;
          
     access_log  /usr/local/nginx/logs/8001-access.log main;
     error_log  /usr/local/nginx/logs/8001-error.log;
          
   location / {
     uwsgi_pass  django;
     include    /usr/local/nginx/conf/uwsgi_params;
     }
      
   location /static/ {
     alias /data/www/APPServer/staticfiles/;
   }
}
  
启动nginx
[root@web-node ~]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
  
[root@web-node ~]# /usr/local/nginx/sbin/nginx
  
[root@web-node ~]# ps -ef|grep nginx
root     21161 21128  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21162 21135  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21165 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21166 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21167 21161  0 22:49 pts/1    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     21172 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21173 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21174 21162  0 22:49 pts/2    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     21263     1  0 22:51 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
www      21264 21263  0 22:51 ?        00:00:00 nginx: worker process
www      21265 21263  0 22:51 ?        00:00:00 nginx: worker process
www      21266 21263  0 22:51 ?        00:00:00 nginx: worker process
www      21267 21263  0 22:51 ?        00:00:00 nginx: worker process
www      21268 21263  0 22:51 ?        00:00:00 nginx: cache manager process
www      21269 21263  0 22:51 ?        00:00:00 nginx: cache loader process
root     21271 18304  0 22:51 pts/0    00:00:00 grep --color=auto nginx
  
[root@web-node ~]# lsof -i:80
COMMAND   PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
nginx   21263 root    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
nginx   21264  www    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
nginx   21265  www    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
nginx   21266  www    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
nginx   21267  www    7u  IPv4 69341986      0t0  TCP *:http (LISTEN)
  
最后输入http://www.kevin.com, 即可访问django的web项目

Supervisor管理uwsgi (守护进程模式)

由于直接执行uwsgi是交互式的, 所以上面使用了tmux终端复用工具, 如果不使用tmux, 则可以使用supervisor, 使用supervisor管理uwsgi, 为了让它后台运行,需要让它变成守护进程。supervisor的使用可以参考: https://www.cnblogs.com/kevingrace/p/7525200.html  .  以下是supervisor的安装和管理记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
1) 安装supervisor
[root@web-node ~]# pip3 install supervisor
会遇到如下报错信息:
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-ns8sn4n6/supervisor/
You are using pip version 9.0.1, however version 18.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
   
这是因为supervisor不支持python3, pip3使用的是python3.6.1版本
[root@web-node ~]# python -V
Python 3.6.1
   
1.1) 安装pyenv
为了使用supervisor,我们需要python2.7的环境。而多版本python的管理,推荐使用pyenv。
   
安装pyenv套装
[root@web-node ~]# curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer | bash
   
内容除了包含 pyenv 以外,还包含如下插件:
- pyenv-doctor
- pyenv-installer
- pyenv-update
- pyenv-virtualenv
- pyenv-which-ext
   
=========================================================
温馨提示:
以上https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/pyenv-installer的访问内容
, 可以将内容粘出来放在服务器的一个shell脚本文件中, 然后执行该脚本用以安装pyenv
   
该脚本的百度下载地址:  https://pan.baidu.com/s/1wW9ylrmc4Q9wxu_i3-1wYA
提取密码: rhtj
   
执行脚本进行安装(执行前授予755权限)
# chmod 755 pyenv-installer
# /bin/bash pyenv-installer
=========================================================
   
路径添加
[root@web-node ~]# ll -d /root/.pyenv
drwxr-xr-x 11 root root 331 Dec 13 10:08 /root/.pyenv
   
[root@web-node ~]# vim ~/.bash_profile              //添加下面内容
export PATH="/root/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
   
使之生效
[root@web-node ~]# source ~/.bash_profile
   
查看安装情况
[root@web-node ~]# pyenv -v
pyenv 1.2.8
   
常用命令
- 查看可安装的python版本列表:pyenv install -l
- 安装指定版本的python:pyenv install 2.7.3
- 查看已安装的python:pyenv versions
- 查看当前设为默认的python版本:pyenv version
   
1.2) 安装python2.7环境
pyenv安装指定版本的python
[root@web-node python]# pyenv install 2.7.13
Installing Python-2.7.13...
Installed Python-2.7.13 to /root/.pyenv/versions/2.7.13
   
[root@web-node ~]# /root/.pyenv/versions/2.7.13/bin/python2.7 -V
Python 2.7.13
   
查看pyenv已安装的python
[root@web-node ~]# pyenv versions
  system
* 2.7.13 (set by /root/.pyenv/version)
  2.7.13/envs/supervisor
   
查看当前pyenv设为默认的python版本
[root@web-node ~]# pyenv version
2.7.13 (set by /root/.pyenv/version)
   
1.3) 安装虚拟环境
新建supervisor虚拟环境
[root@web-node ~]# pyenv virtualenv 2.7.13 supervisor
   
激活虚拟环境
[root@web-node ~]# source /root/.pyenv/versions/2.7.13/envs/supervisor/bin/activate supervisor
(supervisor) [root@web-node ~]#
或者
(supervisor) [root@web-node ~]# source activate supervisor
(supervisor) [root@web-node ~]#
   
安装supervisor
(supervisor) [root@web-node ~]# yum install supervisor
(supervisor) [root@web-node ~]# pip install supervisor
   
生成配置文件
(supervisor) [root@web-node ~]# mkdir -p /etc/supervisor/
(supervisor) [root@web-node ~]# echo_supervisord_conf > /etc/supervisord.conf
   
修改配置文件 (文件最底行添加下面内容)
(supervisor) [root@web-node ~]# vim /etc/supervisord.conf
[include]
files = /etc/supervisor/*.conf
   
运行
(supervisor) [root@web-node ~]# /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
   
(supervisor) [root@web-node ~]# ps -ef|grep supervisord
root     30765     1  0 10:57 ?        00:00:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root     30798 10184  0 10:57 pts/1    00:00:00 grep --color=auto supervisord
   
1.4) 编辑supervisord.service
(supervisor) [root@web-node ~]# cp /usr/lib/systemd/system/supervisord.service /usr/lib/systemd/system/supervisord.service.bak
(supervisor) [root@web-node ~]# vim /usr/lib/systemd/system/supervisord.service        //内容修改为(之前的内容清空, 复制下面的内容)
[Unit]
Description=Process Monitoring and Control Daemon
After=rc-local.service nss-user-lookup.target
   
[Service]
Type=forking
ExecStart=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
ExecReload=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisorctl reload    
ExecStop=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisorctl shutdown   
   
[Install]
WantedBy=multi-user.target
   
1.5) 重启supervisor (多测试几次)
(supervisor) [root@web-node ~]# ps aux | grep supervisord
root     31663  0.0  0.1 215176 13856 ?        Ss   11:03   0:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root     31781  0.0  0.0 112704   976 pts/1    S+   11:03   0:00 grep --color=auto supervisord
   
由于上面的supervisord进程是使用配置文件手动启动的, 首次要使用下面的命令关闭,然后使用"systemctl start/stop supervisord" 才会生效
如果第一次不使用下面命令关闭, 而首次就使用"systemctl stop supervisord" 则关闭不了.
(supervisor) [root@web-node ~]# /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisorctl shutdown
Shut down
(supervisor) [root@web-node ~]# ps aux | grep supervisord                                           
root     31857  0.0  0.0 112704   972 pts/1    S+   11:04   0:00 grep --color=auto supervisord
   
(supervisor) [root@web-node ~]# systemctl start supervisord
(supervisor) [root@web-node ~]# ps aux | grep supervisord
root     31892  0.0  0.1 217312 13872 ?        Ss   11:04   0:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root     31919  0.0  0.0 112704   972 pts/1    S+   11:04   0:00 grep --color=auto supervisord
   
(supervisor) [root@web-node ~]# systemctl stop supervisord                                           
(supervisor) [root@web-node ~]# ps aux | grep supervisord
root     31986  0.0  0.0 112704   976 pts/1    S+   11:04   0:00 grep --color=auto supervisord
   
(supervisor) [root@web-node ~]# systemctl start supervisord
(supervisor) [root@web-node ~]# ps aux | grep supervisord
root     32037  0.0  0.1 217312 13868 ?        Ss   11:04   0:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root     32064  0.0  0.0 112704   976 pts/1    S+   11:04   0:00 grep --color=auto supervisord
   
1.6) 设置开机启动
(supervisor) [root@web-node ~]# systemctl enable supervisord
Created symlink from /etc/systemd/system/multi-user.target.wants/supervisord.service to /usr/lib/systemd/system/supervisord.service.
   
2) 守护uwsgi
先关闭之前使用tmux启动的uwsgi进程
(supervisor) [root@web-node ~]# ps -ef|grep uwsgi
root     29088 29055  0 00:53 pts/4    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     29089 29061  0 00:53 pts/5    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     29092 29089  0 00:53 pts/5    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     29093 29089  0 00:53 pts/5    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     29094 29089  0 00:53 pts/5    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.ini
root     29098 29088  0 00:53 pts/4    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     29099 29088  0 00:53 pts/4    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     29100 29088  0 00:53 pts/4    00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.ini
root     32579 10184  0 11:09 pts/1    00:00:00 grep --color=auto uwsgi
   
(supervisor) [root@web-node ~]# tmux ls
bobo1_session: 1 windows (created Thu Dec 13 00:53:19 2018) [136x29]
bobo_session: 1 windows (created Thu Dec 13 00:53:19 2018) [136x29]
   
(supervisor) [root@web-node ~]# sh /data/script/uwsgi_stop.sh
Killed
   
(supervisor) [root@web-node ~]# ps -ef|grep uwsgi
root     32689 10184  0 11:09 pts/1    00:00:00 grep --color=auto uwsgi
   
(supervisor) [root@web-node ~]# tmux ls
failed to connect to server
   
2.1) 配置supervisor, 以守护进程方式管理uwsgi
先关闭上面启动的supervisord
(supervisor) [root@web-node supervisor]# systemctl stop supervisord
(supervisor) [root@web-node supervisor]# ps aux | grep supervisord
root      2467  0.0  0.0 112704   972 pts/1    S+   11:27   0:00 grep --color=auto supervisord
  
因为nginx和uwsgi通过socket方式交互,所以需要修改uwsgi.ini的配置为:
(supervisor) [root@web-node supervisor]# cd /usr/local/nginx/conf/
(supervisor) [root@web-node conf]# cp uwsgi1.ini uwsgi1.ini.bak
(supervisor) [root@web-node conf]# cp uwsgi2.ini uwsgi2.ini.bak
(supervisor) [root@web-node conf]# vim uwsgi1.ini
[uwsgi]
socket = :8001                     
chdir = /data/www/APPServer
wsgi-file = django_auth_example/wsgi.py
static-map = '/static=static'
master = true
processes = 2
enable-threads = true
   
(supervisor) [root@web-node conf]# vim uwsgi2.ini
[uwsgi]
socket = :8002              
chdir = /data/www/APPServer
wsgi-file = django_auth_example/wsgi.py
static-map = '/static=static'
master = true
processes = 2
enable-threads = true
   
接着在/etc/supervisor中新建文件bobo.conf和bobo1.conf(这里启动了两个端口, 所以也要配置两个)
(supervisor) [root@web-node supervisor]# vim bobo.conf
[program:bobo]
command=/usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi1.ini
directory=/usr/local/nginx/conf/
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
   
(supervisor) [root@web-node supervisor]# vim bobo1.conf
[program:bobo1]
command=/usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi2.ini
directory=/usr/local/nginx/conf/
startsecs=0
stopwaitsecs=0
autostart=true
autorestart=true
   
重启supervisor
(supervisor) [root@web-node supervisor]# ps aux | grep supervisord
root      5177  0.0  0.0 112704   972 pts/1    S+   11:47   0:00 grep --color=auto supervisord
(supervisor) [root@web-node supervisor]# systemctl start supervisord     
   
(supervisor) [root@web-node supervisor]# ps aux | grep supervisord
root      5218  0.0  0.1 217568 14104 ?        Ss   11:47   0:00 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf
root      5253  0.0  0.0 112704   972 pts/1    S+   11:47   0:00 grep --color=auto supervisord
 
(supervisor) [root@web-node supervisor]# systemctl status supervisord  
● supervisord.service - Process Monitoring and Control Daemon
   Loaded: loaded (/usr/lib/systemd/system/supervisord.service; enabled; vendor preset: disabled)
   Active: active (running) since Thu 2018-12-13 13:35:46 CST; 26s ago
  Process: 11883 ExecStop=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisorctl shutdown (code=exited, status=0/SUCCESS)
  Process: 12681 ExecStart=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.conf (code=exited, status=0/SUCCESS)
 Main PID: 12684 (supervisord)
   CGroup: /system.slice/supervisord.service
           ├─12684 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/python2.7 /root/.pyenv/versions/2.7.13/envs/supervisor/bin/superv...
           ├─12717 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi1.ini
           ├─12718 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi2.ini
           ├─12721 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi1.ini
           ├─12722 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi1.ini
           ├─12723 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi2.ini
           └─12724 /usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi2.ini
 
Dec 13 13:35:46 web-node systemd[1]: Starting Process Monitoring and Control Daemon...
Dec 13 13:35:46 web-node systemd[1]: Started Process Monitoring and Control Daemon.
Warning: supervisord.service changed on disk. Run 'systemctl daemon-reload' to reload units.
   
(supervisor) [root@web-node supervisor]# lsof -i:8001
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
uwsgi   5244 root    3u  IPv4 70530592      0t0  TCP *:vcom-tunnel (LISTEN)
uwsgi   5250 root    3u  IPv4 70530592      0t0  TCP *:vcom-tunnel (LISTEN)
uwsgi   5251 root    3u  IPv4 70530592      0t0  TCP *:vcom-tunnel (LISTEN)
   
(supervisor) [root@web-node supervisor]# lsof -i:8002
COMMAND  PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
uwsgi   5245 root    3u  IPv4 70531513      0t0  TCP *:teradataordbms (LISTEN)
uwsgi   5248 root    3u  IPv4 70531513      0t0  TCP *:teradataordbms (LISTEN)
uwsgi   5249 root    3u  IPv4 70531513      0t0  TCP *:teradataordbms (LISTEN)
   
========================================================
附带温馨提示
直接重启supervisor项目bobo和项目bobo1的命令
(supervisor) [root@web-node supervisor]# supervisorctl -c /etc/supervisord.conf restart bobo
bobo: stopped
bobo: started
   
(supervisor) [root@web-node supervisor]# supervisorctl -c /etc/supervisord.conf restart bobo1
bobo1: stopped
bobo1: started
========================================================
   
上面在nginx中vhosts/ng.conf文件中配置的转发关系不用修改.
需要知道的事: 此时django项目中的的静态资源并不是通过uwsgi获取, 而是通过nginx直接获取的(匹配static的path路径访问静态资源)
   
此时输入http://www.kevin.com, 即可访问django的web项目!
   
最后退出supervisor环境
(supervisor) [root@web-node supervisor]# source deactivate
pyenv-virtualenv: deactivate 2.7.13/envs/supervisor
[root@web-node supervisor]#
   
退出supervisor环境后, uwsgi守护进程并没有受到影响。
   
再次进入supervisor环境
[root@web-node supervisor]# source activate supervisor
pyenv-virtualenv: activate supervisor
pyenv-virtualenv: prompt changing will be removed from future release. configure `export PYENV_VIRTUALENV_DISABLE_PROMPT=1' to simulate the behavior.
(supervisor) [root@web-node supervisor]#

posted on 2019-06-21 15:57  webch  阅读(358)  评论(0)    收藏  举报

导航