網(wǎng)絡(luò)模型有很多中卫玖,為了實(shí)現(xiàn)高并發(fā)也有很多方案贱纠,多線程祭椰,多進(jìn)程果正。無(wú)論多線程和多進(jìn)程税肪,IO的調(diào)度更多取決于系統(tǒng)褥傍,而協(xié)程的方式吴藻,調(diào)度來(lái)自用戶暖途,用戶可以在函數(shù)中yield一個(gè)狀態(tài)鳞溉。使用協(xié)程可以實(shí)現(xiàn)高效的并發(fā)任務(wù)瘾带。Python的在3.4中引入了協(xié)程的概念,可是這個(gè)還是以生成器對(duì)象為基礎(chǔ)熟菲,3.5則確定了協(xié)程的語(yǔ)法看政。下面將簡(jiǎn)單介紹asyncio的使用。實(shí)現(xiàn)協(xié)程的不僅僅是asyncio抄罕,tornado和gevent都實(shí)現(xiàn)了類似的功能允蚣。
event_loop 事件循環(huán):程序開啟一個(gè)無(wú)限的循環(huán),程序員會(huì)把一些函數(shù)(實(shí)際上就是協(xié)程)注冊(cè)到事件循環(huán)上呆贿。當(dāng)滿足事件發(fā)生的時(shí)候嚷兔,調(diào)用相應(yīng)的協(xié)程函數(shù)。
coroutine 協(xié)程:協(xié)程對(duì)象做入,指一個(gè)使用async關(guān)鍵字定義的函數(shù)冒晰,它的調(diào)用不會(huì)立即執(zhí)行函數(shù),而是會(huì)返回一個(gè)協(xié)程對(duì)象竟块。協(xié)程對(duì)象需要注冊(cè)到事件循環(huán)壶运,由事件循環(huán)調(diào)用。
task 任務(wù):一個(gè)協(xié)程對(duì)象就是一個(gè)原生可以掛起的函數(shù)浪秘,任務(wù)則是對(duì)協(xié)程進(jìn)一步封裝蒋情,其中包含任務(wù)的各種狀態(tài)。
future: 代表將來(lái)執(zhí)行或沒(méi)有執(zhí)行的任務(wù)的結(jié)果耸携。它和task上沒(méi)有本質(zhì)的區(qū)別
async/await 關(guān)鍵字:python3.5 用于定義協(xié)程的關(guān)鍵字棵癣,async定義一個(gè)協(xié)程,await用于掛起阻塞的異步調(diào)用接口夺衍。
阻塞和await
使用async可以定義協(xié)程對(duì)象浙巫,使用await可以針對(duì)耗時(shí)的操作進(jìn)行掛起,就像生成器里的yield一樣,函數(shù)讓出控制權(quán)的畴。協(xié)程遇到await渊抄,事件循環(huán)將會(huì)掛起該協(xié)程,執(zhí)行別的協(xié)程丧裁,直到其他的協(xié)程也掛起或者執(zhí)行完畢护桦,再進(jìn)行下一個(gè)協(xié)程的執(zhí)行。
并發(fā)
asyncio實(shí)現(xiàn)并發(fā)煎娇,就需要多個(gè)協(xié)程來(lái)完成任務(wù)二庵,每當(dāng)有任務(wù)阻塞的時(shí)候就await,然后其他協(xié)程繼續(xù)工作缓呛。創(chuàng)建多個(gè)協(xié)程的列表催享,然后將這些協(xié)程注冊(cè)到事件循環(huán)中。
底層實(shí)現(xiàn)
python asyio實(shí)現(xiàn)單線程異步模式哟绊, 實(shí)際上底層運(yùn)用了I/O多路復(fù)用方法因妙。用戶態(tài)同步I/O模擬的異步請(qǐng)求。
event_loop實(shí)際上就是一個(gè)I/O多路復(fù)用器票髓,在linux上使用的是epoll.
程序員把協(xié)程函數(shù)注冊(cè)到事件循環(huán)上攀涵,asyio底層首先執(zhí)行系統(tǒng)調(diào)用返回文件描述符,比如執(zhí)行網(wǎng)絡(luò)請(qǐng)求洽沟,然后將該套接字描述符和回調(diào)函數(shù)等封裝成一個(gè)請(qǐng)求以故。然后注冊(cè)到I/O多路復(fù)用器上, 當(dāng)獲取到數(shù)據(jù)之后,執(zhí)行回調(diào)函數(shù)裆操,然后再將回調(diào)函數(shù)的返回值返回給協(xié)程函數(shù)怒详。