菜菜的并发编程笔记 |(九)异步IO实现并发爬虫加速

news/2024/7/7 21:42:24 标签: 爬虫, nginx, 前端, python, flask

在这里插入图片描述
系列索引:菜菜的并发编程笔记 | Python并发编程详解(持续更新~)

文章目录

    • 一、思维导图👧
    • 二、什么是协程?
    • 三、Python 异步IO库介绍:asyncio
    • 四、异步编程的威力
    • 五、异步编程核心原理
    • 六、异步编程代码示例
    • 七、信号量机制的应用

一、思维导图👧

请添加图片描述

二、什么是协程?

在这里插入图片描述
协程:我个人理解的协程就是当遇到需要IO操作时,CPU去执行其他程序,等IO完成后再恢复CPU的使用。使用协程必须使用 loop = asyncio.get_event_loop() 创建超级循环。

三、Python 异步IO库介绍:asyncio

在这里插入图片描述
这里面有几个重要的关键词,一个是async,用于声明函数是异步函数,还有await就是遇到IO阻塞挂起去执行await里面的函数,tasks列表中也可使用ensure_future来创建。最后一行是执行爬虫直到tasks全部完成。

四、异步编程的威力

  • Nginx作为 Web 服务器:
    打败了同步阻塞服务器 Apache, 使用更少的资源支持更多的并发连接,体现更高的效率,能够支持高达 50,000 个并发连接数的响应,使用 epoll and kqueue 作为开发模型
  • Redis为什么这么快:
    处理网络请求采用单线程+使用多路I/O复用模型,非阻塞IO ,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
  • Node.js的优势:
    采用事件驱动、异步编程,为网络服务而设计。其实Javascript的匿名函数和闭包特性非常适合事件驱动、异步编程。Node.js非阻塞模式的IO处理带来在相对低系统资源耗用下的高性能与出众的负载能力,非常适合用作依赖其它IO资源的中间层服务
  • Go语言的一个优势:
    Go 使用Goroutine 和 channel为生成协程和使用信道提供了轻量级的语法,使得编写高并发的服务端软件变得相当容易,很多情况下完全不需要考虑锁机制以及由此带来的各种问题,相比Python单个 Go 应用也能有效的利用多个 CPU 核,并行执行的性能好

五、异步编程核心原理

核心原理1:超级循环

在单线程内实现并发,用一个超级循环(其实就是while true)循环,里面每次轮询处理所有的task

核心原理2:IO多路复用

是一种同步IO模型,实现一个线程可以监视多个文件句柄;
一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;
没有文件句柄就绪时会阻塞应用程序,交出cpu
多路是指网络连接,复用指的是同一个线程

3种实现方式,分别是select,poll,epool

  • select

    数据结构:bitmap
    最大连接数:1024
    fd拷贝:每次调用select拷贝
    工作效率:轮询O(N)
    
  • poll

    数据结构:数组
    最大连接数:无上限
    fd拷贝:每次调用poll拷贝
    工作效率:轮询O(N)
    
  • epool

    数据结构:红黑树
    最大连接数:无上限
    fd拷贝:fd首次调用epool_ctl拷贝,每次调用epoll_wait不拷贝
    工作效率:回调O(1)
    

六、异步编程代码示例

因为协程不支持requests,所以我们使用aiohttp代替。
在协程函数中,可以通过await语法来挂起自身的协程,并等待另一个协程完成直到返回结果。要注意的是,await语法只能出现在通过async修饰的函数中,否则会报SyntaxError错误。

python">import asyncio
import aiohttp
import blog_spider

async def async_craw(url):
    print("craw url: ", url)
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            result = await resp.text()
            print(f"craw url: {url}, {len(result)}")

loop = asyncio.get_event_loop()

tasks = [
    loop.create_task(async_craw(url))
    for url in blog_spider.urls]

import time

start = time.time()
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
print("use time seconds: ", end - start)

七、信号量机制的应用

在这里插入图片描述
我们主要使用信号量机制来控制协程数量,下面三个加#的行是和上一处代码的区别,可以对照学习。

python">import asyncio
import aiohttp
import blog_spider

semaphore = asyncio.Semaphore(10)#

async def async_craw(url):
    async with semaphore:#
        print("craw url: ", url)
        async with aiohttp.ClientSession() as session:
            async with session.get(url) as resp:
                result = await resp.text()
                await asyncio.sleep(5)#
                print(f"craw url: {url}, {len(result)}")

