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

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

背景

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

分析了 Python http.server 模块默认启用的是多线程模型,并对单线程启动做了测试,下面继续

Python http.server 单/多线程分析

首先是之前 blog 提到,启动了 slow_server.py 之后,在终端输入

bash 复制代码
time curl http://localhost:2027/a

去查询该 Web 服务的响应时间如下

可以看到需要 10s 的时间 Web 服务才能响应,这和 SlowHandler 里面定义的 10s 休眠时间是一样的

这里的一个小技巧是,访问 \a 这样一个不存在的页面,只返回一个 404 错误码,不然 curl 返回的内容可就太多了

然后再接着做一个测试,在输入 time curl http://localhost:2027/a 的同时,在另一个终端再输入 time curl http://localhost:2027/b,模拟并发访问的情况

可以看到,访问 \a 页面的等待时间依旧是 10s(因为是先点开访问的)

而后点开访问 \b 页面的等待时间则来到了 18s(不是 10s)

这就足以说明,\a 页面访问的处理,阻塞了 \b 页面访问的处理,这就是上篇 blog 里提到的 HTTPServer 继承了 TCPServer 默认的单线程同步处理能力

再来看下,如果是多线程启动,修改 slow_handler.py 如下

python 复制代码
#!/usr/bin/env python3

from http.server import ThreadingHTTPServer, SimpleHTTPRequestHandler
import time

class SlowHandler(SimpleHTTPRequestHandler):
    def do_GET(self):
        print(f"Handling {self.path} ... (will sleep 10s)")
        time.sleep(10)  # 模拟耗时操作
        """Serve a GET request."""
        f = self.send_head()
        if f:
            try:
                self.copyfile(f, self.wfile)
            finally:
                f.close()

server = ThreadingHTTPServer(('localhost', 2028), SlowHandler)
server.serve_forever()

其实就是把 HTTPServer 给换成 ThreadingHTTPServer,然后端口换一下

其他地方不变,再次运行 slow_handler.py,然后在两个终端分别输入 time curl http://localhost:2028/a 和 time curl http://localhost:2028/b 同时访问两个页面

可以看到,访问 \a 页面的时间是 10s(先访问)

而访问 \b 页面的时间也同样是 10s(后访问)

可以看到,在多线程下,出现并发操作同时访问,两者的时间基本一致,因为访问 \b 页面时会新开一个线程进行处理,而不用等待 \a 页面访问结束

OK,再说一个有意思的点,上篇 blog 里提到,当前的 Python 版本为 v3.12.3,此时默认的是启动多线程 Web 访问,http.server 作为 Python 里的标准库模块,其源码在 CPython 仓库中

GitHub 地址:https://github.com/python/cpython/blob/main/Lib/http/server.py

国内访问 GitHub 比较慢,可以参考下 Gitee 的同步镜像仓库(Gitee 官方维护,自动同步 GitHub 仓库的镜像,更新及时,可信度高 )

Gitee 地址:https://gitee.com/mirrors/cpython/

点击标签

找到 v3.6.15 版本(21年9月),这是 v3.6 的最后一个版本

可以看到这个时候,http.server 模块默认启动的,还是单线程 Web 服务

而到了 v3.7.0 版本时(v3.7 的第一个版本)

http.server 模块被改成了默认多线程启动

所以 python -m http.server 在 Python < v3.7 时无法并发处理请求,只有等一个请求处理完,才能轮到下一个,所以只要有一个请求慢(比如大文件下载、time.sleep),整个服务器对外表现就是卡住了,用户体验不好,所以这里 Python 3.7 是一个分水岭,官方为了提升开发体验,把命令行服务器升级为多线程


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

相关推荐
卸任3 小时前
Vibe coding工具使用心得
前端·ai编程
brien94 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance4 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M4 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写4 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李4 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易4 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马5 小时前
前沿视界
前端
kyriewen5 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员
陈随易5 小时前
3000 万人在用的翻译插件,重写一遍就是一门生意
前端·后端·程序员