接手了一个 python django 写的上古项目。今天稍稍改了改,部署上线的时候突然看到启动命令竟然写的是python manage.py runserver
虽然我从来没写过 django 项目,但是我也知道这命令启动的是开发测试服务器。就跟前端的npm run dev
一样。此时我内心”这特么怎么行,线上业务啊,怎么能这么敷衍,跑个测试服务器就上线“。于是想着改改 Dockerfile ,改成正经的线上部署。
可是我也没搞过 django 啊,经过一通搜索,大致了解到,django 可以通过 Gunicon 、uWSGI 、Apache mod_wsgi 、Daphne 、Hypercom 、Uvicom 等等方式部署。我淦,怎么这么多啊,我也不知道选哪个啊,uWSGI 在官网写在第一个的,那就他吧。
照着官网示例抄吧,先这样再那样,Dockerfile 改好了,试一试,草,Docker 容器怎么启动就停了?一通排查,原来 uwsgi --ini uwsgi.ini
这命令不是前台运行的,Dockerfile 里面拿这个当启动命令起来立马就没了。
经过 N 久翻阅文档,发现 uwsgi 启动会生成一个 pid 文件,看到这里,我这个大聪明有办法了,于是 Dockerfile 启动命令改成CMD uwsgi --ini uwsgi.ini && tail -f uwsgi.pid
,再次尝试,容器成功保活。
正在得意我的聪明才智的时候,结果一看,我淦,uwsgi 是起来了,但是服务为啥不能用啊。又一通排查,我淦,uwsgi.ini 里面的路径好像有问题,可这玩意路径写到哪里文档也没说啊,网上一会说是项目路径,一会说是 app 路径,什么鬼啊,一个一个尝试,结果都特么不行。
再仔细翻翻文档,这什么玩意呀,部署上线什么还要带个 sqllite 文件呀,怎么还有先执行命令整理代码啊,怎么还要。。。。。
从早上 10 点一直捣鼓到现在晚上 8 点,饭都没吃饱,这什么破玩意啊。md 果断敲下 git reset -hard
。滚 tm 的,我真是吃饱了没事干,服务跑得好好的,改什么改,前人用开发服务器肯定是有他的道理的,瞎改什么改。就算服务挂了,Docker 容器自动拉起,有毛线关系啊。
不得不感叹,我部署过上古时期的 java 项目,拷个 war 包上线。也部署过 php 项目,拷份代码到目录就上线,也部署过 golang 项目,本地交叉编译拷个二进制文件上线,也部署过 c c++项目... 像 python 这么恶心的还是第一次,什么乱七八糟路径,调试又没日志,找到日志又不清不楚的,没人用这玩意果然是有原因的。
1
yakun4566 2023-12-12 20:37:55 +08:00
python *.py 还好吧,我们线上项目 Java 也是 java -jar 啊(也有可能是我们水分太大
|
2
volvo007 2023-12-12 23:09:16 +08:00
op 好惨,上来选了个最“基础” 的…… 选 gunicorn 可破,但是,光选中间件也不行啊,你还没部署 nginx 反向代理呢 (狗头
|
3
shimada666 2023-12-13 00:31:57 +08:00 2
搞那么麻烦干嘛,直接 python manage.py runserver 就好了。
等 qps 过 20 再考虑别的吧 |
4
arischow 2023-12-13 08:43:24 +08:00 via iPhone 7
你接手的代码烂,你也菜😄
|
5
llsquaer 2023-12-13 09:30:07 +08:00
写的 api 接口,直接 python manage.py runserver 没毛病。。工作期间 8 小时内 平均 QPS 80 左右至今没问题。内部使用。
不过 python web 是略显复杂。主要就几个容器的区别。熟悉一个当万金油用 |
6
sadfQED2 OP @shimada666 线上大几十台机器,你说 qps 过 20 不
@llsquaer 直接 runserver 区别大吗?是一个 ai 模型,为了提供 api 调用,就 django 包了一层,整个项目就一个接口,代码不超过 100 行 |
7
ihmily 2023-12-13 09:58:44 +08:00
项目就一个接口,直接使用 fastapi 就好了
|
8
JiaNa 2023-12-13 10:02:41 +08:00 via iPhone
@sadfQED2 既然你说了是旧项目,如果之前没有出现性能问题,那么没有性能问题。
如果你愿意折腾、学东西,模拟生产环境 API 进行压测,比较不同方式的性能区别。 |
9
shimada666 2023-12-13 10:08:50 +08:00
@sadfQED2 完全没问题,容器挂个 restart=always ,崩了还能重新启动
|
10
sadfQED2 OP @JiaNa 线上服务,不能随便压。我也不是专业运维,也不是专业的 python 开发。但是就我的理解,直接 python runserver 这应该是单进程运行的,就 python 来说这应该完全没办法充分利用 cpu 。
但是这个项目本质上是调用 PyTorch ,PyTorch 底层又是调用 C++模块,C++模块是不是就能不受限于 Pyton 的单进程直接跑满 CPU 了我也不清楚。 所以到底能不能充分利用 cpu 我也搞不清楚。 |
11
sadfQED2 OP @shimada666 #9 现在容器就是 restart=always ,然后上层网关配置了故障转移。某次请求失败会自动转到其他机房的容器上。但是想着 python runserver 还监听代码变化,随时重启,心里就觉得不舒服
|
12
RedisMasterNode 2023-12-13 10:16:35 +08:00
感觉不是语言的问题。不太理解,这些东西不是在 README 里面写好就行了吗?
https://images2.imgbox.com/91/09/qF1P6Xv1_o.png 这是自己写的古老的新人项目,入职第一周做的,要怎么运行写好就是了,python 也是一样的。 所以骂 python 没用,python 也有一样轻轻松松启动的项目,要怪就怪你这个同事。我运行 java 项目也摸索了很久不知道要怎么启动,c++ 也是各种依赖问题,说白了就是还菜(没有贬义,每个人都有新学东西的时候),还没入门,接手了不熟悉的语言就要运行要调试了,心态放好点都不至于这样。 |
13
chenqh 2023-12-13 10:18:52 +08:00
因为 python 有 gil,所以 djanog runserver 就可以了啊,gunicorn 用进程模型的话,就相当于 master 负责起多个进程
|
14
chenqh 2023-12-13 10:20:31 +08:00
python 像 tornado 想要利用多核,就是 supervisor 起多个进程,模型更简单粗暴
|
15
wizardyhnr 2023-12-13 10:30:10 +08:00
uwsgi+nginx+django 部署本来就是配置多个服务,这种多进程通信 debug 就很难了。楼主还选 docker 容器,docker 推荐一个容器一个服务,一个容器部署多个服务可能很多坑。楼主属于踩坑体质吧?
|
16
msg7086 2023-12-13 10:42:02 +08:00
下次你试试看部署一下那种 2000 年前后写的带汇编的 C 项目到现代的平台。才折腾一天叫什么复杂。
光是把内嵌的 MMX 和 3dnow!汇编全部重写成 SSE/AVX 就得花掉你几星期(笑) |
17
biaodianfu 2023-12-13 11:36:41 +08:00 1
Django 没接触,不知道怎么部署还情有可原,Linux 命令也不熟悉,才得意自己的聪明才智,即使不知道使用 supervisor 守护进程,也应该知道使用 nohup 命令让程序不挂起。
|
18
wenrouxiaozhu 2023-12-13 11:42:16 +08:00
@sadfQED2 用 Gunicon 吧👀...觉得“runserver 监听代码变化,随时重启,心里就觉得不舒服” ,可以后面加一个--noreload 😂
|
19
elboble 2023-12-13 13:42:07 +08:00
是略烦,反正 supervisor+uwsgi+nginx+django ,搞过一次就行了,路径什么的,的确文档说的不清楚,每次都是对着原来的例子改的。
|
20
dayeye2006199 2023-12-13 13:53:23 +08:00
chatgpt 糊个 dockerfile 很快的
|
21
tfdetang 2023-12-13 14:10:13 +08:00
@sadfQED2 ai 模型直接 runserver 会阻塞吧,并发请求还是会有问题的;
如果这种场景最好还是用 fastapi ; 可以找个 uvicorn + fastapi + docker 的模板项目改改就行了; 当然现在这样也不是不能用 |
22
sadfQED2 OP @tfdetang 啊?会阻塞吗?我等会试试,现在一次推理也就十多二十毫秒,可能机器够多,负载均衡后一直没发现问题
fastapi 能简单一点?你别忽悠我,我部署这玩意已经恶心吐了,换一个等会我又几天搞不出来。主要是这破玩意还要 GPU ,然后走公司部署系统又必须要 Dockerfile ,在 docker 里面搞显卡驱动 cuda 啥的我已经吐了 |
24
nevermoreluo 2023-12-13 16:41:02 +08:00
哈哈哈哈哈 确实挺复杂的
去年闲时捡起了很多年前 python ,随便折腾也折腾了一下午 docker+uwsgi+django https://github.com/nevermoreluo/kitchen/blob/main/docker-compose.yml 祝你好运吧 |
25
chenqh 2023-12-13 18:06:18 +08:00
@sadfQED2 汗了,django 单进程,同步肯定阻塞啊,你不信,就去 sleep 看一下,就知道了,一般而已 python 要部署多个实例,
在 docker 之前就是用 supervisor 起多个进程, docker 时代应该是起多个实例 |
26
sadfQED2 OP @chenqh 我就是 sleep 测试的,sleep10 秒,同时发两个请求,两个都 10s 后正常返回
|
28
sadfQED2 OP |
29
chenqh 2023-12-13 18:59:17 +08:00 1
|
31
KJR5OR04CnCiWf02 2023-12-13 20:56:00 +08:00
楼主在做什么 ai 应用?感觉是个大怨种。
|
32
XxxxD 2023-12-13 21:19:15 +08:00
uwsgi 文档感觉好久都没更新,可以 youtube 搜下搭配 Gunicorn 部署
|
33
fantathat 2023-12-13 22:16:56 +08:00
确实复杂,用 gunicorn 涉及到 wsgi, 需要导出 application?
|
34
iorilu 2023-12-14 07:40:33 +08:00
生成环境不要设折腾, 只要能跑就不要动
|
35
IurNusRay 2023-12-14 09:46:27 +08:00
你的 uwsgi.ini 文件是不是配置了 daemonize , 这种模式 uwsgi 主进程开启子进程后会退出,于是 docker 容器也会停止,改成 logto 就可以
|
36
tfdetang 2023-12-14 09:51:42 +08:00
@sadfQED2 看来 django 默认开启了多线程; 其实 docker 里不用搞显卡驱动啥的,base 镜像直接用 torch 啥的官方 gpu 版本的镜像,后面只要把 python 的部分搞定就行了
|
37
sanzrolee 2023-12-14 09:52:24 +08:00
uvicom + supervisor 嘎嘎香,再套层 docker 容器在最外层也可以。
|
38
julyclyde 2023-12-15 19:14:34 +08:00
uwsgi 难道没有“前台运行”功能吗?
干嘛用 tail 来保活? 那你用了 tail ,将来运行 docker kill 的时候,你让 tail 命令去被 kill 么? |
39
julyclyde 2023-12-15 19:15:50 +08:00
你想要的那种“只上传应用程序本身,但是不管运行机制”其实在 python 世界也是存在的
就是 google appengine 、sina appengine 、heroku 那一类 python 、nodejs 、java 比较像,都是“由该语言本身写一个服务器”来运行自己 |
40
julyclyde 2023-12-15 19:16:25 +08:00
还有,如果你们的数据库是 sqlite ,将来可能扩容到多实例的时候会遇到问题
|
41
julyclyde 2023-12-15 19:19:47 +08:00
@sadfQED2 大几十台机器不一定过 20 啊
你知道不,东南亚某知名电子商务网站,在 99 大促销的时候,曾经有关键组件“高达四十八 QPS”,比平时翻两番呢 你 AI 模型的运行速度,浏览器能等得了么?回头估计还得加个 celery |
42
Maerd 2023-12-20 11:36:46 +08:00
比较好奇 一个接口为什么要用 django,而不是用更方便的 fastapi
|
43
Xs2y6914BljWqNfl 323 天前
@Maerd 完全看个人喜好的
|