初学 django,django 默认能否并发? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
lanqing
V2EX    Python

初学 django,django 默认能否并发?

  •  
  •   lanqing 2018-11-21 14:44:24 +08:00 11763 次点击
    这是一个创建于 2547 天前的主题,其中的信息可能已经有所发展或是发生改变。

    urls.py

     re_path(r'ceshi_uwsgi',view=views.test), re_path(r'ceshi_uwsgi2',view=views.test), 

    views.py

    def test(request): time.sleep(5) return HttpResponse('ok') def test2(request): time.sleep(5) return HttpResponse('ok') 

    启动方式

    python manage.py runserver 0:8002 

    例 1:当我快速在浏览器两个窗口分别输入

    http://localhost:8002/publisher/ceshi_uwsgi http://localhost:8002/publisher/ceshi_uwsgi 

    给我的反应是一个窗口请求 5 秒执行完后再执行另外一个窗口请求,总共 10 秒

    例 2:当我快速在浏览器两个窗口分别输入

    http://localhost:8002/publisher/ceshi_uwsgi http://127.0.0.1:8002/publisher/ceshi_uwsgi 

    给我的反应是基本上是同时执行 请求总共 5 秒中

    我所理解的并发是 django 一个单线程的程序,一个请求没有结束是不能开始第二个请求(换句话就是不能并发),我后来给 django 配置了 uwsgi 服务器,结果还是像上述一样,我不太理解为什么会出现上面这种情况,希望大佬可以指点一二,感谢

    第 1 条附言    2018-11-22 10:17:23 +08:00

    非常感谢各位的回复!

    有个朋友的回答,我觉得回答的挺好的,就是那个11111111的朋友..

    我查了一下官方文档

    (django==2.1) --nothreading Disables use of threading in the development server. The server is multithreaded by default. 

    django默认是多线程的,应该是支持并发,只不过没有uwsgi+nginx支持的好而已

    还有google浏览器第一个访问没进去,第二个是不会响应的(我没仔细测试,但是应该是对的..)

    非常感谢

    26 条回复    2018-12-05 14:43:30 +08:00
    lanqing
        1
    lanqing  
    OP
       2018-11-21 14:45:52 +08:00
    我希望在两个请求基本上同时发生的情况下,同时结束(能够并发),怎么实现它
    Acebiu
        2
    Acebiu  
       2018-11-21 14:54:48 +08:00 via Android
    请使用专业的工具测试,比如 ab,Chrome 访问两个相同的地址,会在一个加载完毕后再加载另外一个。
    scriptB0y
        3
    scriptB0y  
       2018-11-21 14:55:20 +08:00
    你 uwsgi 配置多个进程多个线程,就支持并发了,默认单进程单线程跑应该还是没并发的。
    Neojoke
        4
    Neojoke  
       2018-11-21 15:42:00 +08:00
    Python 是有个全局锁,所以 Python 的应用一般是多进程部署,要想彻底搞明白这个问题,先搞定 Python 的全局锁,是什么,然后在研究一下 Django 的 python 启动模式,去官方文档里找 uwsgi 服务器的配置说明,启动完成以后,检查一下进程中是否有多个 uwsgi 进程,如果有,则是多进程启动
    SmartKeyerror
        5
    SmartKeyerror  
       2018-11-21 19:25:28 +08:00
    首先要分清 Web Server 和 Web Application 之间的区别:Web Server 可以使用多线程多线程或者是 Reactor 模型来支持并发, 前者可以支持并行, 后者因为 GIL 的原因, 只能支持并发。 而 Web Application 仅仅只是一个应用而已, 当你使用 runserver 来启动 Django 时, 其实是启动了 Django 为开发者所提供的测试 Server 而已, 并不支持并发, 请求为串行执行。 至于在配置了 uwsgi Web Server 之后还是不支持并发, 尝试将 process 配置为 CPU 核心数
    Nick2VIPUser
        6
    Nick2VIPUser  
       2018-11-21 21:19:59 +08:00   1
    生产上可以用 uwsgi+nginx
    lfzyx
        7
    lfzyx  
       2018-11-21 21:26:27 +08:00   4
    上面动不动就说 GIL 全局锁的是不是有毛病?你家网站是 CPU 密集型的?
    FullBridgeRect
        8
    FullBridgeRect  
       2018-11-21 21:53:45 +08:00 via Android
    django 自带那个是调试用的,虽然是串行,但正常人是不会将他放到生产环境的。你要并行的 uwsgi 非阻塞模式 /gunicorn 异步引擎了解一下
    laike9m
        9
    laike9m  
       2018-11-21 21:56:57 +08:00
    @Neojoke 和 GIL 基本没关系
    ltoddy
        10
    ltoddy  
       2018-11-21 21:57:17 +08:00
    网络请求本身就是异步的.
    111111111111
        11
    111111111111  
       2018-11-21 22:00:22 +08:00 via Android
    楼上的不观察细节吗。两次请求的域名不一样就并发…一样就串行

    Chrome 有这个毛病,同样的 URL 并发请求,如果第一无响应第二个根本不发出去

    另外建议楼主在视图函数的开始和结束时分别打带时间的 Log,这才是 debug 应有的态度
    111111111111
        12
    111111111111  
       2018-11-21 22:01:24 +08:00 via Android
    @FullBridgeRect django 的 runserver 是多线程的
    111111111111
        13
    111111111111  
       2018-11-21 22:13:14 +08:00 via Android
    django 文档里明确说明了 runserver 是多线程,如果想要单线程需要加参数--nothreading 为啥各位大佬都说串行……
    ericls
        14
    ericls  
       2018-11-22 00:10:49 +08:00
    wsgi 并发要借助 thread 和 multi-process
    FullBridgeRect
        15
    FullBridgeRect  
       2018-11-22 01:24:26 +08:00 via Android
    @111111111111 是吗平时都没留意,很多 wsgi 服务器都说要特定的引擎才能实现非阻塞,就把他套在了 runserver 上面了
    Trim21
        16
    Trim21  
       2018-11-22 01:53:34 +08:00 via Android
    这个是 chrome 的问题,对同一个 url 只会在第一个请求结束之后才开始第二个请求。
    Neojoke
        17
    Neojoke  
       2018-11-22 09:02:35 +08:00
    @111111111111 Python 的多线程基本上是伪并行,可以了解一下 GIL 全局锁,就明白了,Python 的应用即便是使用了多线程,但基本上没办法处理高并发,所以一般高并发配合的必须是多进程,或者采用协程,但协程是开弓没有回头箭,一开始是协程,就要任何代码都是协程,否则性能很难保证
    petelin
        18
    petelin  
       2018-11-22 09:29:53 +08:00 via iPhone
    @Neojoke 没法高并发是因为 python 慢,可不是因为什么全局锁。你在学习一下并发和并行的区别就明白了
    hljjhb
        19
    hljjhb  
       2018-11-22 09:51:07 +08:00 via Android
    既视感 两三年前有个如出一辙的帖子
    111111111111
        20
    111111111111  
       2018-11-22 11:00:06 +08:00 via Android
    @Neojoke

    In CPython, due to the Global Interpreter Lock,.....
    However, threading is still an appropriate model if you want to run multiple I/O-bound tasks simultaneously.
    petelin
        21
    petelin  
       2018-11-22 17:40:33 +08:00
    @Neojoke 另外 Python 的多线程是真的多线程, 只是有一把锁而已, 执行 Python 代码的时候要先拿到这把锁. 但是调用系统库那可是真的并行在跑
    Neojoke
        22
    Neojoke  
       2018-11-22 18:11:24 +08:00
    @petelin
    我觉得吧,您让我学习一下的建议,我会接受的,但您是否考虑一下我的建议?
    1. 翻翻 Python 解释器的源码,找找 CPython 的全局锁的实现代码。
    这里给您奉上:
    https://github.com/python/cpython/blob/e62a694fee53ba7fc16d6afbaa53b373c878f300/Python/ceval.c#L238
    2. 考虑一下解释器作为共享资源,被全局锁保护以后,多线程代码在执行的时候,是否会被同步,在临界代码执行以后,才会被释放
    3. 再思考一下,在什么特殊的情况下,会主动让出全局锁
    4. PyThread_type_lock 这个看一下结构体,然后呢,自己做个试验,在多线程的情况下,模拟并发耗时操作,不断调高线程数,看一下总耗时是否和线程数的增加成正相关
    5. 人家说的 Django,里面基本上是 Python 代码,几乎没有 C 的扩展调用,系统库也不都是用 C 实现的,C 实现的 io 操作是使用操作系统本身的线程、进程以及信号量来处理的。
    Neojoke
        23
    Neojoke  
       2018-11-22 18:32:20 +08:00
    楼主,没有人会使用 Django 默认的 runserver 进行生产部署的,并且官方文档也非常不推荐在生产环境使用 runserver 进行部署,原因就是 Python 虽然可以多线程,但是因为 CIL 的存在,导致其并发效率非常低,至于为什么很低,我前面已经把关键点罗列了一下。
    生产环境部署 Python 的 Web 应用,有两种方式,一种是 uwsgi 使用多进程,多开 work,进行部署,一种是使用 gevent 协程实现非阻塞异步 I/O,但是我前面说了,这种要求,其他的代码也必须是非阻塞的编程模型。跟 nodejs 一样。
    @111111111111 说的 runserver 是多线程的没有什么问题,能解决您的测试疑惑,但这里面最本质的还是要考虑,CIL 到底对并发有多大影响,GIL 一直起作用的时候,线程需要不断等待获取 GIL,线程被同步,但 I/O 操作的时候,Python 代码是会让出全局锁的,所以,多线程是有效的,可以考虑使用,但前提这是非阻塞的 I/O,也就说,C 底层提供的 I/O 功能,或者用 C 实现的非阻塞 I/O 功能,uwsgi 虽然是 C 写的,但不是非阻塞的,可以查看一下 C 的源码,如果不设置多个 work,就不能处理高并发,可以压测一下。试试
    petelin
        24
    petelin  
       2018-11-22 18:58:42 +08:00 via iPhone
    @Neojoke 你这不也承认多线程是有用的吗,还有什么好抬杠的。网站就是一个网络数据的处理,c 单线程估计也能完爆多线程的 python,python 的协程估计比多线程还强,这里面的思想不就是让 CPU 一直跑着去 handle 数据?数据流动比 CPU 处理速度慢多了
    Neojoke
        25
    Neojoke  
       2018-11-22 21:18:36 +08:00 via iPhone
    @petelin
    前提都看不懂么?在非阻塞的情况下多线程能处理并发,阻塞代码基本上多线程没用
    什么 C 单线程完爆 Python 多线程,还估计,说的是 C 的非阻塞 IO 代码能交还 GIL,不会引起 Python 多线程的同步等待,这也是 Python 伪并发的原因
    这里的思想是 CPU 跑着 handle 数据?想表达什么?
    数据流动比 CPU 处理速度快?数据流动是什么?
    YuanGu333
        26
    YuanGu333  
       2018-12-05 14:43:30 +08:00
    有大佬开多一个贴再说明说明吗?
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1233 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 17:47 PVG 01:47 LAX 09:47 JFK 12:47
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86