OpenResty 阻塞操作

2021-08-07 11:54 更新

OpenResty 的誕生,一直對(duì)外宣傳是同步非阻塞(100% non-blocking)的。基于事件通知的 Nginx 給我們帶來了足夠強(qiáng)悍的高并發(fā)支持,但是也對(duì)我們的編碼有特殊要求。這個(gè)特殊要求就是我們的代碼,也必須是非阻塞的。如果你的服務(wù)端編程生涯一開始就是從異步框架開始的,恭喜你了。但如果你的編程生涯是從同步框架過來的,而且又是剛剛開始深入了解異步框架,那你就要小心了。

Nginx 為了減少系統(tǒng)上下文切換,它的 worker 是用單進(jìn)程單線程設(shè)計(jì)的,事實(shí)證明這種做法運(yùn)行效率很高。Nginx 要么是在等待網(wǎng)絡(luò)訊號(hào),要么就是在處理業(yè)務(wù)(請(qǐng)求數(shù)據(jù)解析、過濾、內(nèi)容應(yīng)答等),沒有任何額外資源消耗。

常見語言代表異步框架

  • Golang:使用協(xié)程技術(shù)實(shí)現(xiàn)
  • Python:gevent 基于協(xié)程的 Python 網(wǎng)絡(luò)庫
  • Rust:用的少,只知道語言完備支持異步框架
  • OpenResty:基于 Nginx,使用事件通知機(jī)制
  • Java:Netty,使用網(wǎng)絡(luò)事件通知機(jī)制

異步編程的噩夢(mèng)

異步編程,如果從零開始,難度是非常大的。一個(gè)完整的請(qǐng)求,由于網(wǎng)絡(luò)傳輸?shù)姆沁B續(xù)性,這個(gè)請(qǐng)求要被多次掛起、恢復(fù)、運(yùn)行,一旦網(wǎng)絡(luò)有新數(shù)據(jù)到達(dá),都需要立刻喚醒恢復(fù)原始請(qǐng)求處于運(yùn)行狀態(tài)。開發(fā)人員不僅僅要考慮異步 API 接口本身的使用規(guī)范,還要考慮業(yè)務(wù)請(qǐng)求的完整處理,稍有不慎,全盤皆輸。

最最重要的噩夢(mèng)是,我們好不容易搞定異步框架和業(yè)務(wù)請(qǐng)求完整性,但是卻在我們的業(yè)務(wù)請(qǐng)求上使用了阻塞函數(shù)。一開始沒有任何感知,只有做壓力測(cè)試的時(shí)候才發(fā)現(xiàn)我們的并發(fā)量上不去,各種卡頓,甚至開始懷疑人生:異步世界也就這樣。

OpenResty 中的阻塞函數(shù)

官方有明確說明,OpenResty 的官方 API 絕對(duì) 100% non-blocking,所以我們只能在她的外面尋找了。我這里大致歸納總結(jié)了一下,包含下面幾種情況:

  • 高 CPU 的調(diào)用(壓縮、解壓縮、加解密等)
  • 高磁盤的調(diào)用(所有文件操作)
  • 非 OpenResty 提供的網(wǎng)絡(luò)操作(luasocket 等)
  • 系統(tǒng)命令行調(diào)用(os.execute 等)

這些都應(yīng)該是我們盡量要避免的。理想豐滿,現(xiàn)實(shí)骨感,誰能保證我們的應(yīng)用中不使用這些類型的 API?沒人保證,我們能做的就是把他們的調(diào)用數(shù)量、頻率降低再降低,如果還是不能滿足我們需要,那么就考慮把他們封裝成獨(dú)立服務(wù),對(duì)外提供 TCP/HTTP 級(jí)別的接口調(diào)用,這樣我們的 OpenResty 就可以同時(shí)享受異步編程的好處又能達(dá)到我們的目的。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)