使用 Hypercorn HTTP/2 ASGI 部署 FastAPI
Another ASGI web server that supports HTTP/2 and HTTP/3 specifications
我已經介紹了很多關於 FastAPI 的教程,其中伺服器部署了 Uvicorn,一個快速的 ASGI Web 伺服器。在撰寫本文時,Uvicorn 目前僅支援 HTTP/1.1 和 WebSockets。根據官方文件,計劃支援 HTTP/2,但沒有預計完成時間。
HTTP/2 是舊 HTTP/1 的繼承者,它在減少延遲的同時保持相同的高階語義(方法、標頭欄位、狀態程式碼等)。基於維基百科,它通過以下方式改進了網頁的載入:
-
data compression
- HTTP/2 Server Push
- pipelining of requests
- fixing the head-of-line blocking problem in HTTP 1.x
- multiplexing multiple requests over a single TCP connection
This articles covers FastAPI server deployment for HTTP/2 using another ASGI web server called Hypercorn. For your information, Hypercorn is
… an ASGI web server based on the sans-io hyper, h11, h2, and wsproto libraries and inspired by Gunicorn. Hypercorn supports HTTP/1, HTTP/2, WebSockets (over HTTP/1 and HTTP/2), ASGI/2, and ASGI/3 specifications. Hypercorn can utilise asyncio, uvloop, or trio worker types.
Let’s proceed to the next section and start installing the necessary modules.
Setup
It is highly recommended to create a virtual environment before you continue with the installation. Activate the virtual environment and continue installing the necessary packages via pip install
.
FastAPI
Run the following command to install FastAPI:
pip install fastapi
Hypercorn
Install Hypercorn as follows:
pip install hypercorn
Implementation
In this section, you will learn to write a simple FastAPI script and run it using Hypercorn.
FastAPI Server
Let’s create a new Python file called myapp.py
in the same working directory with the following code:
from fastapi import FastAPIapp = FastAPI()@app.get("/")
async def root():
return {"message": "Hello world!"}
Deploying with Hypercorn
Next, run the following command at the terminal to start your server. By default, it will run as localhost
on port 8000
.
hypercorn myapp:app
Similar to Uvicorn, Hypercorn uses the following syntax
hypercorn <module_name>:<variable_name>
-
module_name
— name of the module (filename) -
variable_name
— name of the variable defined for FastAPI
Binding to Specific Address
However, the configuration or available options are a lot different compared to Uvicorn. For example, you have to use the bind
option for specifying the host and port as follows:
# Hypercorn
hypercorn myapp:app --bind 0.0.0.0:8080# Uvicorn
uvicorn myapp:app --host 0.0.0.0 --port 8080
Binding to Multiple Addresses
In fact, you can bind it to multiple servers and serve them simultaneously. This is extremely useful when you need to serve the server on both IPv4 and IPv6. For example:
hypercorn myapp:app --bind "0.0.0.0:5000" --bind "[::]:5000"
Other Configurations Options
Furthermore, you can use the following options when running Hypercorn in the command line as well.
-
--access-logformat
— The log format for the access log, see Logging. -
--access-logfile
— The target logger for access logs, use-
for stdout. -
--backlog
—The maximum number of pending connections. -
--ca-certs
— Path to the SSL CA certificate file. -
--certfile
— Path to the SSL certificate file. -
--cipher
— Ciphers to use for the SSL setup. -
--debug
— Enable debug mode, i.e. extra logging and checks. -
--error-logfile --log-file
— The target location for the error log, use — for stderr. -
--graceful-timeout
— Time to wait after SIGTERM or Ctrl-C for any remaining requests (tasks) to complete. -
--keep-alive
— Seconds to keep inactive connections alive before closing. -
--keyfile
— Path to the SSL key file. -
--log-config
— A Python logging configuration file. -
--log-level
— The (error) log level. -
--pid
— Location to write the PID (Program ID) to. -
--reload
—Enable automatic reloads on code changes. -
--worker-class
— The type of worker to use. Options include asyncio, uvloop (requirespip install hypercorn[uvloop]
), and trio (requirespip install hypercorn[trio]
). -
--workers
—The number of workers to spawn and use.
Result
Assuming that you have ran the following command:
hypercorn myapp:app
You should get the following output at the console when you run it:
[2021-07-10 21:24:19 +0800] [5464] [INFO] Running on http://127.0.0.1:8000 (CTRL + C to quit)
Open up a browser and head over to the following URL mentiond in the console:
http://localhost:8000/
The output should be as follows:
{"message":"Hello world!"}
However, the server indicated in the response headers is hypercorn-h11 which refers to HTTP/1.1
Image by the authorThis is mainly because HTTP/2 requires a mandatory encryption. You have to serve it with certificates even if you are running it as localhost
.
Generate a Self-signed Certificate
Let’s create a temporary self-signed certificate using rsa for 365 days. Run the following command in your command line:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
如果您在讀取檔案時遇到openssl.cnf
如下問題:
Can't open .../openssl.cnf for reading. No such file or directory
它只是意味著它無法找到配置檔案。如果你已經安裝了 openssl 附帶的 Git,只需將其指向openssl.cnf
使用-config
選項的位置。例如:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -config "C:\Program Files\Git\usr\ssl\openssl.cfg"
它將生成兩個新檔案:
- key.pem
- cert.pem
- 金鑰.pem
- 證書.pem
接下來,將這兩個檔案放在與 myapp.py 相同的目錄中,並使用--keyfile
和--certfile
命令執行它:
hypercorn --keyfile key.pem --certfile cert.pem myapp:app
在您的瀏覽器上,重新載入頁面,但這次使用 https 代替:
https://localhost:8000/
它應該提示一個警告頁面表明(如果您使用的是自簽名證書,這是正常的):
localhost:8000 uses an invalid security certificate.
The certificate is not trusted because it is self-signed.
接受風險並繼續訪問請求的 URL。您應該獲得以下響應標頭:
hypercorn-h2
表示伺服器正在執行 HTTP/2。對於生產伺服器,建議改用有效證書。您可以使用Let's Encrypt為您的網站獲取免費證書。
結論
讓我們回顧一下您今天所學的內容。
本文以對 HTTP/2 的簡要說明開始。它還涵蓋了對 Uvicorn 和 Hypercorn ASGI 伺服器的 HTTP/2 支援。
然後,它通過pip install
.
它繼續使用 FastAPI 伺服器的標準樣板並在本地主機上執行它。除此之外,它還介紹了使用 Hypercorn 部署 FastAPI 伺服器時可用的配置。
本教程還包括一個關於生成自簽名證書的簡單部分,因為 HTTP/2 在部署期間需要強制證書。