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 单/多线程分析(五)

相关推荐
成为你的宁宁1 小时前
【Jenkins 参数化构建实战指南:基于机器环境与插件配置,详解 tag 标签管理、commit 修订号应用、版本切换及回退全流程】
git·gitlab·jenkins·参数化构建
漫漫求13 小时前
ubuntu22.04 安装报错:grub-install/dev/sda 解决方案
ubuntu
00后程序员张15 小时前
HTTPS Everywhere 时代的抓包挑战,从加密流量解析到底层数据流捕获的全流程方案
网络协议·http·ios·小程序·https·uni-app·iphone
dodod201217 小时前
Ubuntu 24.04 LTS 使用清华大学的 Ubuntu 镜像源以加速下载和更新操作
linux·运维·ubuntu
Yeliang Wu21 小时前
LLaMA-Factory 模型评估理论与实战:基于 Ubuntu 22.04 的系统化指南
linux·ubuntu·llama·评估·llamafactory
阿巴~阿巴~1 天前
解锁HTTP方法奥秘:GET与POST的深度探索与实战演示
服务器·网络·网络协议·http·get·post·请求方法
wan_da_ren1 天前
Windows 环境下使用 Go Modules 拉取带外层 Basic Auth 的私有 GitLab 仓库 — 完整解决方案
windows·golang·gitlab
Eric.Lee20211 天前
ubuntu系统在bashrc文件中对conda进行启用设置
linux·运维·python·ubuntu·conda
咕咕嘎嘎10241 天前
应用层协议HTTP
网络·网络协议·http