SlideShare ist ein Scribd-Unternehmen logo
Backend-Services mit Rust
Jens Siebert (@jens_siebert, @jens_siebert@mastodon.online)
WebMontag Kassel, 07. November 2022
Über mich
• Senior Software Developer bei
doks.innovation in Kassel
• Drohnen-Steuerung, Computer
Vision, Architektur
• Maker, 3D-Drucker, Nerd
Quo vadis, Backend-Entwicklung?
Interpretierte Sprachen:
• Java/JVM-basierte Sprachen: Spring, Micronaut, MicroProfile
• Javascript/Typescript: Node.js, Deno, Express
• Python: Django, Flask
Kompilierte Sprachen:
• Go: Kite, go-kit, go-micro
• Rust: actix-web, rocket, tide, warp, axum
Quo vadis, Backend-Entwicklung?
Interpretierte Sprachen:
• Einfach zu lernen
• Sicherheit durch automatische Speicherverwaltung
• Garbage Collection
• Langsamer Start-up/Just-in-Time Kompilierung
Go:
• Einfach zu lernen
• Sicherheit durch automatische Speicherverwaltung
• Garbage Collection
• Schneller Start-up/Ahead-of-Time Kompilierung
Und Rust?
Rust:
• Nicht ganz so einfach zu lernen
• Sicherheit durch automatische Speicherverwaltung
• Garbage Collection
• Schneller Start-up/Ahead-of-Time Kompilierung
Discord „Read States“ Service
https://discord.com/blog/why-discord-is-switching-from-go-to-rust
Discord „Read States“ Service
https://discord.com/blog/why-discord-is-switching-from-go-to-rust
Discord „Read States“ Service
https://discord.com/blog/why-discord-is-switching-from-go-to-rust
Rust vs. Go? Rust AND Go!
For most companies and users, Go is the right default option. Its performance is strong, Go is
easy to adopt, and Go’s highly modular nature makes it particularly good for situations
where requirements are changing or evolving.
As your product matures, and requirements stabilize, there may be opportunities to have
large wins from marginal increases in performance. In these cases, using Rust to maximize
performance may well be worth the initial investment.
https://thenewstack.io/rust-vs-go-why-theyre-better-together
Web Frameworks für Rust
• actix-web (https://actix.rs)
• rocket (https://rocket.rs)
• tide (https://github.com/http-rs/tide)
• warp (https://github.com/seanmonstar/warp)
• axum (https://github.com/tokio-rs/axum)
Auswahlhilfen:
https://www.lpalmieri.com/posts/2020-07-04-choosing-a-rust-web-framework-2020-edition/
https://github.com/flosse/rust-web-framework-comparison
actix-web Architektur
actix-web
Client
tokio
Operating System
High Performance Asynchronous IO
actix-web Features
• Vollständig asynchron
• HTTP/1.x und HTTP/2
• Request Routing
• Middlewares (Logger, Session, CORS, etc.)
• Transparente (De-)Kompression
• WebSockets
• Streams
• Unterstützung für SSL/TLS
• Unterstützung für Keep-Alive und Slow Requests
• Statische Assets
Hello World!
use actix_web::{web, App, HttpRequest, HttpServer, Responder};
async fn greet(req: HttpRequest) -> impl Responder {
let name = req.match_info().get("name").unwrap_or("World");
format!("Hello {}!", &name)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/", web::get().to(greet))
.route("/{name}", web::get().to(greet))
})
.bind("127.0.0.1:8000")?
.run()
.await
}
Main-Funktion
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/", web::get().to(greet))
.route("/{name}", web::get().to(greet))
})
.bind("127.0.0.1:8000")?
.run()
.await
}
Server-Initialisierung
App-Initialisierung
Route-Mapping
Adress-Bindung
Entry-Point
Handler-Funktion
// Impliziter HttpResponse
async fn greet(req: HttpRequest) -> impl Responder {
let name = req.match_info().get("name").unwrap_or("World");
format!("Hello {}!", &name)
}
// Expliziter HttpResponse
async fn greet(req: HttpRequest) -> Result<HttpResponse, Error> {
let name = req.match_info().get("name").unwrap_or("World");
let body = format!("Hello {}!", &name);
Ok(HttpResponse::Ok().body(body))
}
Datenbankzugriff mit Diesel
• Object Relational Mapper und Query Builder für Rust
• Fokus auf möglichst schlanke Abstraktionen
• Hohe Performance
• Unterstützte Datenbanken:
• MySQL
• PostgreSQL
• SQLite
• …
Datenbankzugriff mit Diesel -- Mapping
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Insertable)]
pub struct User {
pub id: String,
pub name: String
}
Datenbankzugriff mit Diesel -- Verbindung
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let connspec = std::env::var("DATABASE_URL").expect("DATABASE_URL");
let manager = ConnectionManager::<SqliteConnection>::new(connspec);
let pool = r2d2::Pool::builder()
.build(manager)
.expect("Failed to create pool.");
HttpServer::new(move || {
App::new()
.data(pool.clone())
.service(get_user)
.service(add_user)
})
.bind("127.0.0.1:8000")?
.run()
.await
}
Datenbankzugriff mit Diesel -- Insert-Handler
#[post("/user")]
async fn add_user(pool: web::Data<DbPool>, form: web::Json<NewUser>) ->
Result<HttpResponse, Error> {
let conn = pool.get().expect("couldn't get db connection from pool");
let user = web::block(move || insert_new_user(&form.name, &conn))
.await
.map_err(|e| {
eprintln!("{}", e);
HttpResponse::InternalServerError().finish()
})?;
Ok(HttpResponse::Ok().json(user))
}
Datenbankzugriff mit Diesel -- Insert
pub fn insert_new_user(nm: &str, conn: &SqliteConnection,) ->
Result<User, diesel::result::Error> {
use crate::schema::users::dsl::*;
let new_user = User {
id: Uuid::new_v4().to_string(),
name: nm.to_owned()
};
diesel::insert_into(users).values(&new_user).execute(conn)?;
Ok(new_user)
}
Fazit
Rust als Basis für Backend-Services bietet:
• Hohe Performance durch Ahead-of-Time Kompilierung, Zero Cost Abstractions
• Sicheres Speichermanagement bereits während der Kompilierung
• Sichere Nebenläufigkeit
• Keine Einbrüche bei der Performance durch Garbage Collection
• Komfortables Tooling, welches etablierten Sprachen und Frameworks in nichts nachsteht
• Freundliche und hilfsbereite Community
• Teilweise steile Lernkurve (aber es lohnt sich!)
Literatur
Vielen Dank!
https://www.rust-lang.org/learn
https://actix.rs/docs
https://diesel.rs/guides
Twitter: @jens_siebert
Mastodon: @jens_siebert@mastodon.online

