大家好,我是橙子!今天我們來聊聊 uvicorn,這個在 Python 網絡編程中非常高效且受歡迎的 ASGI 服務器。如果你在構建 Python Web 應用,尤其是想要提升性能,或是開發高并發系統,那么 uvicorn 會是一個非常合適的選擇。
在今天的教程中,我們將一起探討:
什么是 ASGI,為什么需要 uvicorn?
如何安裝和配置 uvicorn 服務器
如何用 uvicorn 啟動一個簡單的 Web 應用
如何在生產環境中優化 uvicorn 服務器的性能
讓我們從頭開始,輕松搞定 uvicorn 的安裝與使用!
什么是 ASGI,為什么需要 uvicorn?
在了解 uvicorn 之前,首先要知道 ASGI( Server Gateway )是干什么的。簡單來說,ASGI 是 Python Web 應用的接口規范,它為 Python 提供了更靈活的異步編程支持,相較于傳統的 WSGI(Web Server Gateway ),ASGI 支持更高效的異步 I/O 操作,特別適合實時性要求較高的應用,如聊天系統、實時數據推送等。
而 uvicorn 是一個 ASGI 服務器,也就是說,它是一個高效、快速的 Web 服務器,專門用來處理符合 ASGI 規范的 Python Web 應用。與傳統的 WSGI 服務器(比如 )相比,uvicorn 在處理并發和異步任務時表現得更加優異。
安裝 uvicorn
要開始使用 uvicorn,首先需要在 Python 環境中安裝它。打開命令行,輸入以下命令進行安裝:
pip?install?uvicorn
小貼士:
pip?install?"uvicorn[gunicorn]"
使用 uvicorn 啟動一個簡單的 Web 應用
接下來,我們用 uvicorn 啟動一個簡單的 FastAPI 應用(FastAPI 是一個高性能的 Web 框架,專為 ASGI 設計)。我們將通過一個簡單的 "Hello World" API 來了解如何使用 uvicorn。
1. 編寫 FastAPI 應用
首先,我們需要安裝 FastAPI 和 uvicorn:
pip?install?fastapi
然后,我們創建一個簡單的 FastAPI 應用:
from?fastapi?import?FastAPI
#?創建?FastAPI?應用
app?=?FastAPI()
#?定義根路由
@app.get("/")
def?read_root():
????return?{"message":?"Hello,?World!"}
小貼士:
2. 啟動 uvicorn 服務器
保存上述代碼為 main.py,然后通過 uvicorn 啟動該應用:
uvicorn?main:app?--reload
訪問 :8000,你就可以看到 "Hello, World!" 的返回值了。
3. 請求文檔
FastAPI 提供了一個內置的交互式 API 文檔頁面。你可以訪問 :8000/docs 來查看和測試 API。非常方便!這也是 FastAPI 被開發者青睞的原因之一。
如何在生產環境中優化 uvicorn
在開發環境中,使用 --reload 可以讓代碼改動后自動重啟,但是在生產環境中,我們需要更多的優化。
1. 使用 啟動 uvicorn
生產環境通常會使用 配合 uvicorn 來啟動應用,這樣可以充分利用多核 CPU 的性能。首先,我們需要安裝 :
pip?install?gunicorn
然后,通過以下命令使用 啟動 uvicorn:
gunicorn?-w?4?-k?uvicorn.workers.UvicornWorker?main:app
這樣可以讓你的應用在生產環境中高效且穩定地運行。
2. 調整 uvicorn 的配置
uvicorn 提供了許多配置選項來優化性能。比如,我們可以增加 --workers 來啟動多個工作進程,提高并發處理能力:
uvicorn?main:app?--workers?4
小貼士:
x ASGI 應用中的異步任務
uvicorn 最適合用于異步任務和并發處理的應用。如果你的應用需要處理大量的并發請求,使用異步編程將能極大地提高性能。
在 FastAPI 中,你可以使用 async 和 await 來創建異步路由:
from?fastapi?import?FastAPI
app?=?FastAPI()
@app.get("/async")
async?def?async_hello():
????return?{"message":?"Hello,?async?World!"}
通過異步路由,FastAPI 可以在請求過程中執行 I/O 操作而不會阻塞其他請求,這樣可以處理更多的并發。
小練習
現在,橙子給大家布置一個小練習:
使用 uvicorn 啟動一個 FastAPI 應用,支持一個異步接口 /async,該接口返回當前時間戳。
嘗試修改 workers 和 reload 參數,觀察性能差異。
今天的 Python 學習之旅就到這里啦!uvicorn 是一個非常高效的 ASGI 服務器,能夠大幅提升 Python Web 應用的性能,特別適合高并發場景。記得動手敲代碼,嘗試搭建屬于你自己的高效 Web 應用。祝大家學習愉快,Python 學習節節高!
WebRTC 媒體服務器
開源社區里可用的 WebRTC 媒體服務器有 Licode、OWT、Kurento、Jitsi、Janus、Medooze 和 。其中,能夠作為 MCU 使用的有 Licode、OWT、Kurento、Medooze,能夠作為 SFU 使用的有 Licode、OWT、Kurento、Jitsi、Janus、。
下面我們對其中幾個具有代表性的媒體服務器進行介紹。
OWT
OWT(Open WebRTC Toolkit) 是 Intel 在 2014 年推出的針對 WebRTC 的開發套件。該套件包含了優化 Intel 硬件的服務器和客戶端 SDK。Intel 持續為該套件增加新的特性,并于 2018 年將該套件開源。
OWT 既可以充當多點控制單元(MCU),又可以作為選擇性轉發單元(SFU) 使用。它還提供了對媒體進行解碼、處理和重新編碼后再將其發送回客戶端的能力。
OWT 包含的主要功能如下。
OWT 應用層使用 Node.js 開發,媒體處理層使用了 C++ 語言,數據庫使用 MongoDB,消息通信使用了 。
OWT 還提供了全平臺的客戶端 SDK,可以方便地整合到業務之中。
Kurento
Kurento 開源項目包含了一個 WebRTC 媒體服務器(KMS) 和一組與之通信的客戶端 API。使用 Kurento 可以簡化 Web 及移動端音視頻應用程序的開發過程。Kurento 提供的功能包括音視頻實時通信、實時轉碼、服務器端錄制、合流、廣播等。
Kurento 的特性有以下幾個。
1.動態 WebRTC 媒體管道
Kurento 允許使用自定義媒體管道連接到 WebRTC 對等設備,例如 Web 瀏覽器和移動應用程序。這些媒體管道包括播放器、記錄器、混音器等,即使在媒體已經連通的情況下,也可以在任何時間點對這些媒體管道進行組合、激活或停用。
2.客戶端/服務器架構
使用 Kurento 開發的應用程序遵循客戶端/服務器架構。Kurento 媒體服務器(KMS)提供了支持 Kurento 協議的 接口,該接口允許客戶端應用程序定義管道拓撲。
3.Java和客戶端應用程序
KMS 部署的典型示例包括 3 層體系結構,其中用戶的瀏覽器通過中間客戶端應用程序與 KMS 服務器交互。有幾個官方的 Kurento 客戶端庫,支持在客戶端應用程序中使用 Java 和 。遵循 協議,可以輕松開發自己的客戶端 SDK。
4.第三方模塊
Kurento 媒體服務器具有基于插件的可擴展結構,該結構允許第三方自定義模塊。通過自定義模塊,可以將任何媒體處理算法集成到 WebRTC 應用程序中,例如集成計算機視覺增強現實、視頻索引和語音分析等。
Kurento Media Server 的代碼是開源的,根據Apache License Version 2.0 的條款發布可在 GitHub 上免費獲得。
Janus
采用C語言實現的 Janus 是一個 Liux 風格編寫的 WebRTC 媒體服務器開源項目,支持在 Linux/MacOS下編譯、部署,但不支持 Windows 環境。
Janus 分為兩層: 插件層和傳輸層。Janus 插件的設計類似于 Nginx,用戶可以根據自己的需要動態加載或卸載插件,也可以根據自身業務需要編寫自己的插件。Janus 默認支持的插件如下。
媒體數據傳輸層主要實現了 WebRTC 中的流媒體及其相關協議,如 DTLS、ICE、SDP、RTP、SRTP、SCTP 等。
信令傳輸層用于處理Janus 的各種信令,支持的信令傳輸協議包括HTTP/HTTPS、/、NanoMsg、MQTT、PfUnix 和 。不過需要注意的是,有些協議是可以通過編譯選項控制是否安裝的,也就是說這些協議并不是默認全部安裝的。另外,Janus的所有信令都采用JSON格式。
Janus 整體架構采用了插件的方案,這種架構方案非常優秀,用戶可以根據自己的需要,非常方便地在上面編寫應用程序。Janus 支持的功能非常多,比如 SIP、RTSP、音視頻文件的播放和錄制等,所以在融合性上比其他系統有非常大的優勢。另外,Janus 的底層代碼是由C語言編寫的,性能非常強大。Janus 的開發、部署手冊非常完善,因此它是一個非常優秀的開源項目。
是一個較新的 WebRTC 媒體服務器,其底層采用C++實現,外層使用Node.js 進行封裝。 服務器端以 Node.js 模塊的形式提供。
及其客戶端庫的設計目標如下。
支持 和 SVC,底層使用 C++ 開發,使用 libuv 作為異步IO事件處理庫,保證了數據傳輸的高效性。 的實現邏輯非常清晰,它不關心上層應用如何做,只關心底層數據的傳輸,并將其做到極致。
與 Janus 相比, 更關注數據傳輸的實時性、高效性和簡潔性,而 Janus 相對來講更加復雜一些。
作為 SFU 媒體服務器的優點如下。
與其他的 SFU 相比, 最大的不同是它不能作為一個獨立的服務器使用,而是以 Node.js 模塊的形式存在,這樣做的好處是可以整合到更大的應用程序中,不受自身的限制。在服務器端引人 的方式如下。
const mediasoup = require("mediasoup");
在 Node.js 模塊內部, 可以分為兩個獨立的組件: 一個 層,提供了適用于 Node.js 的現代 ; 一組處理媒體層(ICE、DTLS、RTP等)的C/C++子進程(Worker)。
這兩個組件通過進程相互通信,但是,從開發人員的角度來看,應用程序只需要關注 API 層。
把每個實例稱為一個子進程,通常在每核 CPU 上啟動一個子進程。在子進程內部有多個 Router,每個 Router 相當于一個房間。在每個房間里可以有多個參與者,每個參與者在 中由一個 代理。換句話說,對于 Router,一個 就相當于一個用戶。
分為3類 ,即 、 和 。
用于與 WebRTC 類型的客戶端進行連接,如瀏覽器、WebRTC移動端等。
用于與傳統的 RTP 類型的客戶端連接,通過該 可以播放多媒體文件、執行媒體錄制等。
用于實現 Router 之間的連接,也就是一個房間中的音視頻流通過 傳到另一個房間。由于一個 Router 只能運行在單核上,因此借助 可以充分利用多核 CPU 的特性,支持更多人同時在線。
每個 可以包含多個 和 。 表示媒體流的生產者,分為兩種類型,即音頻生產者和視頻生產者。 表示媒體流的消費者,也分為兩種類型,即音頻消費者和視頻消費者。
信令交互過程
的信令交互本質上與原生 WebRTC 的信令交互是一樣的。 在其提供的客戶端及服務器端庫中封裝了 WebRTC 的原生 API,如 ()、()等方法都封裝在 的 API 中。
通常由客戶端發起信令交互,流程如下。
如果客戶端創建的是發送通道,則進一步的流程如下。
如果客戶端創建的是接收通道,則流程如下。
媒體服務器的選擇
開源社區的幾個媒體服務器各有特色,在實際應用中應根據項目需要進行選擇。當需要采用MCU方案時,推薦使用OWT;當需要在服務器端對媒體流進行處理,比如增加人臉識別等功能時,推薦使用 Kurento; 當構建通用的WebRTC平臺時,Janus 基于插件的模式更為合適; 如果希望打造單一的視頻通話應用,則推薦使用 。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。