部署
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-releaseCentOS 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/selinuxSELINUX=disabled 1) 安装Python3.6.1系统默认的是python2.7, 需要升级到Python3.6.1 ( 该Django项目跑在Python3.6.1版本下)[root@web-node ~]# python -VPython 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/python3lrwxrwxrwx 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/profilePATH=$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.confuser 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.confupstream 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.confserver{listen 80 default;server_name _;return 500;} 检查nginx配置文件是否正确[root@r1014001 ~]# /usr/local/nginx/sbin/nginx -tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: 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]# lsdb.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/bashtmux new -d -s bobo_session && tmux send -t bobo_session 'python /data/www/APPServer/manage.py runserver 0.0.0.0:8001' ENTERtmux 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/bashtmux kill-session -t bobo_session && tmux kill-session -t bobo1_session 授予脚本执行权限[root@web-node script]# chmod 755 ./*[root@web-node script]# lltotal 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 -tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: 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 nginxroot 1322 1 0 16:56 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginxwww 1323 1322 0 16:56 ? 00:00:00 nginx: worker processwww 1324 1322 0 16:56 ? 00:00:00 nginx: worker processwww 1325 1322 0 16:56 ? 00:00:00 nginx: worker processwww 1326 1322 0 16:56 ? 00:00:00 nginx: worker processwww 1327 1322 0 16:56 ? 00:00:00 nginx: cache manager processwww 1328 1322 0 16:56 ? 00:00:00 nginx: cache loader processroot 1397 12945 0 16:56 pts/0 00:00:00 grep --color=auto nginx [root@web-node ~]# ps -ef|grep managewww 1327 1322 0 16:56 ? 00:00:00 nginx: cache manager processroot 1370 1341 3 16:56 pts/4 00:00:00 python /data/www/APPServer/manage.py runserver 0.0.0.0:8002root 1371 1336 3 16:56 pts/2 00:00:00 python /data/www/APPServer/manage.py runserver 0.0.0.0:8001root 1374 1370 6 16:56 pts/4 00:00:00 /usr/bin/python /data/www/APPServer/manage.py runserver 0.0.0.0:8002root 1375 1371 5 16:56 pts/2 00:00:00 /usr/bin/python /data/www/APPServer/manage.py runserver 0.0.0.0:8001root 1399 12945 0 16:56 pts/0 00:00:00 grep --color=auto manage [root@web-node ~]# lsof -i:80COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEnginx 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:8001COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEpython 1375 root 4u IPv4 68810914 0t0 TCP *:vcom-tunnel (LISTEN) [root@web-node ~]# lsof -i:8002COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEpython 1374 root 4u IPv4 68811847 0t0 TCP *:teradataordbms (LISTEN) [root@web-node ~]# tmux lsbobo1_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.pydef 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 Nginxsocket = 127.0.0.1:8001 # the base directory (full path)chdir = /data/www/APPServer # Django's wsgi filewsgi-file = django_auth_example/wsgi.py # maximum number of worker processesprocesses = 4 #thread numbers startched in each worker processthreads = 2 [root@web-node ~]# vim /usr/local/nginx/conf/uwsgi2.ini [uwsgi]#the local unix socket file than commnuincate to Nginxsocket = 127.0.0.1:8002 # the base directory (full path)chdir = /data/www/APPServer # Django's wsgi filewsgi-file = django_auth_example/wsgi.py # maximum number of worker processesprocesses = 4 #thread numbers startched in each worker processthreads = 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/bashtmux new -d -s bobo_session && tmux send -t bobo_session 'uwsgi /usr/local/nginx/conf/uwsgi1.ini' ENTERtmux 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/bashtmux kill-session -t bobo_session && tmux kill-session -t bobo1_sessionps -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 lsbobo1_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:8001COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEuwsgi 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:8002COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEuwsgi 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 uwsgiroot 21161 21128 0 22:49 pts/1 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 21162 21135 0 22:49 pts/2 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 21165 21161 0 22:49 pts/1 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 21166 21161 0 22:49 pts/1 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 21167 21161 0 22:49 pts/1 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 21172 21162 0 22:49 pts/2 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 21173 21162 0 22:49 pts/2 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 21174 21162 0 22:49 pts/2 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 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.confupstream 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 -tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: 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 nginxroot 21161 21128 0 22:49 pts/1 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 21162 21135 0 22:49 pts/2 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 21165 21161 0 22:49 pts/1 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 21166 21161 0 22:49 pts/1 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 21167 21161 0 22:49 pts/1 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 21172 21162 0 22:49 pts/2 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 21173 21162 0 22:49 pts/2 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 21174 21162 0 22:49 pts/2 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 21263 1 0 22:51 ? 00:00:00 nginx: master process /usr/local/nginx/sbin/nginxwww 21264 21263 0 22:51 ? 00:00:00 nginx: worker processwww 21265 21263 0 22:51 ? 00:00:00 nginx: worker processwww 21266 21263 0 22:51 ? 00:00:00 nginx: worker processwww 21267 21263 0 22:51 ? 00:00:00 nginx: worker processwww 21268 21263 0 22:51 ? 00:00:00 nginx: cache manager processwww 21269 21263 0 22:51 ? 00:00:00 nginx: cache loader processroot 21271 18304 0 22:51 pts/0 00:00:00 grep --color=auto nginx [root@web-node ~]# lsof -i:80COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEnginx 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 -VPython 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/.pyenvdrwxr-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 -vpyenv 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.13Installing 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 -VPython 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 version2.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 supervisordroot 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.confroot 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 DaemonAfter=rc-local.service nss-user-lookup.target [Service]Type=forkingExecStart=/root/.pyenv/versions/2.7.13/envs/supervisor/bin/supervisord -c /etc/supervisord.confExecReload=/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 supervisordroot 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.confroot 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 shutdownShut 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 supervisordroot 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.confroot 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 supervisordroot 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 supervisordroot 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.confroot 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 supervisordCreated 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 uwsgiroot 29088 29055 0 00:53 pts/4 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 29089 29061 0 00:53 pts/5 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 29092 29089 0 00:53 pts/5 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 29093 29089 0 00:53 pts/5 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 29094 29089 0 00:53 pts/5 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi2.iniroot 29098 29088 0 00:53 pts/4 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 29099 29088 0 00:53 pts/4 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 29100 29088 0 00:53 pts/4 00:00:00 uwsgi /usr/local/nginx/conf/uwsgi1.iniroot 32579 10184 0 11:09 pts/1 00:00:00 grep --color=auto uwsgi (supervisor) [root@web-node ~]# tmux lsbobo1_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.shKilled (supervisor) [root@web-node ~]# ps -ef|grep uwsgiroot 32689 10184 0 11:09 pts/1 00:00:00 grep --color=auto uwsgi (supervisor) [root@web-node ~]# tmux lsfailed 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 supervisordroot 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/APPServerwsgi-file = django_auth_example/wsgi.pystatic-map = '/static=static'master = trueprocesses = 2enable-threads = true (supervisor) [root@web-node conf]# vim uwsgi2.ini[uwsgi]socket = :8002 chdir = /data/www/APPServerwsgi-file = django_auth_example/wsgi.pystatic-map = '/static=static'master = trueprocesses = 2enable-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.inidirectory=/usr/local/nginx/conf/startsecs=0stopwaitsecs=0autostart=trueautorestart=true (supervisor) [root@web-node supervisor]# vim bobo1.conf[program:bobo1]command=/usr/local/python3/bin/uwsgi /usr/local/nginx/conf/uwsgi2.inidirectory=/usr/local/nginx/conf/startsecs=0stopwaitsecs=0autostart=trueautorestart=true 重启supervisor(supervisor) [root@web-node supervisor]# ps aux | grep supervisordroot 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 supervisordroot 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.confroot 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.iniDec 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:8001COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEuwsgi 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:8002COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEuwsgi 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 bobobobo: stoppedbobo: started (supervisor) [root@web-node supervisor]# supervisorctl -c /etc/supervisord.conf restart bobo1bobo1: stoppedbobo1: started======================================================== 上面在nginx中vhosts/ng.conf文件中配置的转发关系不用修改.需要知道的事: 此时django项目中的的静态资源并不是通过uwsgi获取, 而是通过nginx直接获取的(匹配static的path路径访问静态资源) 此时输入http://www.kevin.com, 即可访问django的web项目! 最后退出supervisor环境(supervisor) [root@web-node supervisor]# source deactivatepyenv-virtualenv: deactivate 2.7.13/envs/supervisor[root@web-node supervisor]# 退出supervisor环境后, uwsgi守护进程并没有受到影响。 再次进入supervisor环境[root@web-node supervisor]# source activate supervisorpyenv-virtualenv: activate supervisorpyenv-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]# |
浙公网安备 33010602011771号