Weitere ähnliche Inhalte

PPTX
Microservices mit Rust
Jens Siebert
 
PDF
Webapplikationen mit Node.js
Sebastian Springer
 
PDF
Go - Googles Sprache für skalierbare Systeme
Frank Müller
 
PDF
DevOpsCon - Verteilte Entwicklung in Go
Frank Müller
 
PDF
Node.js für Webapplikationen
Sebastian Springer
 
PDF
Web-Services mit Go
Sebastian Harl
 
PDF
Node.js
Sebastian Springer
 
PDF
WebAssembly
Jens Siebert
 
Microservices mit Rust
Jens Siebert
 
Webapplikationen mit Node.js
Sebastian Springer
 
Go - Googles Sprache für skalierbare Systeme
Frank Müller
 
DevOpsCon - Verteilte Entwicklung in Go
Frank Müller
 
Node.js für Webapplikationen
Sebastian Springer
 
Web-Services mit Go
Sebastian Harl
 
WebAssembly
Jens Siebert
 

Mehr von Jens Siebert (17)

PDF
Embedded Rust
Jens Siebert
 
PDF
Embedded Rust
Jens Siebert
 
PPTX
TinyML – Machine Learning für eingebettete Systeme
Jens Siebert
 
PPTX
Deep Learning mit TensorFlow.js
Jens Siebert
 
PPTX
Chatbots bauen mit dem Microsoft Bot Framework
Jens Siebert
 
PPTX
Integrating The Things Network Applications with Azure IoT Services
Jens Siebert
 
