Preface: Introduction to the Rust language
The students who have participated in a large-scale project such as C + + may have experienced the problem of "being" overtime because of NULL Pointer, Memory leak and so on. Don't be depressed, you're not alone, Mozilla Firefox developers have also experienced this problem. Browsers can be said to be the most frequent use of the software, the current mainstream browser is mainly Google Chrome, Internet Explorer, Mozilla Firefox. To enhance the user experience, Mozilla has started a multi-threaded rendering program. However, in the face of large-scale C + + projects, Mozilla developers are not stuck. At this point, rust is in the developer's eyes, compatible with C + + ABI, multi-programming paradigm support, GC-free and unique proprietary systems, hit it off the Mozilla and Rust languages, and quickly launches Mozilla's next-generation browser engine project: servo, So far (August 2018), Servo has become the largest rust project in the community, in addition to the rust compiler itself. Servo has been partially used in versions after Firefox 57.
The rust language is designed to be safe, efficient, concurrent, and practical. Rust solves the following pain points in C + + to some extent:
- Container/Array out-of-bounds access;
- Leakage of dynamic memory allocation and double free problem;
- It is difficult to manage dependencies;
The first two points are the most likely cause of bugs and security issues in C + + projects, and relying on people to examine these issues is often not the best solution. Rust simplifies the object of this study by its unique ownership system, which exposes some obscure issues during compilation. Everything has two sides, due to strict compile-time inspection and engineering implementation of the trade-offs, rust to a certain extent at the expense of the speed of compilation and flexibility, the "flexibility" to abandon does not mean that the rust language performance decline, but when we write the rust program, we may need to change the past ideas.
In the rust circle, there is a joke: "C + + is debugging when you want to wall, and rust is compiled when you want to wall."
Next we will build a basic impression of the ownership system in rust with a simple example.
Core concept: Ownership system
Rust's ownership system consists of three core concepts: ownership, borrowing, and life cycle. Let's start with a simple example to create an intuitive concept of ownership and life cycle.
#[derive (Debug)]
struct Foo;
fn Main () {
let foo = foo; Note:foo not implement Copy trait
Let bar = foo;
println!("{:?}", bar);// println!("{:?}", foo);
}
First we create a variable foo of type Foo, then we execute let bar = foo, and then we try to output the values of the two variables, and if we remove the comment from line 9th, the program will not compile because in rust, for a type that does not implement copy trait, If we assign a binding to another binding, the move semantics are used by default, that is, for any given resource, when and only if there is a variable binding corresponding to it.
To learn more about Rust's little brother xxx sister, you can refer to rust learning
Using rust for HTTP Web backend app development
HTTP Web back-end application development in the rust ecosystem currently relies on two base libraries: HTTP and Hyper, where HTTP provides the basic types of HTTP standards-related, such as request<t>, response<t> and statuscode and common headers, etc. hyper is an efficient, accurate HTTP underlying library that encapsulates HTTP message parsing, message encoding processing, connection control, and so on, for the user to implement an FN-like (Request) Response mapping, you can finish the development of HTTP Web server.
Based on HTTP and hyper, there are many frameworks for Web application development in the community, commonly used:
? Rocket
? Iron
? Actix-web
? Tower-web
It is worth mentioning that Tower-web, released last week, as part of the official net team's 2018 work plan, will provide a flexible, efficient, and easy-to-use web development framework for the rust ecosystem in the future. So without further ado, we get a glimpse of it through a practical walkthrough.
At the end of this month, Tower-web will be integrated into the wrap project as part of the wrap framework and the focus of development will be transferred to wrap.
Practical Walkthrough
Log in to Huawei Cloud and create an ECS as our back-end application server
The system version used in combat is Ubuntu 16.04, and if you choose a different system you need to adjust the command as appropriate.
Installing the associated Toolchain
Apt Update && apt install build-essential
Installing the Rust tool chain
Curl Https://sh.rustup.rs-sSf | Sh
By the end of this step, we can begin to write our app service.
Writing back-end Web Apps
To build a restful Chinese participle API this time, let's start by creating a rust engineering cargo new--bin Chinese_segmentation
Next, add the dependent dependencies in the 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"
Then there is our main.rs, which, like other languages, introduces external dependencies and related declarations in the beginning of the file:
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;
Next we define our service resources 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}
}
Once we have defined our service resources, we define the input and output types of the input Web API:
#[derive (Debug, Extract)]
struct Tokenizerequest {
Text:string
}
#[derive (Debug, Response)]
#[web (status = "200")]//When Handler returns Ok (XX), 200 status code is returned
struct Tokenizeresponse {
Words:vec<string>,
}
So far, we have our service resources, input and output type, next to our play, the Web part of the implementation, do not worry, because it is really simple.
impl_web! {
Impl Chinesetokenizer {
#[post ("/tokenize")]
#[content_type ("Application/json")]
fn tokenize (&self, Body:tokenizerequest), Reqult<tokenizeresponse, () > {
Ok (Tokenizeresponse {
Words:self.cut (&body.text),
})
}
}
}
And finally, here's our main function:
fn Main () {
Initialize 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();
}
Now, let's test our results by ordering Rust_log=chinese_segmentation=info Cargo run--release. After the service runs locally, we can test our interface by ordering Curl-h "Content-type:application/json"-X post-d ' {"text": "Middleware Little Brother"} ' <url>.
After the local test passes, we need to start deploying, and we'll check if the security group of the ECS is in the direction of releasing Port 8081.
API deployment
The API Gateway integrates a range of functions such as monitoring, flow control, load balancing and so on to provide developers with high-performance, highly available API hosting services, and in this practice we deploy our APIs in API gateways.
Log into Huawei Cloud API Gateway service and select "New API"
- Fill in the basic information of the API
In this experiment, select No certification.
Defining API Requests
The request path is filled with/segment, the method is POST
- Defining back-end services
The request mode is set to post and in the VPC channel, we need to create a new VPC channel. The port is set to 8081 and is associated with an elastic cloud server.
Once you have created the VPC channel, go back to the API creation page and fill in the relevant information:
Once the gateway is created, we need to go back to our Elastic cloud server and run our back-end servers first:
Rust_log=chinese_segmentation=info nohup./target/release/chinese_segmentation 2>&1 ~/api.log &
As an example, here we use the Nohup command to run our service. However, in a production environment, it is recommended to use tools such as SYSTEMD to run services.
After the service is running on the cloud server, publish the API to the release environment.
Then we can have fun with our API.
5 minutes Apig Combat: Quickly build APIs with rust language capabilities open