RUST有毒乳丰,如何從零開始到接入微服務(wù)集群 第一章

前言

RUST:

  • 適合編程初學(xué)者學(xué)習(xí)内贮、當前適合當團隊的語言選型對象、優(yōu)雅
  • 適合學(xué)習(xí)夜郁、適合準備什燕、適合強迫癥、適合
缺點
  • 1 上手困難竞端,相對其他語言有較復(fù)雜的語法和理念屎即,門檻比較高
  • 2 有很多獨有表達式,可讀性較差
  • 3 嚴格的語法限制婶熬,如作用域剑勾、生命周期等,學(xué)習(xí)成本高
  • 4 目前版本不統(tǒng)一赵颅,stable和nightly版本區(qū)別較大
  • 5 不好做語言遷移虽另,生態(tài)還不完全
優(yōu)點
  • 1 有毒,容易上癮
  • 2 社區(qū)開發(fā)速度快饺谬,現(xiàn)在是個學(xué)習(xí)的好時候捂刺,目前,保持著每 6 周更新一次的節(jié)奏募寨。Rust 發(fā)布的工具鏈包括了 stable族展、betanightly 三種不同版本。 nightly 是最激進的版本拔鹰,包含了大量(可能不穩(wěn)定)的新/高級特性仪缸。stable 版本目前可能還不支持一些高級特性。beta 介于兩者之間列肢。
  • 3 從語言層面就減少各種開銷和數(shù)據(jù)競爭恰画,更加安全
  • 4 性能

參考資料

官方中文網(wǎng)站
crates 庫類搜索
簡體中文文檔
語法基礎(chǔ)教程
RUST 特性分析 by austenliao
Rust中文社區(qū)
tokio文檔
Rocket文檔

必看語法

借用和引用
匹配
模式
生命周期
更多...

目錄

  • 安裝RUST
  • hello world
  • 使用第三方庫
  • 測試socket stream
  • 搭建http服務(wù)
  • 數(shù)據(jù)庫操作
  • 與golang的壓測對比
  • 接入基于consul的grpc微服務(wù)集群

一 安裝RUST

  • 下載
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  • 激活環(huán)境
source $HOME/.cargo/env
  • 檢查是否安裝成功
$ cargo --version
cargo 1.38.0 (23ef9a4ef 2019-08-20)

cargo 命令介紹

  • cargo build 可以構(gòu)建項目
  • cargo run 可以運行項目
  • cargo test 可以測試項目
  • cargo doc 可以為項目構(gòu)建文檔
  • cargo publish 可以將庫發(fā)布到 crates.io宾茂。

二 helloworld

$ cargo new myhello
  • 生成的文件結(jié)構(gòu)
$ tree
.
├── Cargo.toml
└── src
    └── main.rs
//main.rs
fn main() {
    println!("Hello, world!");
}