PPTX
GraphQL
Jens Siebert
 
PPTX
Embedded JavaScript
Jens Siebert
 
PPTX
Windows 10 IoT Core
Jens Siebert
 
PPTX
Microsoft Bot Framework (Node.js Edition)
Jens Siebert
 
PPTX
Microsoft Bot Framework (.NET Edition)
Jens Siebert
 
PPTX
Electron
Jens Siebert
 
PPTX
Windows 10 IoT Core
Jens Siebert
 
PPTX
Physical Web
Jens Siebert
 
PPTX
Windows 10 IoT Core
Jens Siebert
 
PPTX
TypeScript
Jens Siebert
 
PPTX
TypeScript
Jens Siebert
 
Embedded Rust
Jens Siebert
 
Embedded Rust
Jens Siebert
 
TinyML – Machine Learning für eingebettete Systeme
Jens Siebert
 
Deep Learning mit TensorFlow.js
Jens Siebert
 
Chatbots bauen mit dem Microsoft Bot Framework
Jens Siebert
 
Integrating The Things Network Applications with Azure IoT Services
Jens Siebert
 
GraphQL
Jens Siebert
 
Embedded JavaScript
Jens Siebert
 
Windows 10 IoT Core
Jens Siebert
 
Microsoft Bot Framework (Node.js Edition)
Jens Siebert
 
Microsoft Bot Framework (.NET Edition)
Jens Siebert
 
Electron
Jens Siebert
 
Windows 10 IoT Core
Jens Siebert
 
Physical Web
Jens Siebert
 
Windows 10 IoT Core
Jens Siebert
 
TypeScript
Jens Siebert
 
TypeScript
Jens Siebert
 
Anzeige

