5分鐘APIG實戰: 使用Rust語言快速構建API能力開放
序言: Rust 語言簡介
參與過 C/C++ 大型專案的同學可能都經歷過因為 Null Pointer 、 Memory Leak 等問題 “ 被 ” 加班了不知道多少個晚上。別沮喪,你不是一個人, Mozilla Firefox 的開發者們同樣經歷過這個問題。瀏覽器可以說是我們日常使用最為頻繁的軟體了,目前主流的瀏覽器主要 有 Google Chrome 、 Internet Explorer 、 Mozilla Firefox 。 為了提升使用者體驗, Mozilla 就已經啟動了多執行緒渲染的計劃。然而,面對大型的 C/C++ 工程, Mozilla 的開發者們也堅持不住了。此時, Rust 進入了開發者的眼中,與 C/C++ ABI 相容、多程式設計正規化支援、無 GC 及獨特的所有權系統,使得 Mozilla 與 Rust 語言一拍即合,並迅速啟動了 Mozilla 的下一代瀏覽器引擎專案: ,到目前為止( 2018 年 8 月), servo 已經成為了除 Rust 編譯器自身外,社群中最大的 Rust 專案。 servo 目前已經部 分應用在 Firefox 57 之後的版本中。
Rust 語言的設計目標是安全、高效、併發以及實用性。 Rust 從一定程度上解決了 C++ 的以 下痛點:
1. 容器 / 陣列越界訪問;
2. 動態記憶體分配的洩露與 double free 問題;
3. 難以對依賴進行管理;
其中前兩點在 C/C++ 專案中是最容易引發 Bug 以及安全問題的原因,依靠人來對這些問題進行檢查往往不是最佳的解決方案。 Rust 透過其獨特的所有權系統, 簡化 這個所研究的物件,使得一些隱晦的問題在編譯期間便暴露出來。任何事情都是有兩面性的,由於嚴格的編譯期檢查以及工程實現上的取捨, Rust 在一定程度上犧牲了編譯速度以及靈活性,對 “ 靈活性 ” 的捨棄並不代表 Rust 語言的表現力下降,只是我們在編寫 Rust 程式時,可能需要 改變一下以往的思路。
在 Rust 圈子中,有一句調侃: “C++ 是除錯的時候想撞牆,而 Rust 是編譯的時候想撞牆 ” 。
接下來我們將透過一個簡單的例子來建立 Rust 中所有權系統的一個基本印象。
Rust 的所有權系統包括三個核心概念:所有權、借用以及生命週期。我們首先來透過一個 簡單的例子來建立對所有權以及生命週期的直觀概念。
#[derive(Debug)]
struct Foo;
fn main() {
let foo = Foo; // Note: Foo not implement Copy trait
let bar = foo;
println!("{:?}", bar);
// println!("{:?}", foo);
}
首先建立了一個 Foo 型別的變數 foo ,然後我們執行 let bar = foo; ,然後我們嘗試 輸出這兩個變數的值,如果我們將第 9 行的註釋去掉,程式將無法透過編譯,這是因為在 Rust 中,對於沒有實現 Copy trait 的型別,如果我們將一個繫結賦給另一個繫結,預設 使用的是 move 語義,也即對於任意給定的資源,當且僅當有一個變數繫結與之對應。
想要進一步學習 Rust 的小哥哥小姐姐,可以參考
進行 HTTP Web 後端應用開發
在 Rust 生態中進行 HTTP Web 後端應用開發目前主要依賴兩個基礎庫: 以及 ,其中 http 提供 HTTP 標準相關的基礎型別,如 Request<T> 、 Response<T> 以及 StatusCode 和常用的 Header 等; hyper 的定位是一個高效、準確的 HTTP 底層庫,它封裝了 HTTP 的報文解析、報文編碼處理、連線控制等內容,對於使用者而言 只需要實現一個類似於 Fn(Request) -> Response 的對映,就可以完 HTTP Web 服務端的開 發。
基於 http 以及 hyper ,社群中還有很多用於 Web 應用開發的框架,常用的有:
•
•
•
•
值得一提的是上週剛釋出的 tower-web ,因為這是官方 net 團隊 2018 年工作計劃的一部分, 這個庫在未來會為 Rust 生態提供一個靈活、高效、易於使用的 Web 開發框架。那麼事不宜遲, 我們透過實戰演練來一睹為快。
在本月月底, tower-web 將會整合到 專案中,成為 wrap 框架的一部分,開發的重心將會轉移到 wrap 上。
登入公有云 ,並建立彈性雲伺服器作為我們的後端應用 伺服器
實戰中使用的系統版本為 Ubuntu 16.04 ,如果選擇不同的系統需要根據情況調整命令。
apt update && apt install build-essential
#
安裝
Rust
工具鏈
curl -sSf | sh
這一步結束後,我們就可以開始編寫我們的應用服務了。
應用
這次分享我們來構建一個 RESTful 中文分詞 API ,首先我們來建立一個 Rust 工程 cargo new --bin chinese_segmentation
接下來在 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”
1. 填寫 API 的基本資訊
在本次實驗中,選擇無認證。
1. 定義 API 請求
請求路徑填為 /segment ,方法為 POST
1. 定義後端服務
請求方式設定為 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 愉快地玩耍啦。
上述公有云以華為云為具體案例,有興趣可以上去體驗一下~ https://www.huaweicloud.com/product/apig.html
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31543630/viewspace-2212716/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 實戰逆向RUST語言程式Rust
- Rust語言快速安裝指南Rust
- Express 實戰(六):構建 API 介面ExpressAPI
- [實戰] 使用 MongoDB Go 驅動與 Iris 構建 RESTful APIMongoDBRESTAPI
- Go語言實戰(三)- 內建容器Go
- 使用 Rust 語言編寫 Java JNI 實現RustJava
- 使用Rust語言實現帕斯卡三角Rust
- 使用Rust語言實現基本影像識別Rust
- 文盤rust--使用 Rust 構建RAGRust
- Kotlin實戰:使用DSL構建結構化API去掉冗餘的介面方法KotlinAPI
- Dart語言——45分鐘快速入門(下)Dart
- Dart語言——45分鐘快速入門(上)Dart
- PHP熟手使用Rust作為後端開發語言PHPRust後端
- Go 語言實戰: 編寫可維護 Go 語言程式碼建議Go
- GO 語言 Web 開發實戰一GoWeb
- [譯] Go 語言實戰: 編寫可維護 Go 語言程式碼建議Go
- 《從零構建前後分離的web專案》實戰 -5分鐘快速構建炒雞規範的VUE專案骨架WebVue
- 帶讀 |《Go in Action》(中文:Go語言實戰) 語法和語言結構概覽(三)Go
- 帶讀 |《Go in Action》(中文:Go語言實戰)語法和語言結構概覽 (二)Go
- Go 語言實戰 GraphQLGo
- 使用 Rust、OpenAI 和 Qdrant 構建 Agentic RAGRustOpenAI
- 【語言】Java 日期 API 的使用技巧JavaAPI
- 如何快速構建服務發現的高可用能力
- HMS Core在MWC2022展示最新開放能力,助力開發者構建精品應用
- 以太坊Solidity程式語言開發框架————15、構建流程Solid框架
- Dapr + .NET Core實戰(十三)跨語言開發
- Apache Dubbo 社群召集 Rust 語言開發者ApacheRust
- 使用go語言開發自動化API測試工具GoAPI
- WAIC | 騰訊開放百餘項AI能力 深入AI戰略三層架構AI架構
- Rust語言4歲了 | rust-langRust
- 如何構建設計語言系統
- GO 語言快速開發入門Go
- Go語言SQL操作實戰GoSQL
- 實戰 | 使用 Kotlin Flow 構建資料流 "管道"Kotlin
- Rust 語言學習之旅Rust
- 使用Rust和WebAssembly構建Web應用程式RustWeb
- 有Go語言實戰培訓班嗎?go語言開發環境搭建Go開發環境
- 使用 Mux, Go, PostgreSQL, GORM 構建 APIUXGoSQLORMAPI