Rocket的目標是提供一個高彈性和高可用性的組態配置系統,開發者或是系統管理員可以很輕易地對每一個別的設定項目使用環境變數、設定檔或是程式碼來進行設定。



以設定優先等級來說,寫死在程式碼內的設定值的優先權是最高的。其次是環境變數,最後才是寫在設定檔中的設定值。這篇文章會先從優先權最低的設定方式開始說明。

不過在開始說明設定方式之前,先來了解一下Rocket框架到底有哪些項目可以設定吧!

Rocket框架的組態配置

啟動Rocket框架時,Rocket會於標準輸出(stdin)中列出啟動該Rocket應用程式時所使用的組態配置。如下圖所示:

rocket-configuration

Rocket框架定義了以下三種執行環境,用來控制所有設定項目的預設值:

執行環境名稱簡寫描述
developmentdev開發時用的執行環境。
stagingstage應用程式正式部署前的執行環境,可以用來進行整合測試或系統測試。
productionprod應用程式正式部署時的執行環境。

Rocket框架的主要可設定項目如下表:

項目名稱類型預設值(dev)預設值(stage)預設值(prod)功用
address字串(主機名稱或IP位址)localhost0.0.0.00.0.0.0Rocket框架啟動時要監聽的網路介面(主機名稱或IP位置)。
port整數(16位元的無號整數)800080008000Rocket框架啟動時要監聽的TCP連接埠。
keep_alive整數(32位元的無號整數,表示秒數)555是否開啟HTTP的keep-alive機制,0為不開啟;超過0表示要keep-alive的秒數。不過Rocket現階段對於keep-alive機制的支援是有點問題的。
workers整數(大於零且為16位元的無號整數)程式執行環境的邏輯CPU核心數量再乘上2倍。執行緒池(Thread Pool)所使用的執行緒數量。
log字串(offcriticalnormaldebug)normalnormalcritical設定Log的輸出層級。愈靠近debug層級的話,輸出的Log愈多。
secret_key字串(256位元的Base64資料)由Rocket框架於啟動時隨機產生。用來作為基於Cookie的會話(Cookie-based Session)等需加密時的場合所使用的密鑰。在使用production執行環境時,這個項目的值應由系統管理員手動設定,確保每個應用程式實體都是使用一樣的密鑰。
limits表格(欄位的值皆為大於零且為64位元的無號整數,表示位元組){forms = 32768}{forms = 32768}{forms = 32768}針對不同的請求類型,來限制Rocket框架在讀取每個請求時,最大能讀取前面的幾個位元組。
tls表格(certskey值分別為SSL證書和密鑰的路徑)使Rocket框架能夠提供HTTPS服務。如果不設定的話就只會使用HTTP。Rocket框架所提供的HTTPS功能不建議使用在正式環境中。

關於secret_key的產生,可以直接使用OpenSSL指令來完成。指令如下:

openssl rand -base64 32

rocket-configuration

設定Rocket框架

用設定檔設定Rocket框架

Rocket框架在啟動的時候,預設會去讀取工作目錄中的Rocket.toml檔案,如果這個檔案不存在,就會不斷地往上層目錄中尋找Rocket.toml檔案來用。

Rocket.toml設定檔的撰寫方式很簡單,如下:

[global]
address = "0.0.0.0"
port = 9958
keep_alive = 0
workers = 128
log = "debug"
secret_key = "nKLiGJThxey3v1npBVtXNfr3PQsH50r6c/TSv47nuio="
limits = {forms = 10485760}

global區塊會覆寫掉所有執行環境的設定值。如果想要針對某個執行環境來設定的話,可以直接把執行環境的名稱作為區塊名稱,寫進Rocket.toml設定檔中。

例如:

[development]
address = "localhost"
port = 8000
workers = 16
keep_alive = 5
log = "normal"
limits = { forms = 32768 }

[staging]
address = "0.0.0.0"
port = 8000
workers = 128
keep_alive = 5
log = "normal"
limits = { forms = 32768 }