Backend-Services mit Rust

  • 1. Backend-Services mit Rust Jens Siebert (@jens_siebert, @[email protected]) WebMontag Kassel, 07. November 2022
  • 2. Über mich • Senior Software Developer bei doks.innovation in Kassel • Drohnen-Steuerung, Computer Vision, Architektur • Maker, 3D-Drucker, Nerd
  • 3. Quo vadis, Backend-Entwicklung? Interpretierte Sprachen: • Java/JVM-basierte Sprachen: Spring, Micronaut, MicroProfile • Javascript/Typescript: Node.js, Deno, Express • Python: Django, Flask Kompilierte Sprachen: • Go: Kite, go-kit, go-micro • Rust: actix-web, rocket, tide, warp, axum
  • 4. Quo vadis, Backend-Entwicklung? Interpretierte Sprachen: • Einfach zu lernen • Sicherheit durch automatische Speicherverwaltung • Garbage Collection • Langsamer Start-up/Just-in-Time Kompilierung Go: • Einfach zu lernen • Sicherheit durch automatische Speicherverwaltung • Garbage Collection • Schneller Start-up/Ahead-of-Time Kompilierung
  • 5. Und Rust? Rust: • Nicht ganz so einfach zu lernen • Sicherheit durch automatische Speicherverwaltung • Garbage Collection • Schneller Start-up/Ahead-of-Time Kompilierung
  • 6. Discord „Read States“ Service https://discord.com/blog/why-discord-is-switching-from-go-to-rust
  • 7. Discord „Read States“ Service https://discord.com/blog/why-discord-is-switching-from-go-to-rust
  • 8. Discord „Read States“ Service https://discord.com/blog/why-discord-is-switching-from-go-to-rust
  • 9. Rust vs. Go? Rust AND Go! For most companies and users, Go is the right default option. Its performance is strong, Go is easy to adopt, and Go’s highly modular nature makes it particularly good for situations where requirements are changing or evolving. As your product matures, and requirements stabilize, there may be opportunities to have large wins from marginal increases in performance. In these cases, using Rust to maximize performance may well be worth the initial investment. https://thenewstack.io/rust-vs-go-why-theyre-better-together
  • 10. Web Frameworks für Rust • actix-web (https://actix.rs) • rocket (https://rocket.rs) • tide (https://github.com/http-rs/tide) • warp (https://github.com/seanmonstar/warp) • axum (https://github.com/tokio-rs/axum) Auswahlhilfen: https://www.lpalmieri.com/posts/2020-07-04-choosing-a-rust-web-framework-2020-edition/ https://github.com/flosse/rust-web-framework-comparison
  • 12. actix-web Features • Vollständig asynchron • HTTP/1.x und HTTP/2 • Request Routing • Middlewares (Logger, Session, CORS, etc.) • Transparente (De-)Kompression • WebSockets • Streams • Unterstützung für SSL/TLS • Unterstützung für Keep-Alive und Slow Requests • Statische Assets
  • 13. Hello World! use actix_web::{web, App, HttpRequest, HttpServer, Responder}; async fn greet(req: HttpRequest) -> impl Responder { let name = req.match_info().get("name").unwrap_or("World"); format!("Hello {}!", &name) } #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/", web::get().to(greet)) .route("/{name}", web::get().to(greet)) }) .bind("127.0.0.1:8000")? .run() .await }
  • 14. Main-Funktion #[actix_web::main] async fn main() -> std::io::Result<()> { HttpServer::new(|| { App::new() .route("/", web::get().to(greet)) .route("/{name}", web::get().to(greet)) }) .bind("127.0.0.1:8000")? .run() .await } Server-Initialisierung App-Initialisierung Route-Mapping Adress-Bindung Entry-Point
  • 15. Handler-Funktion // Impliziter HttpResponse async fn greet(req: HttpRequest) -> impl Responder { let name = req.match_info().get("name").unwrap_or("World"); format!("Hello {}!", &name) } // Expliziter HttpResponse async fn greet(req: HttpRequest) -> Result<HttpResponse, Error> { let name = req.match_info().get("name").unwrap_or("World"); let body = format!("Hello {}!", &name); Ok(HttpResponse::Ok().body(body)) }
  • 16. Datenbankzugriff mit Diesel • Object Relational Mapper und Query Builder für Rust • Fokus auf möglichst schlanke Abstraktionen • Hohe Performance • Unterstützte Datenbanken: • MySQL • PostgreSQL • SQLite • …
  • 17. Datenbankzugriff mit Diesel -- Mapping #[derive(Debug, Clone, Serialize, Deserialize, Queryable, Insertable)] pub struct User { pub id: String, pub name: String }
  • 18. Datenbankzugriff mit Diesel -- Verbindung #[actix_web::main] async fn main() -> std::io::Result<()> { let connspec = std::env::var("DATABASE_URL").expect("DATABASE_URL"); let manager = ConnectionManager::<SqliteConnection>::new(connspec); let pool = r2d2::Pool::builder() .build(manager) .expect("Failed to create pool."); HttpServer::new(move || { App::new() .data(pool.clone()) .service(get_user) .service(add_user) }) .bind("127.0.0.1:8000")? .run() .await }
  • 19. Datenbankzugriff mit Diesel -- Insert-Handler #[post("/user")] async fn add_user(pool: web::Data<DbPool>, form: web::Json<NewUser>) -> Result<HttpResponse, Error> { let conn = pool.get().expect("couldn't get db connection from pool"); let user = web::block(move || insert_new_user(&form.name, &conn)) .await .map_err(|e| { eprintln!("{}", e); HttpResponse::InternalServerError().finish() })?; Ok(HttpResponse::Ok().json(user)) }
  • 20. Datenbankzugriff mit Diesel -- Insert pub fn insert_new_user(nm: &str, conn: &SqliteConnection,) -> Result<User, diesel::result::Error> { use crate::schema::users::dsl::*; let new_user = User { id: Uuid::new_v4().to_string(), name: nm.to_owned() }; diesel::insert_into(users).values(&new_user).execute(conn)?; Ok(new_user) }
  • 21. Fazit Rust als Basis für Backend-Services bietet: • Hohe Performance durch Ahead-of-Time Kompilierung, Zero Cost Abstractions • Sicheres Speichermanagement bereits während der Kompilierung • Sichere Nebenläufigkeit • Keine Einbrüche bei der Performance durch Garbage Collection • Komfortables Tooling, welches etablierten Sprachen und Frameworks in nichts nachsteht • Freundliche und hilfsbereite Community • Teilweise steile Lernkurve (aber es lohnt sich!)