Rocket的目標是提供一個高彈性和高可用性的組態配置系統,開發者或是系統管理員可以很輕易地對每一個別的設定項目使用環境變數、設定檔或是程式碼來進行設定。
以設定優先等級來說,寫死在程式碼內的設定值的優先權是最高的。其次是環境變數,最後才是寫在設定檔中的設定值。這篇文章會先從優先權最低的設定方式開始說明。
不過在開始說明設定方式之前,先來了解一下Rocket框架到底有哪些項目可以設定吧!
Rocket框架的組態配置
啟動Rocket框架時,Rocket會於標準輸出(stdin)中列出啟動該Rocket應用程式時所使用的組態配置。如下圖所示:
Rocket框架的主要可設定項目如下表:
項目名稱 | 類型 | 預設值(預設會用編譯模式來區分Profile:debug /release ) |
功用 |
---|---|---|---|
address | 字串(IP位址) | 127.0.0.1 |
Rocket框架啟動時要監聽的網路介面(IP位址)。 |
port | 整數(16位元的無號整數) | 8000 |
Rocket框架啟動時要監聽的TCP連接埠。 |
workers | 整數(無號整數) | CPU邏輯核心的數量 | 執行非同步函數的執行緒數量。 |
max_blocking | 整數(無號整數) | 512 |
執行阻塞任務的最大執行緒數量。 |
ident | 字串、false |
Rocket |
在HTTP回應中,於Server 標頭欄位中要夾帶的值。如果設為false ,則不回應Server 標頭。 |
ip_header | 字串、false |
X-Real-IP |
在HTTP請求中,要把哪個標頭欄位中的值當作是客戶端的真實IP。如果設為false ,則不使用這個方式來取得客戶端的真實IP。 |
limits | 表格(欄位的值皆為表示位元組大小的字串) | { bytes = "8KiB", data-form = "2MiB", file = "1MiB", form = "32KiB", json = "1MiB", msgpack = "1MiB", string = "8KiB" } |
針對不同的請求類型,來限制Rocket框架在讀取每個請求時,最大能讀取前面的幾個位元組。 |
temp_dir | 字串(目錄路徑) | 執行環境的暫存目錄 | 暫存檔所存放的目錄之路徑。 |
keep_alive | 整數(32位元的無號整數,表示秒數) | 5 |
HTTP連線的keep-alive時間,0 為不開啟;超過0 表示要keep-alive的秒數。 |
tls | 表格(certs 、key 值分別為SSL證書和密鑰的路徑) |
無 | 使Rocket框架能夠提供HTTPS服務。如果不設定的話就只會使用HTTP。Rocket框架所提供的HTTPS功能不建議使用在正式環境中,應使用Nginx等反向代理伺服器。 |
secret_key | 字串(256位元或是512位元的Base64資料) | 由Rocket框架於啟動時隨機產生。 | 用來作為基於Cookie的會話(Cookie-based Session)等需加密時的場合所使用的密鑰。在使用release 執行環境時,這個項目的值必須由系統管理員手動設定,確保每個應用程式實體都是使用一樣的密鑰。這個欄位只會在啟用rocket 的secrets 特色時才會有作用。 |
shutdown | 表格 ( ctrlc 為布林值,設定是否能用Ctrl + c來觸發shutdown;force 為布林值,設定是否強制關閉非同步執行環境;signals 為Set集合,設定哪些中斷信號可以觸發shutdown,Unix環境才有效;grace 和mercy 為32位元無號整數,前者為強制關閉HTTP回應等伺服器I/O前的等待時間秒數,後者為強制關閉連線I/O前的等待時間秒數) |
{ ctrlc = true, force = true, signals = [SIGTERM], grace = 2, mercy = 3 } |
設定如何「優雅的關機」(Graceful Shutdown)。 |
log_level | 字串(off 、critical 、normal 、debug ) |
normal /critical |
設定Log的輸出層級。愈靠近debug 層級的話,輸出的Log愈多。 |
cli_colors | 布林 | true |
是否在Log中使用顏色和Emoji。 |
關於secret_key
的產生,可以直接使用OpenSSL指令來完成。指令如下:
設定Rocket框架
用設定檔設定Rocket框架
Rocket框架在啟動的時候,預設會去讀取工作目錄中的Rocket.toml
檔案,如果這個檔案不存在,就會不斷地往上層目錄中尋找Rocket.toml
檔案來用。
Rocket.toml
設定檔的撰寫方式很簡單,如下:
[default]
address = "0.0.0.0"
port = 9958
keep_alive = 0
workers = 32
log = "debug"
secret_key = "nPu3M2/h4UOA8kVEpPqH+4KUzLaJKwhM78BAMBH+AEM="
limits = { form = "10MiB" }
default
區塊會覆寫掉欄位的預設值。如果想要針對某個Profile來設定的話,可以直接把Profile的名稱作為區塊名稱,寫進Rocket.toml
設定檔中。
例如:
[default]
workers = 16
limits = { form = "32KiB" }
[debug]
address = "127.0.0.1"
port = 8000
keep_alive = 5
log = "normal"
[release]
address = "0.0.0.0"
port = 80
keep_alive = 10
log = "off"
secret_key = "nPu3M2/h4UOA8kVEpPqH+4KUzLaJKwhM78BAMBH+AEM="
如果要加入自定義的Profile也是可以,也是一樣將Profile名稱作為區塊名稱來撰寫即可,如下:
[my_profile]
port = 12345
secret_key = "nPu3M2/h4UOA8kVEpPqH+4KUzLaJKwhM78BAMBH+AEM="
使用自定義的Profile時,未定義到的項目預設值會使用debug
這個Profile的預設值,請見上表(但secret_key
必須要手動設定)。至於要如何讓Rocket套用為這個Profile,會在下一個小節說明。
用環境變數設定Rocket框架
Rocket的設定項目,都可以使用ROCKET_項目名稱(大寫)
這樣的環境變數命名方式來設定。
例如:
ROCKET_ADDRESS=0.0.0.0
ROCKET_PORT=9958
ROCKET_WORKERS=16
ROCKET_KEEP_ALIVE=0
ROCKET_LOG_LEVEL=debug
ROCKET_SECRET_KEY='nPu3M2/h4UOA8kVEpPqH+4KUzLaJKwhM78BAMBH+AEM='
ROCKET_LIMITS='{form = "10MiB"}'
如果想要更改Profile,則要用ROCKET_PROFILE
這個環境變數。
例如以下指令,可以讓Rocket應用程式以my_profile
環境來執行:
ROCKET_PROFILE=my_profile cargo run
用程式碼來設定Rocket框架
如果我們想要用程式碼來設定Rocket框架的話,程式可以寫成如以下這樣:
#[macro_use]
extern crate rocket;
use rocket::{
config::{Config, LogLevel},
data::{Limits, ToByteUnit},
};
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
#[launch]
fn rocket() -> _ {
let figment = Config::figment()
.merge(("address", "0.0.0.0"))
.merge(("port", 9958))
.merge(("keep_alive", 0))
.merge(("worker", 16))
.merge((
"log_level",
if cfg!(debug_assertions) { LogLevel::Debug } else { LogLevel::Critical },
))
.merge(("secret_key", "nPu3M2/h4UOA8kVEpPqH+4KUzLaJKwhM78BAMBH+AEM="))
.merge(("limits", Limits::new().limit("form", 10.mebibytes())));
rocket::custom(figment).mount("/", routes![index])
}
自訂的項目名稱
Rocket框架的設定檔並不是只能撰寫上述提到的設定項目,如果我們有其它設定值想要透過Rocket框架的設定檔來傳入的話,也是同樣可以用環境變數、設定檔或是程式碼的方式將我們自訂的項目名稱以及設定值傳給Rocket框架。
例如:
[default]
custom = 16384
[release]
custom = 4096
ROCKET_CUSTOM=16384
let figment = Config::figment()
.merge(("custom", if cfg!(debug_assertions) { 16384 } else { 4096 }));
let rocket = rocket::custom(figment);
...
把設定值傳給Rocket框架之後呢?要怎麼在框架內取得?這個就先留到後面的章節再來介紹啦!現階段我們可以用Figment
結構實體提供的extract_inner
方法來取得指定的設定欄位,如以下程式:
#[macro_use]
extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"Hello, world!"
}
#[launch]
fn rocket() -> _ {
let figment = rocket::Config::figment()
.merge(("custom", if cfg!(debug_assertions) { 16384 } else { 4096 }));
println!("custom = {:?}", figment.extract_inner::<u32>("custom"));
rocket::custom(figment).mount("/", routes![index])
}
總結
在這個章節中,我們瞭解了Rocket框架的設定方式。直至目前為止,我們所學的Rocket知識已經足夠完成Web應用程式的開發和部署了。不過,Rocket框架的功能遠遠不只有這些。在下一個章節中,我們要來學習Rocket框架提供的錯誤捕獲者機制。
下一章:錯誤捕獲者(Error Catcher)。