//Cargo.toml
[package]
name = "myhello"
version = "0.1.0"
authors = ["root"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
  • 運行
$ cargo run
Compiling myhello v0.1.0 (/mnt/hgfs/winwork/rust/myhello)
error: linker `cc` not found
  |
  = note: No such file or directory (os error 2)

error: aborting due to previous error

error: Could not compile `myhello`.

To learn more, run the command again with --verbose.
  • 失敗了,新裝的虛擬機環(huán)境不夠完全,注意最好換成aliyun的源再繼續(xù)
$ sudo apt install build-essential
  • 再次運行拴还,成功
$ cargo run
   Compiling myhello v0.1.0 (/mnt/hgfs/winwork/rust/myhello)
    Finished dev [unoptimized + debuginfo] target(s) in 0.54s
     Running `target/debug/myhello`
Hello, world!

三 簡單使用第三方庫

  • 參照官方示例跨晴,使用ferris-says庫,用來畫個say hi的小人
// main.rs
use ferris_says::say; // from the previous step
use std::io::{stdout, BufWriter};

fn main() {
    let stdout = stdout();
    let out = b"Hello fellow Rustaceans!";
    let width = 24;
    let mut writer = BufWriter::new(stdout.lock());
    say(out, width, &mut writer).unwrap();
}
# Cargo.toml中加入
[dependencies]
ferris-says = "0.1"
# 編譯 后可在target目錄中找到可執(zhí)行文件
$ cargo build
# 或者直接運行
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 1.79s
     Running `target/debug/myhello`
----------------------------
| Hello fellow Rustaceans! |
----------------------------
              \
               \
                  _~^~^~_
              \) /  o o  \ (/
                '_   -   _'
                / '-----' \

四 測試socket stream

  • 當我們需要寫功能的時候片林,可以從crates.io 可以搜索需要用到的庫
image.png

注意:
Documentation 會指向官方文檔網(wǎng)站
Repository 會指向github

  • tokio 異步編程框架是使用人數(shù)較多的框架端盆,不僅是引用量和下載量都是最高的,而且是官方支持的項目。但是rust生態(tài)目前還不是很完善费封,因此很多項目都不穩(wěn)定焕妙,從github中可以看到

NOTE: Tokio's master is currently undergoing heavy development. This branch and the alpha releases will see API breaking changes and there are currently significant performance regressions that still need to be fixed before the final release. Use the v0.1.x branch for stable releases.

  • 根據(jù)官方的start文檔 修改Cargo.toml 和 main.rs
[dependencies]
tokio = "0.1"
extern crate tokio;

use tokio::io;
use tokio::net::TcpStream;
use tokio::prelude::*;

fn main() {
    // Parse the address of whatever server we're talking to
    let addr = "127.0.0.1:6142".parse().unwrap();
    let client = TcpStream::connect(&addr).and_then(|stream| {
        println!("created stream");
        // Process stream here.
        io::write_all(stream, "hello world\n").then(|result| {
            println!("wrote to stream; success={:?}", result.is_ok());
            Ok(())
        })
    }).map_err(|err| {
        // All tasks must have an `Error` type of `()`. This forces error
        // handling and helps avoid silencing failures.
        // In our example, we are only going to log the error to STDOUT.
        println!("connection error = {:?}", err);
    });

    println!("About to create the stream and write to it...");
    tokio::run(client);
    println!("Stream has been created and written to.");
}
  • 先用 nc 啟動6142端口的監(jiān)聽進程, 然后運行cargo run 可以看到以下狀態(tài)
$ nc -l -p 6142
hello world
$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 3.90s
     Running `target/debug/myhello`
About to create the stream and write to it...
created stream
wrote to stream; success=true
Stream has been created and written to.

五 搭建一個http restful服務(wù)

  • 這里我們直接使用框架rocket弓摘,類似于node中的express, go里面的gin等。
  • 推薦先讀rocket api文檔
  • 注意 需要使用nightly版本
$ rustup default nightly
$ rustc --version
rustc 1.40.0-nightly (aa69777ea 2019-10-29)
新建項目
$ cargo new management
  • main.rs代碼:
#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}
  • 運行
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 2m 28s                                                          │root@cowkeysu1:/mnt/hgfs/winwork/rust/Rocket# cd ..
     Running `target/debug/management`                                                                                  │root@cowkeysu1:/mnt/hgfs/winwork/rust# cd ..
 Configured for development.                                                                                          │root@cowkeysu1:/mnt/hgfs/winwork# mv^C
    => address: localhost                                                                                               │root@cowkeysu1:/mnt/hgfs/winwork# ls
    => port: 8000                                                                                                       │faf  go  go1.12.12.linux-amd64.tar.gz  ocr  rust  ziliao
    => log: normal                                                                                                      │root@cowkeysu1:/mnt/hgfs/winwork# cd rust/
    => workers: 2                                                                                                       │root@cowkeysu1:/mnt/hgfs/winwork/rust# s
    => secret key: generated                                                                                            │cd s: command not found
    => limits: forms = 32KiB                                                                                            │root@cowkeysu1:/mnt/hgfs/winwork/rust# ls
    => keep-alive: 5s                                                                                                   │hello  myrust  Rocket  rustover
    => tls: disabled                                                                                                    │root@cowkeysu1:/mnt/hgfs/winwork/rust# cd rustover/
  Mounting /:                                                                                                         │root@cowkeysu1:/mnt/hgfs/winwork/rust/rustover# ls
    => GET / (index)                                                                                                    │management  myhello
 Rocket has launched from http://localhost:8000
  • 調(diào)用測試
$ curl http://127.0.0.1:8000
hello,world!
  • 加入GET、POST的方法
    下面的代碼只有不到50行势决,不過很容易出錯蓝撇,主要難點還是在rust語法以及Rocket框架的處理上
  • main.rs 代碼:
#![feature(proc_macro_hygiene, decl_macro)]
#[macro_use] 
extern crate rocket;
#[macro_use] 
extern crate rocket_contrib;
#[macro_use] 
extern crate serde;

use serde::{Serialize, Deserialize};
use rocket::response::status;
use rocket::response::{self,Responder,Response};
use std::io::Cursor;
use rocket::http::{Status, ContentType};
use rocket::request::Request;
use rocket_contrib::json::Json;
use serde_json::json;


#[derive(Serialize)]
struct User {
    id : usize,
    name : String,
    age : i32,
    updated : i64,
}

impl<'r> Responder<'r> for User {
    fn respond_to(self, _: &Request) -> response::Result<'r> {
        Response::build()
            .sized_body(Cursor::new(json!(self).to_string()))
            .header(ContentType::new("application", "json"))
            .ok()
    }
}

