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

前言

RUST:

  • 適合編程初學(xué)者學(xué)習(xí)、當(dāng)前適合當(dāng)團隊的語言選型對象、優(yōu)雅
  • 適合學(xué)習(xí)、適合準(zhǔn)備、適合強迫癥、適合
缺點
  • 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ā)布的工具鏈包括了 stablebetanightly 三種不同版本。 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

  • 當(dāng)我們需要寫功能的時候,可以從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)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,978評論 2 374

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