BiliOB 观测者的最近一次更新后,服务器内存占用飞速提高,经常因为内存不足 Kill 掉 Mongodb 数据库以及 Spring boot 的后端服务。
出现这种问题是在爬虫更新后。我在爬虫中引入了结巴分词模块,对弹幕进行分析。
然而 Scrapy 的爬虫管理很有问题,为了引入我需要的分词和词频统计功能,我必须在弹幕爬虫中引入 jieba.analyze
这个包,从而在弹幕爬虫中使用。而且在弹幕爬虫的初始化内载入自定义字典。
而实际运行情况是这样的,无论我使用 scrapy crawl ...
命令启动哪一个爬虫,都会载入 jieba.analyze,并且初始化每一个爬虫。
而我使用 memory_profiler
对内存进行分析后,发现内存的使用情况是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Line ================================================ 31 180.3 MiB 180.3 MiB @profile 32 def __init__(self): 33 34 35 246.7 MiB 66.3 MiB jieba.load_userdict('.biliob_analyzer/dict.txt') 36 37 38 246.7 MiB 0.0 MiB self.client = MongoClien(settings['MINGO_HOST'], 27017) 39 40 246.7 MiB 0.0 MiB self.client.admin.authenticate(settings['MINGO_USER'], 41 246.7 MiB 0.0 MiB settings['MONGO_PSW']) 42 246.7 MiB 0.0 MiB self.db = self.clien['biliob'] 43 246.7 MiB 0.0 MiB self.coll = self.d['author'] 44 246.7 MiB 0.0 MiB self.redis_connection = redis.from_url(redis_connect_string)
|
这是把这样一个爬虫加入爬虫列表后,所有爬虫的启动时内存消耗。
此前,一个爬虫大概占据 70MB 左右,引入了结巴分词后,内存消耗直接飙到 180.3MB,上涨 100MB 以上,引入自定义词库之后,再增加 66.3MB,总计消耗 246.7MB。
看上去不多,但是对于我这个非常低端的服务器而言,是非常重的负载了。因为最为糟糕的是,我的服务器有可能会同时跑四五个爬虫,而 java 和 mongodb 也是两个吃内存的怪兽。与之相对,我的服务器只有 2GB 的内存空间。
因此急需优化。但 scrapy 似乎没有内置解决方案。其实有一种很简单的思路,只需要将爬虫分成两个 project,就能不受干扰地引入各自的模块。
经过分解,原先爬虫的内存占用如下。
1 2 3 4 5 6 7 8 9 10 11 12 13
| Line ================================================ 29 72.2 MiB 72.2 MiB @profile 30 def __init__(self): 31 32 33 72.3 MiB 0.0 MiB self.client = MongoClient(settings['MINGO_HOST'], 27017) 34 35 72.3 MiB 0.0 MiB self.client.admin.authenticate(settings['MINGO_USER'], 36 72.3 MiB 0.0 MiB settings['MONGO_PSW']) 37 72.3 MiB 0.0 MiB self.db = self.client['biliob'] 38 72.3 MiB 0.0 MiB self.coll = self.db['author'] 39 72.3 MiB 0.0 MiB self.redis_connection = redis.from_url(redis_connect_string)
|
可以看到,恢复了正常水平。
可维护
但这样毕竟可维护性是极差的。因为有很多相同的配置需要重复一遍,那么有没有一种方案可以解决这个问题呢?
……