问题说明
项目地址:musnows/encrypt2bdy
之前自己瞎写了一个上传文件到百度云的python程序,提供了docker并部署在了我自己的nas上,但是我限制容器可用内存大小为1GB后,总是会遇到docker因为内存爆满直接被系统kill了的情况。
现在总算有时间看看到底是啥问题了,其实我已经能想到了,上传文件的部分已经是按分片上传的,理论上不是那个地方的问题,另外一个打开文件的地方只有一处,就是计算文件整体md5的操作。
因为当时没想明白问题在哪里,我还在项目的README里面写了一个不建议用于备份大文件,因为内存会撑爆的提示(
| 12
 3
 4
 5
 6
 7
 
 | ### 已知错误
 #### 1.docker退出码137
 
 内存不足时,系统将对应docker容器终止。出现此问题,请确认您要备份的文件中不会出现大于您系统内存或docker容器内存限制的文件。
 
 正如开头所说,本项目适合于备份照片、图片、文档等小文件,并不建议用于备份录像、电影等资源。
 
 | 
原有代码读取md5的方式
在程序中,我计算文件整体md5的操作是这样写的
| 12
 3
 4
 5
 6
 7
 
 | with open(file_path, 'rb') as f:
 file_bytes = f.read()
 
 file_name = os.path.basename(file_path)
 file_md5_str = hashlib.md5(file_bytes).hexdigest()
 _log.debug(f"{file_path} | {file_md5_str}")
 
 | 
问题其实很明朗,就是这里的f.read()操作直接将整个文件加载到内存里面了!备份的文件稍微大一点,指定要把内存整爆的!
分片读取md5
这部分代码应该替换为如下形式,分片读取文件,并将读取的md5给update到hashlib.md5()对象中
| 12
 3
 4
 5
 6
 7
 8
 
 | def file_md5(file_path: str):"""给定一个文件路径,分片加载文件,计算文件的md5"""
 chunk_size = 4096
 with open(file_path, 'rb') as f:
 file_md5 = hashlib.md5()
 while chunk := f.read(chunk_size):
 file_md5.update(chunk)
 return file_md5.hexdigest()
 
 | 
经过测试,这种办法计算出来的md5和直接f.read()全部计算出的md5完全一致
| 12
 3
 
 | ╰─ python3.10 test.py                 ca60e24bf4dde156a381c8b9d268faf5
 ca60e24bf4dde156a381c8b9d268faf5
 
 | 
内存占用监控线程
用下面的代码弄个内存占用的监控线程,通过psutil库实时打印内存占用
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | import psutilimport os
 import threading
 import time
 
 
 def monitor_memory_usage():
 process = psutil.Process(os.getpid())
 while True:
 memory_info = process.memory_info()
 print(f"Memory used: {memory_info.rss / (1024 * 1024):.2f} MB")
 time.sleep(1)
 
 
 
 memory_monitor_thread = threading.Thread(target=monitor_memory_usage)
 memory_monitor_thread.start()
 
 
 
 
 memory_monitor_thread.join()
 
 
 | 
内存占用测试
将项目中上传到百度云的部分注释掉,休眠10秒替代上传操作,模拟原有代码整体打开一个文件,又分片打开文件上传到百度云的流程。
用两个450MB左右的视频做测试。程序原有思路是遍历需要备份目录中的所有文件,分片上传到百度云。计算整个文件的MD5的操作其实是用来本地入库标定文件是否有修改、是否已经上传的。
不过后续加密文件的操作也是无脑f.read(),这部分也需要修改。

日志输出如下,可以看到,开始处理test目录之后,程序直接把视频完整加载到了内存里面,占用内存的大小和视频文件大小基本一致。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 
 | ╰─ python3.10 main.py[23-12-17 20:01:22] INFO:confLoad.py:<module>:68 | [config] loaded config from './config/config.yml'
 [23-12-17 20:01:22] INFO:confLoad.py:<module>:89 | [config] loaded config success
 [23-12-17 20:01:22] INFO:querySql.py:<module>:72 | [sqlite3] create all tables
 [23-12-17 20:01:23] INFO:main.py:<module>:294 | [start] start at 23-12-17 20:01:23
 [23-12-17 20:01:23] INFO:encrypt.py:__init__:24 | load key file from './config/encrypt.key'
 Memory used: 39.18 MB
 [23-12-17 20:01:23] INFO:main.py:upload_task:132 | 上传任务开始:23-12-17 20:01:23
 [23-12-17 20:01:23] INFO:main.py:upload_task:139 | 开始处理路径 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test' | 文件数量 2
 [23-12-17 20:01:23] INFO:main.py:upload_task:144 | [0] 开始处理 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4'
 Memory used: 483.52 MB
 Memory used: 483.52 MB
 Memory used: 483.52 MB
 Memory used: 483.52 MB
 Memory used: 483.52 MB
 Memory used: 483.52 MB
 Memory used: 483.52 MB
 Memory used: 483.52 MB
 Memory used: 483.52 MB
 Memory used: 483.52 MB
 [23-12-17 20:01:33] INFO:main.py:upload_task:237 | [1] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4' 文件哈希:7d5735eba55a638a1290ab36e00530ca
 [23-12-17 20:01:33] INFO:main.py:upload_task:144 | [1] 开始处理 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4'
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 Memory used: 517.39 MB
 [23-12-17 20:01:44] INFO:main.py:upload_task:237 | [2] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4' 文件哈希:b7b0cd46e3ac7681a3644d9761ad3e71
 [23-12-17 20:01:44] INFO:main.py:upload_task:282 | 本次上传完毕,上传:2,跳过:0,错误:0 | 总计:2
 [23-12-17 20:01:44] INFO:main.py:upload_task:283 | 本次上传完毕,平均上传速度:43.143mb/s | 总耗时:21.16s
 [23-12-17 20:01:44] INFO:main.py:upload_task:286 | 本次上传完毕,下次处理:2023-12-17 21:00:00
 
 | 
带上加密之后更加离谱,只是第一个文件就直接把内存占用干到了3.2GB,处理第二个文件的时候,也是直接干到了2.4GB,这种程度的内存消耗谁顶得住?更何况百度云API最大支持10GB的文件上传,如果要加载一个10GB的文件还得了啊?
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 
 | ╰─ python3.10 main.py[23-12-17 19:43:56] INFO:confLoad.py:<module>:68 | [config] loaded config from './config/config.yml'
 [23-12-17 19:43:56] INFO:confLoad.py:<module>:89 | [config] loaded config success
 [23-12-17 19:43:56] INFO:querySql.py:<module>:72 | [sqlite3] create all tables
 [23-12-17 19:43:56] INFO:main.py:<module>:291 | [start] start at 23-12-17 19:43:56
 Memory used: 39.31 MB
 [23-12-17 19:43:56] INFO:encrypt.py:__init__:24 | load key file from './config/encrypt.key'
 [23-12-17 19:43:56] INFO:main.py:upload_task:132 | 上传任务开始:23-12-17 19:43:56
 [23-12-17 19:43:56] INFO:main.py:upload_task:139 | 开始处理路径 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test' | 文件数量 2
 Memory used: 923.04 MB
 Memory used: 3267.48 MB
 Memory used: 483.71 MB
 Memory used: 483.71 MB
 Memory used: 483.71 MB
 Memory used: 483.71 MB
 Memory used: 483.71 MB
 Memory used: 483.71 MB
 Memory used: 483.71 MB
 Memory used: 483.71 MB
 Memory used: 483.71 MB
 Memory used: 483.71 MB
 [23-12-17 19:44:08] INFO:main.py:upload_task:234 | [1] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4' 文件哈希:7d5735eba55a638a1290ab36e00530ca
 Memory used: 990.96 MB
 Memory used: 2410.97 MB
 Memory used: 1622.17 MB
 Memory used: 517.57 MB
 Memory used: 517.57 MB
 Memory used: 517.57 MB
 Memory used: 517.57 MB
 Memory used: 517.57 MB
 Memory used: 517.57 MB
 Memory used: 517.57 MB
 Memory used: 517.57 MB
 Memory used: 517.57 MB
 Memory used: 517.57 MB
 [23-12-17 19:44:22] INFO:main.py:upload_task:234 | [2] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4' 文件哈希:b7b0cd46e3ac7681a3644d9761ad3e71
 [23-12-17 19:44:22] INFO:main.py:upload_task:279 | 本次上传完毕,上传:2,跳过:0,错误:0 | 总计:2
 [23-12-17 19:44:22] INFO:main.py:upload_task:280 | 本次上传完毕,平均上传速度:35.371mb/s | 总耗时:25.81s
 [23-12-17 19:44:22] INFO:main.py:upload_task:283 | 本次上传完毕,下次处理:2023-12-17 21:00:00
 
 
 | 
先将md5计算的函数给修改了,改成分片计算。可以看到,效果显著!内存占用和程序刚开始运行的时候差距只有5MB,这才是正常的内存占用!
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 
 | ╰─ python3.10 main.py[23-12-17 20:03:20] INFO:confLoad.py:<module>:68 | [config] loaded config from './config/config.yml'
 [23-12-17 20:03:20] INFO:confLoad.py:<module>:89 | [config] loaded config success
 [23-12-17 20:03:20] INFO:querySql.py:<module>:72 | [sqlite3] create all tables
 [23-12-17 20:03:20] INFO:main.py:<module>:294 | [start] start at 23-12-17 20:03:20
 Memory used: 39.26 MB
 [23-12-17 20:03:20] INFO:encrypt.py:__init__:24 | load key file from './config/encrypt.key'
 [23-12-17 20:03:20] INFO:main.py:upload_task:132 | 上传任务开始:23-12-17 20:03:20
 [23-12-17 20:03:20] INFO:main.py:upload_task:139 | 开始处理路径 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test' | 文件数量 2
 [23-12-17 20:03:20] INFO:main.py:upload_task:144 | [0] 开始处理 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4'
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 [23-12-17 20:03:32] INFO:main.py:upload_task:237 | [1] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《ILLSHOWYOU》KDA阿狸.mp4' 文件哈希:7d5735eba55a638a1290ab36e00530ca
 [23-12-17 20:03:32] INFO:main.py:upload_task:144 | [1] 开始处理 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4'
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 Memory used: 44.08 MB
 [23-12-17 20:03:44] INFO:main.py:upload_task:237 | [2] 成功上传 '/home/mu/code-wsl/py-wsl/encrypt2bdy/test/【超丝滑60帧】4K精装字幕版《MORE》KDA.mp4' 文件哈希:b7b0cd46e3ac7681a3644d9761ad3e71
 [23-12-17 20:03:44] INFO:main.py:upload_task:282 | 本次上传完毕,上传:2,跳过:0,错误:0 | 总计:2
 [23-12-17 20:03:44] INFO:main.py:upload_task:283 | 本次上传完毕,平均上传速度:38.689mb/s | 总耗时:23.60s
 [23-12-17 20:03:44] INFO:main.py:upload_task:286 | 本次上传完毕,下次处理:2023-12-17 21:00:00
 
 | 
The end
关于分片计算md5的介绍就这么多,我这个程序里面文件加密的部分也需要修改,不过那就不是本文的范畴了~