在Rust生態中進行HTTP Web後端應用開發目前主要依賴兩個基礎庫:http 以及hyper,其中 http 提供HTTP標準相關的基礎類型,如Request<T> 、Response<T>以及StatusCode和經常使用的Header等;hyper的定位是一個高效、準確的 HTTP底層庫,它封裝了HTTP的報文解析、報文編碼處理、鏈接控制等內容,對於用戶而言 只須要實現一個相似於Fn(Request) -> Response的映射,就能夠完HTTP Web服務端的開 發。git
基於http以及hyper,社區中還有不少用於Web應用開發的框架,經常使用的有:github
值得一提的是上週剛發佈的tower-web,由於這是官方net團隊2018年工做計劃的一部分, 這個庫在將來會爲Rust生態提供一個靈活、高效、易於使用的Web開發框架。那麼事不宜遲, 咱們經過實戰演練來一睹爲快。web
在本月月底,tower-web將會集成到wrap項目中,成爲wrap框架的一部分,開發的重心將會轉移到wrap上。json
登陸華爲雲,並建立彈性雲服務器做爲咱們的後端應用 服務器後端
實戰中使用的系統版本爲Ubuntu 16.04,若是選擇不一樣的系統須要根據狀況調整命令。api
apt update && apt install build-essential
# 安裝Rust工具鏈
curl https://sh.rustup.rs -sSf | sh安全
這一步結束後,咱們就能夠開始編寫咱們的應用服務了。服務器
此次分享咱們來構建一個RESTful中文分詞API,首先咱們來建立一個Rust工程 cargo new --bin chinese_segmentationapp
接下來在Cargo.toml中添加相關依賴負載均衡
[dependencies]
tower-web = "0.2"
# Jieba Chinese Work Segmentation
jieba-rs = "0.2"
# logging utils
log = "0.4.0"
env_logger = "0.5.12"
# Serializing responses, deserializing requests
serde = "1.0.70"
而後是咱們的main.rs,與其餘語言同樣,在文件開始的部分引入外部依賴以及相關聲明:
extern crate jieba_rs;
#[macro_use]
extern crate tower_web;
#[macro_use]
extern crate log;
extern crate env_logger;
use std::iter::FromIterator;
use std::collections::HashSet;
use jieba_rs::Jieba;
use tower_web::ServiceBuilder;
接下來咱們定義咱們的服務資源ChineseTokenizer:
#[derive(Debug)]
struct ChineseTokenizer {
inner: Jieba,
}
impl ChineseTokenizer {
pub fn new() -> ChineseTokenizer {
ChineseTokenizer { inner: Jieba::new() }
}
// 對傳入的字符串進行分詞,並返回一個字符串向量
pub fn cut(&self, text: &String) -> Vec<String> {
let words = self.inner.cut(&text, true)
.into_iter()
.map(|word| word.to_owned())
.collect::<HashSet<String>>();
let mut words = Vec::from_iter(words.into_iter());
// 因爲使用HashSet進行去重會引入不肯定性,
// 所以對結果進行重排,使輸出的結果有序。
words.sort();
words
}
}
定義了咱們的服務資源後,咱們來定義輸入Web API的輸入輸出類型:
#[derive(Debug, Extract)]
struct TokenizeRequest {
text: String
}
#[derive(Debug, Response)]
#[web(status = "200")] // 當 handler 返回 Ok(xx) 時,返回 200 狀態碼
struct TokenizeResponse {
words: Vec<String>,
}
到目前爲止,咱們已經有了咱們的服務資源,輸入輸出類型,接下來就到咱們的重頭戲了, Web 部分的實現,別擔憂,由於真的很簡單。
impl_web! {
impl ChineseTokenizer {
#[post("/tokenize")]
#[content_type("application/json")]
fn tokenize(&self, body: TokenizeRequest) -> Reqult<TokenizeResponse, ()> {
Ok(TokenizeResponse {
words: self.cut(&body.text),
})
}
}
}
最後是咱們的main函數:
fn main() {
// 初始化Logger
env_logger::init();
let addr = "0.0.0.0:8081".parse().expect("invalid address");
info!("listening on http://{}", addr);
ServiceBuilder::new()
.resource(ChineseTokenizer::new()) // 註冊咱們的服務資源
.run(&addr) // 讓咱們的服務跑起來
.unwrap();
}
如今,咱們經過命令RUST_LOG=chinese_segmentation=info cargo run --release來檢驗 一下咱們的成果了。服務在本地跑起來以後,咱們能夠經過命令 curl -H "Content-Type: application/json" -X POST -d '{"text":"中間件小哥"}' <url> 來測試一下咱們的接口。
本地測試經過以後,就須要着手開始部署了,咱們檢查一下彈性雲服務器的安全組的入方向 是否放開8081端口。
API 網關集成了監控、流控、負載均衡等一系列功能,爲開發者提供高性能、高可用的API 託管服務,在本次實踐中,咱們將咱們的API部署在API網關中。
登陸華爲雲API網關服務,選擇「新建API」
在本次實驗中,選擇無認證。
請求路徑填爲 /segment,方法爲 POST
請求方式設置爲POST,在VPC通道這一項中,咱們須要新建VPC通道。端口設置爲8081, 並將其與彈性雲服務器關聯。
建立完VPC通道後,回到API建立頁面,填入相關信息:
網關建立完成後,咱們須要回到咱們的彈性雲服務器,將咱們的後端服務器先跑起來:
RUST_LOG=chinese_segmentation=info nohup ./target/release/chinese_segmentation 2>&1 ~/api.log &
做爲示例,這裏使用nohup命令來跑咱們的服務。但在生產環境中,建議使用 systemd等工具來跑服務。
服務在雲服務器運行起來以後,將API發佈至RELEASE環境中。
而後咱們就能夠和咱們的API愉快地玩耍啦。