[production]
address = "0.0.0.0"
port = 80
workers = 128
keep_alive = 10
log = "off"
secret_key = "nKLiGJThxey3v1npBVtXNfr3PQsH50r6c/TSv47nuio="
limits = { forms = 32768 }

用環境變數設定Rocket框架

Rocket的設定項目,都可以使用ROCKET_項目名稱(大寫)這樣的環境變數命名方式來設定。

例如:

ROCKET_ADDRESS=0.0.0.0
ROCKET_PORT=9958
ROCKET_KEEP_ALIVE=0
ROCKET_WORKERS=128
ROCKET_LOG=debug
ROCKET_SECRET_KEY="nKLiGJThxey3v1npBVtXNfr3PQsH50r6c/TSv47nuio="
ROCKET_LIMITS="{forms = 10485760}"

rocket-configuration

如果想要更改執行環境,則要用ROCKET_ENV這個環境變數。

例如以下指令,可以讓Rocket應用程式以production環境來執行:

ROCKET_ENV=prod cargo run

rocket-configuration

用程式碼來設定Rocket框架

在先前學習Rocket的Hello World程式時,我們在建立Rocket的結構實體時,是直接使用Rocket的結構體提供的ignite方法。如果我們想要用程式碼來設定Rocket框架的話,這部份的程式可以改寫成如以下這樣:

use rocket::config::{Config, Environment, LoggingLevel, Limits};

let config = Config::build(if cfg!(debug_assertions) {
        Environment::Development
    } else {
        Environment::Production
    })
    .address("0.0.0.0")
    .port(9958)
    .keep_alive(0)
    .workers(128)
    .log_level(LoggingLevel::Debug)
    .secret_key("nKLiGJThxey3v1npBVtXNfr3PQsH50r6c/TSv47nuio=")
    .limits(Limits::new().limit("forms", 10485760))
    .unwrap();

let rocket = rocket::custom(config);

...

利用Rocket的結構體提供的custom方法,可以傳入開發者自己建立的Config結構實體,來產生Rocket結構實體。

關於Environment列舉實體的建立,如果要以ROCKET_ENV這個環境變數來控制的話,可以使用它所提供的active關聯函數。例如以上程式可以再修改成這樣:

use rocket::config::{Config, Environment, LoggingLevel, Limits};

let config = Config::build(Environment.active().unwrap())
    .address("0.0.0.0")
    .port(9958)
    .keep_alive(0)
    .workers(128)
    .log_level(LoggingLevel::Debug)
    .secret_key("nKLiGJThxey3v1npBVtXNfr3PQsH50r6c/TSv47nuio=")
    .limits(Limits::new().limit("forms", 10485760))
    .unwrap();

let rocket = rocket::custom(config);

...

ROCKET_ENV這個環境變數沒有被設定,會自動去判斷目前程式專案的編譯模式是否為Release,如果不是的話,預設會用Development變體;如果是的話,預設則會用Production變體。

自訂的項目名稱

Rocket框架的設定檔並不是只能撰寫上述提到的設定項目,如果我們有其它設定值想要透過Rocket框架的設定檔來傳入的話,也是同樣可以用環境變數、設定檔或是程式碼的方式將我們自訂的項目名稱以及設定值傳給Rocket框架。

例如:

[development]
custom = 16384

[staging]
custom = 4096

[production]
custom = 4096

[production]
ROCKET_CUSTOM=16384
use rocket::config::{Config, Environment};

let config = Config::build(Environment.active().unwrap())
    .extra("custom", if cfg!(debug_assertions) {
        16384
    } else {
        4096
    })
    .unwrap();

let rocket = rocket::custom(config);

...

把設定值傳給Rocket框架之後呢?要怎麼取得?這個就先留到後面的章節再來介紹啦!

總結

在這個章節中,我們瞭解了Rocket框架的設定方式。直至目前為止,我們所學的Rocket知識已經足夠完成Web應用程式的開發和部署了。不過,Rocket框架的功能遠遠不只有這些。在下一個章節中,我們要來學習Rocket框架提供的錯誤捕獲者機制。

下一章:錯誤捕獲者(Error Catcher)