尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

深入解析:49、【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 单/多线程分析(一)

深入解析:49、【Ubuntu】【Gitlab】拉出内网 Web 服务:http.server 单/多线程分析(一)
📅 发布时间:2026/6/20 2:22:40

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

背景

上篇 blog
【Ubuntu】【Gitlab】拉出内网 Web 服务:Nginx 事件驱动分析(二)
分析了 Nginx 的高性能设计,多进程模型,配合事件驱动 + 非阻塞 I/O + epoll(Linux),下面继续

Python http.server 单/多线程分析

分析完了 Nginx 的高性能模型,下面再对比下之前的 Python http.server 模型

首先,在分析多线程模型之前,有个比较有意思的点,首先终端输入

python3 --version

可以看到本地版本号是 v3.12.3
在这里插入图片描述
然后查看 http/server.py 实现如下

# ... 前面省略
def test(HandlerClass=BaseHTTPRequestHandler,
ServerClass=ThreadingHTTPServer,
protocol="HTTP/1.0", port=8000, bind=None):
"""Test the HTTP request handler class.
This runs an HTTP server on port 8000 (or the port argument).
"""
ServerClass.address_family, addr = _get_best_family(bind, port)
HandlerClass.protocol_version = protocol
with ServerClass(addr, HandlerClass) as httpd:
host, port = httpd.socket.getsockname()[:2]
url_host = f'[{host}]' if ':' in host else host
print(
f"Serving HTTP on {host} port {port} "
f"(http://{url_host}:{port}/) ..."
)
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\nKeyboard interrupt received, exiting.")
sys.exit(0)
if __name__ == '__main__':
import argparse
import contextlib
parser = argparse.ArgumentParser()
parser.add_argument('--cgi', action='store_true',
help='run as CGI server')
parser.add_argument('-b', '--bind', metavar='ADDRESS',
help='bind to this address '
'(default: all interfaces)')
parser.add_argument('-d', '--directory', default=os.getcwd(),
help='serve this directory '
'(default: current directory)')
parser.add_argument('-p', '--protocol', metavar='VERSION',
default='HTTP/1.0',
help='conform to this HTTP version '
'(default: %(default)s)')
parser.add_argument('port', default=8000, type=int, nargs='?',
help='bind to this port '
'(default: %(default)s)')
args = parser.parse_args()
if args.cgi:
handler_class = CGIHTTPRequestHandler
else:
handler_class = SimpleHTTPRequestHandler
# ensure dual-stack is not disabled; ref #38907
class DualStackServer(ThreadingHTTPServer):
def server_bind(self):
# suppress exception when protocol is IPv4
with contextlib.suppress(Exception):
self.socket.setsockopt(
socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
return super().server_bind()
def finish_request(self, request, client_address):
self.RequestHandlerClass(request, client_address, self,
directory=args.directory)
test(
HandlerClass=handler_class,
ServerClass=DualStackServer,
port=args.port,
bind=args.bind,
protocol=args.protocol,
)

可以看到这里默认启用的是多线程模型

在这里插入图片描述
这里要先解释先 http.server 的单线程和多线程模式,首先说单线程模式,单线程的处理类如下
在这里插入图片描述

可以看到,HTTPServer 是 socketserver.TCPServer 的子类,HTTPServer 继承的是 TCPServer 单线程同步处理的默认行为,其执行流程如下:

  • Python http.server 启动一个单线程/进程
  • 接收一个客户端连接(accept 方法阻塞接收)
  • 调用 handle 方法处理这个请求(比如读文件,返回 HTTP 响应)
  • 这个请求需要完全处理完,连接关闭后,才能处理下一个请求

这里单线程执行的逻辑点在于,第二个请求必须等第一个请求结束才能被处理,无法并发,下面来测试验证一下这个单线程阻塞行为

首先,在 index.html 目录下新建一个 slow_server.py 启动文件,用来模拟低速处理服务器,slow_server.py 的内容如下

#!/usr/bin/env python3
from http.server import HTTPServer, 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 = HTTPServer(('localhost', 2027), SlowHandler)
server.serve_forever()

这里解释下里面几个点

  • 首先是 SlowHandler 是继承了 http.server 模块里面的静态处理类 SimpleHTTPRequestHandler,SlowHandler 就是准备模拟的低速服务器
  • 然后这里 SlowHandler 重写了下 SimpleHTTPRequestHandler 里面的 do_Get 方法,注意,这里重写的 do_Get 方法几乎就是拷贝的 SimpleHTTPRequestHandler 里面的 do_Get 方法,唯一不同的,就是加了两行,一行是 print 打印,另一行是 time.sleep 延时操作,相当于收到请求后,延时 10s 再处理
    在这里插入图片描述
  • 然后最后是用 HTTPServer 启动该服务,该 Web 服务可以通过 2027 端口进行访问,注意,这里必须是 HTTPServer,因为 HTTPServer 是单线程,现在就是要测试验证单线程的阻塞行为

OK,用 chmod 777 给 slow_server.py 赋予执行权限,然后在该目录(index.html 同级目录)目录下执行 ./slow_server.py 启动这个模拟低速 Web 服务

然后终端输入

time curl http://localhost:2027/a

可以测试这个 Web 服务的连接时间

终端输入 man time,查看到该命令的描述如下
在这里插入图片描述
可以看到,time 命令是一个测量程序运行时资源消耗的命令(不仅仅是测量时间,虽然名字叫 time),比如花了多少 CPU 时间,实际耗时,内存使用等,但这个属于 GNU time,需要用 /usr/bin/time 命令(和上面的不是同一个命令,虽然都叫 time),关于 GNU time 就不展开分析了

直接在终端输入 time 命令的话(上面用的),只能测量时间如下
在这里插入图片描述


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

相关新闻

  • ZGC分代模式揭秘:如何实现亚毫秒级停顿与高效内存管理
  • 微PE官网同源技术社区推荐:AI语音新星VoxCPM-1.5-TTS-WEB-UI发布
  • GitHub镜像网站同步更新:VoxCPM-1.5-TTS-WEB-UI开源语音模型上线

最新新闻

  • 2026西安2026正规漏水检测维修公司精选口碑榜TOP5权威推荐-精准定位检测漏水点-专业防水补漏堵漏维修、卫生间/厨房/屋顶/天沟/地下室/阳台防水漏水检测维修 - 安佳防水
  • 微信聊天记录永久保存终极指南:如何让珍贵对话永不丢失
  • MC9S12XE GPIO深度解析:从寄存器配置到中断实战
  • 2026襄阳2026正规漏水检测维修公司精选口碑榜TOP5权威推荐-精准定位检测漏水点-专业防水补漏堵漏维修、卫生间/厨房/屋顶/天沟/地下室/阳台防水漏水检测维修 - 安佳防水
  • 5步掌握FitGirl游戏启动器:高效管理压缩游戏的终极工具
  • 2026年西安评价高的玻璃门生产厂家哪家强 - 品牌鉴赏官2026

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号