loop = asyncio.get_event_loop()

tasks = [
    loop.create_task(async_craw(url))
    for url in blog_spider.urls]

import time

start = time.time()
loop.run_until_complete(asyncio.wait(tasks))
end = time.time()
print("use time seconds: ", end - start)

下一篇我们将分析Geventasyncio的区别,并讲解如何使用Gevent改造一个异步服务器。

Python进阶之并发编程篇持续更新,欢迎点赞收藏关注

上一篇:菜菜的并发编程笔记 |(八)使用多进程multiprocessing进行项目开发
下一篇:菜菜的并发编程笔记 |(十)异步编程库Asyncio和Gevent的对比、使用Gevent改造异步服务器

本人水平有限,文章中不足之处欢迎下方👇评论区批评指正~

如果感觉对你有帮助,点个赞👍 支持一下吧 ~

不定期分享 有趣、有料、有营养内容,欢迎 订阅关注 🤝 我的博客 ,期待在这与你相遇 ~


http://www.niftyadmin.cn/n/1425712.html

相关文章

hibernate实践 附QBC检索方式常用的设定查询条件的方法

* EL使用(取name中文乱码怎么办,set还有范围是怎么回事) 1.hibernate设计模式的应用(程序开发范例宝典 实例379)通用数据库模块Hibernate.javapackage mrgf; import java.util.List;import org.hibernate.cfg.Configuration;import org.hibernate.SessionFactory;import org.…

hibenate的一对一,一对多的关联操作实践

应用一对一关联实现级联添加数据 (作业:实现级联删除的功能)在Record类中建立类型为IdCard的属性和对应的set()/get()方法,其关键代码如下: private IdCard idCard; public void setIdCard(IdCard idCard) { this.idCard idCard; } public IdCard getIdCard(){ …

struts设计模式之DispathAction类实现多个操作

struts设计模式DispathAction类实现用户查询通常在一个Action类中只完成一个业务操作,如果在一个Action类中要完成一组紧密 相关的业务操作,可以使用DispathAction类.DispathAction类继承Action类,它是一个 抽象类,封装了一些基本的方兴未艾,来赋予一个Action类处理多个操作的…

《Spring 2.0核心技术与最佳实践》第一天

序java开发,从桌面系统到企业应用,从手机到智能卡. 随着J2EE1.5标准的发布,Sun将J2EE正式更名为JaveEE,JavaEE平台继承了Java语言的安全性和高可移植性,为企业应用的设计,开发,部署和管理提供了一套完善的解决方案,它包括了从前端Web界面到中间件,再到后端数据库系统的一系列技…

《Spring 2.0核心技术与最佳实践》第二天

组件就是普通的Bean(拿来重复使用) 使用IoC容器管理Bean1.函数重用,类重用,组件重用(通过接口来使用?)2 控制权(负责创建配置组件)发生了反转,从应用程序转移到了IoC容器.在IoC容器中能被"装配",需有"注入"机制,使组件注到另一组件.依赖注入:将组件配置和…

《Spring 2.0核心技术与最佳实践》第三天

第三天 1.Ioc_XDoclet学习,XDoclet使用 (三个配置文件,一个Bean中要写的标注,xDoclet的jar包) 配置Ant(连接spring的模板,还可以合并手写的spring-bean.xml)来实现xml的自动生成(bin/config.xml) Ant的build.xml (关键配置文件)<?xml version"1.0" encoding&…

菜菜的刷题日记 | 蓝桥杯 — 十六进制转八进制(纯手撕版)附进制转换笔记

系列索引&#xff1a;菜菜的刷题日记 | 被LeetCode用Python狂虐的那段日子 万万没想到啊&#xff0c;回老家过年断更的几天之后&#xff0c;我会因为无聊在除夕这天做了会儿题&#xff0c;然后写篇题解。 文章目录【题目】【我的代码】【进制转换笔记】【思考】【题目】 题目链…

《Spring 2.0核心技术与最佳实践》第四天

hsqldb文档(把数据以文件的形式保存下来的方法?)HSQLDB是一个纯Java编写的数据库.使用方法1.导入hsqldb.jar org.hsqldb.jdbcDriver jdbc:hsqldb:mem:bookstore2. 编程 (org.hsqldb.Server;)import java.sql.Connection;import java.sql.DriverManager;import java.s…