#[post("/user/<id>")]
fn addUser(id: usize) -> status::Accepted<String> {
    status::Accepted(Some(format!("id: '{}'", id)))
}

//fn getUser(id: usize) -> Json<User> {
#[get("/user/<id>")]
fn getUser(id: usize) -> User {
    User{
        id:id,
        name:"cowkeys".to_string(),
        age:27,
        updated:0
    }
}

fn main() {
    rocket::ignite().mount("/", routes![addUser,getUser]).launch();
}
  • 運行
$ Cargo run
 Configured for development.
    => address: 0.0.0.0
    => port: 8000
    => log: normal
    => workers: 2
    => secret key: generated
    => limits: forms = 32KiB
    => keep-alive: 5s
    => tls: disabled
  Mounting /:
    => POST /user/<id> (addUser)
    => GET /user/<id> (getUser)
 Rocket has launched from http://0.0.0.0:8000
  • 測試調(diào)用
// GET
curl http://localhost:8000/user/1
id: '1'
// POST
curl -X POST http://localhost:8000/user/1
{"age":19,"id":1,"name":"cowkeys","updated":0}
  • 控制臺會出現(xiàn):
GET /user/1:
    => Matched: GET /user/<id> (getUser)
    => Outcome: Success
    => Response succeeded.
GET /user/1:
    => Matched: GET /user/<id> (getUser)
    => Outcome: Success
    => Response succeeded.
  • 到此渤昌,http服務(wù)完成。
總結(jié)

本文介紹了RUST的基礎(chǔ)入門独柑,如何開始使用rust。下篇會從接入數(shù)據(jù)庫開始忌栅,一直到使用grpc接入consul服務(wù)發(fā)現(xiàn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末湖员,一起剝皮案震驚了整個濱河市瑞驱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唤反,老刑警劉巖鸭津,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件读第,死亡現(xiàn)場離奇詭異,居然都是意外死亡怜瞒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門惠窄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漾橙,“玉大人,你說我怎么就攤上這事霜运。” “怎么了淘捡?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長激况。 經(jīng)常有香客問我,道長乌逐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任浙踢,我火速辦了婚禮蹈丸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逻杖。我一直安慰自己,他們只是感情好荸百,可當我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蓝翰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪畜份。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天爆雹,我揣著相機與錄音,去河邊找鬼钙态。 笑死,一個胖子當著我的面吹牛册倒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播驻子,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼脾歧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤司顿,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后大溜,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡座云,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年付材,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厌衔。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖睬隶,靈堂內(nèi)的尸體忽然破棺而出锣夹,到底是詐尸還是另有隱情苏潜,我是刑警寧澤,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布贴唇,位于F島的核電站,受9級特大地震影響滤蝠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜物咳,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一蹄皱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧巷折,春花似錦、人聲如沸锻拘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至推穷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間馒铃,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工区宇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人议谷。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像叶洞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子衩辟,可洞房花燭夜當晚...
    茶點故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內(nèi)容