52、【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 单/多线程分析(四)

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

上篇 blog
【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 单/多线程分析(三)

分析了 Python http.server 在多线程下并发处理 TCP 网络请求的极限,下面继续

Python http.server 单/多线程分析

OK,前面都是从线程的角度,分析 Python http.server 模块不能支持高并发,下面再补充下,从进程的角度看这个事情

首先,Python 是一个解释型语言,当在终端输入

bash 复制代码
python3 -m http.server 2025

这样一个命令尝试运行 Python 程序时,操作系统会为这个程序创建一个进程 ,这个进程将使用 CPython(Python 解释器,前面的 C 表示解释器是用 C 语言写的 ) 来把 *.py 文件编译成字节码并执行

然后这里关键点来了,运行 Python 命令时,操作系统启动一个新进程,相当于一个 Python 程序等于一个进程,在这个进程中,可以有多个线程,但这些线程之间会受到 GIL (全称 Global Interpreter Lock,全局解释器锁)的限制

比如运行完 python3 -m http.server 2025 之后,在终端输入

bash 复制代码
ps aux | grep http.server

可以看到 Python 启动的 Web 服务进程,这个进程使用了 2025 端口对外提供服务,对进程来说,进程是操作系统分配资源的基本单位,正常情况下,一个带有多线程的进程可以同时使用多个 CPU 核心,达到并行执行的效果

但对于 Python 程序而言,CPython 解释器在工作时,需要在 GIL(全局解释器锁)机制下才能正常运行,GIL 会确保同一时刻,只有一个线程能够执行 Python 字节码,所以,即使机器是多核的,在一个 Python 进程内,http.server 即使开了多线程,在执行纯 Python 代码时,也只能轮流使用 1 个 CPU 核心,无法真正并行

GIL 的工作流程大致如下:

  • 整个 CPython 进程只有一把 GIL 锁
  • 任何线程想执行 Python 字节码必须先获取 GIL 锁
  • 如果 GIL 锁被其他线程占着,那么当前线程只能等待

所以即使有 16 个线程,16 个 CPU 核心,同一时刻也只有 1 个线程在跑 Python 代码,因为整个 CPython 进程只有一把 GIL 锁,这就好比一个厨房(Python 进程)里,有 16 个厨师(线程),但只有一把菜刀(GIL 锁),谁想切菜(执行 Python 代码),必须拿到菜刀,这个厨师在切菜的时候,其他厨师就只能干站着等(因为没菜刀了),再多厨师也快不起来

Python 官方(https://docs.python.org/3/library/threading.html)对这块儿的描述如下

OK,下面再分析下多线程的并发行为,之前 blog 【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 单/多线程分析(二) 说过,开启多线程后,两个 Web 请求等待的时间基本是相同的,因为当线程执行 IO 操作,比如 time.sleep()socket.recv()file.read()时,线程会主动释放 GIL 锁 ,因为这些 IO 操作是耗时的,操作系统要去处理磁盘,或者网络任务,在这段时间 Python 解释器就可以闲下来不干活,也就没必要一直占着 GIL 锁,此时该 Python 进程内的其他线程就可以趁机获取 GIL,去执行自己的 Python 代码

所以 Python 的多线程是否有用,得分情况

  • 对于 IO 密集型任务(比如 Web 服务器):多线程是有效的,因为大部分时间在等 IO
  • 对于 CPU 密集型任务(比如循环计算,图像处理等):多线程就没有用了,因为要一直抢 GIL 锁

OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog
【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 单/多线程分析(五)

相关推荐
不可能的是15 小时前
前端 SSE 流式请求三种实现方案全解析
前端·http
欧云服务器4 天前
怎么让脚本命令可以同时在centos、debian、ubuntu执行?
ubuntu·centos·debian
智渊AI4 天前
Ubuntu 20.04/22.04 下通过 NVM 安装 Node.js 22(LTS 稳定版)
ubuntu·node.js·vim
古译汉书4 天前
【IoT死磕系列】Day 7:只传8字节怎么控机械臂?学习工业控制 CANopen 的“对象字典”(附企业级源码)
数据结构·stm32·物联网·http
The️5 天前
Linux驱动开发之Read_Write函数
linux·运维·服务器·驱动开发·ubuntu·交互
再战300年5 天前
Samba在ubuntu上安装部署
linux·运维·ubuntu
qwfys2005 天前
How to install golang 1.26.0 to Ubuntu 24.04
ubuntu·golang·install
木尧大兄弟5 天前
Ubuntu 系统安装 OpenClaw 并接入飞书记录
linux·ubuntu·飞书·openclaw
小虾爬滑丫爬5 天前
ubuntu上设置Tomcat 开机启动
ubuntu·tomcat·开机启动
老师用之于民5 天前
【DAY25】线程与进程通信:共享内存、同步机制及实现方案
linux·c语言·ubuntu·visual studio code