高并发异步爬虫落地:单机日采百万数据,性能提升10倍的优化方案
背景之前做电商价格监测项目时最开始写的同步爬虫一天只能爬10万条数据服务器都跑满了还是不够用。后来一步步优化改成异步协程连接池复用的架构单机一天就能爬120万条数据CPU占用还不到30%。一、优化前的痛点先看看最开始的垃圾性能同步爬虫用requests循环爬一秒最多爬5条一天10万条顶天资源浪费每个请求都新建连接TCP握手开销占了70%的时间没有限流爬太快被封IP爬太慢完不成任务卡得要死二、最终优化架构我最终落地的架构非常简单不需要复杂的分布式集群单台2核4G服务器就能跑满带宽任务调度器异步任务队列协程池连接池复用模块请求去重模块数据持久化模块限流/降级模块这套架构的核心是尽可能减少不必要的开销把所有能复用的东西都复用起来把CPU的性能榨干。三、核心优化点1. 异步协程替换同步请求这个是最基础的优化我用asyncioaiohttp替换了原来的requests并发量直接提升了10倍# 基础异步爬取逻辑asyncdeffetch_url(url,semaphore,session):asyncwithsemaphore:# 控制并发数避免把服务器跑崩try:asyncwithsession.get(url,timeout10)asresp:ifresp.status200:returnawaitresp.text()else:returnNoneexceptExceptionase:returnNoneasyncdefmain():semaphoreasyncio.Semaphore(200)# 并发数控制在200我这边2核4G服务器跑200并发刚好# 连接池复用配置这个是性能提升的核心timeoutaiohttp.ClientTimeout(total30)connectoraiohttp.TCPConnector(limit200,# 连接池大小和并发数一致limit_per_host20,# 单个域名最多20个连接避免被封ttl_dns_cache300,# DNS缓存5分钟减少DNS解析开销force_closeFalse# 不要主动关闭连接保持长连接)asyncwithaiohttp.ClientSession(connectorconnector,timeouttimeout)assession:tasks[fetch_url(url,semaphore,session)forurlinurls]resultsawaitasyncio.gather(*tasks,return_exceptionsTrue)# 处理结果...这里要注意并发数不是越大越好我最开始设成500结果服务器直接OOM了后来压测发现2核4G服务器设成200是最优的CPU占用30%左右带宽刚好跑满。2. 连接池复用优化这个优化是性能提升最大的原来每个请求都新建TCP连接握手就要3次断开还要4次开销太大。现在用连接池复用TCP连接开销直接减少了70%单个域名的连接数控制在20以内避免给目标服务器造成太大压力被封DNS缓存5分钟减少DNS解析的开销保持长连接不要主动关闭aiohttp会自动复用可用的连接3. 限流降级策略爬太快很容易被封我做了两层限流域名级限流每个域名每秒最多爬10次超过就延迟几秒再爬全局限流单机每秒最多爬100次超过就自动降低并发数小贴士不要相信什么动态UA就能不被封限速才是最靠谱的反爬策略只要你爬的速度比正常人访问还慢几乎不会被封。四、压测数据我压测了10万条请求优化前后的对比指标优化前同步优化后异步连接池总耗时8小时20分钟23分钟QPS3.372CPU占用90%28%内存占用1.2G300M请求成功率82%97%优化后的性能是原来的21倍资源占用反而更低完全够用了。五、踩坑经验协程数太高导致OOM最开始把并发数设成500结果内存直接爆了后来压测找到最优值是200连接池太大被封IP最开始单个域名的连接数设成50结果爬了10分钟就被封了改成20就没问题了异常处理不完整导致任务卡住最开始没有处理超时、连接重置这些异常有时候任务会卡住几个小时后来加了超时和异常重试机制就好了下一篇我会讲这套爬虫的容灾方案怎么做到7×24小时运行零数据丢失。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2512318.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!