關(guān)于Rust和GraphQL

GraphQL簡介

GraphQL是一種開源的數(shù)據(jù)查詢和操作語言,同時也是一種運(yùn)行時,用于根據(jù)客戶端的查詢返回數(shù)據(jù)。它最初由Facebook于2012年開發(fā),并于2016年公開發(fā)布。相比傳統(tǒng)的REST API,GraphQL為客戶端提供了更大的靈活性。客戶端可以明確指定所需的數(shù)據(jù),避免了返回冗余字段的問題。

如今,Netflix、SpotifyShopify等許多知名公司都在使用GraphQL來構(gòu)建API。特別是聯(lián)邦GraphQL API(由多個微服務(wù)組成的大型超圖)極大地提升了靈活性,使團(tuán)隊能夠獨(dú)立開發(fā),同時為客戶端提供了統(tǒng)一的接口。

Rust簡介

Rust是一種靜態(tài)類型的系統(tǒng)編程語言,能夠編譯為高效的機(jī)器代碼。它的運(yùn)行速度與C和C++相當(dāng),同時提供了現(xiàn)代化的語言特性和強(qiáng)大的生態(tài)系統(tǒng)。Rust以其安全性和性能著稱,是構(gòu)建高效系統(tǒng)的理想選擇。


準(zhǔn)備工作

在開始之前,請確保您已安裝Rust工具鏈(推薦使用 rustup)。此外,建議使用Rust版本 1.72.0 或更高版本。您可以通過以下命令檢查當(dāng)前安裝的Rust版本:

rustc --version

設(shè)置項目

  1. 打開終端,導(dǎo)航到您希望存放項目的目錄。
  2. 創(chuàng)建一個新文件夾并進(jìn)入該文件夾:
    mkdir rust_graphql_api && cd rust_graphql_api
  3. 使用Cargo創(chuàng)建一個新的Rust項目:
    cargo new --bin rust_graphql_api
    cd rust_graphql_api

固定Rust版本

為確保項目的穩(wěn)定性,創(chuàng)建一個名為 rust-toolchain.toml 的文件,并添加以下內(nèi)容:

[toolchain]
channel = "1.72.0"
components = ["rustfmt", "clippy"]

此文件將固定Rust版本并啟用代碼格式化工具 rustfmt 和代碼檢查工具 clippy

配置格式化和Lint規(guī)則

創(chuàng)建 .rustfmt.toml 文件并添加以下內(nèi)容:

edition = "2021"
newline_style = "Unix"

同時,為 clippy 創(chuàng)建配置文件 .clippy.toml

cognitive-complexity-threshold = 30

完成后,您可以使用以下命令格式化代碼并檢查代碼質(zhì)量:

cargo fmt --all
cargo clippy --all-targets --all-features

創(chuàng)建Web服務(wù)器

Cargo.toml 中添加以下依賴項:

[dependencies]
axum = "0.6"
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }

然后,在 src/main.rs 中實現(xiàn)一個基本的HTTP服務(wù)器:

use axum::{routing::get, Router};
use std::net::SocketAddr;

#[tokio::main]
async fn main() {
 let app = Router::new().route("/health", get(health_check));

 let addr = SocketAddr::from(([127, 0, 0, 1], 8000));
 println!("Listening on {}", addr);
 axum::Server::bind(&addr)
 .serve(app.into_make_service())
 .await
 .unwrap();
}

async fn health_check() -> &'static str {
 "OK"
}

運(yùn)行以下命令啟動服務(wù)器:

cargo run

打開瀏覽器訪問 http://localhost:8000/health,您將看到返回的 OK 響應(yīng)。


添加GraphQL支持

Cargo.toml 中添加以下依賴項:

[dependencies]
async-graphql = "5.0"
async-graphql-axum = "5.0"

定義GraphQL模式

src/model/mod.rs 中添加以下代碼:

use async_graphql::{Context, Object};

pub struct QueryRoot;

#[Object]
impl QueryRoot {
 async fn hello(&self, _ctx: &Context) -> &str {
 "Hello, GraphQL!"
 }
}

配置GraphQL路由

src/routes/mod.rs 中添加以下代碼:

use async_graphql::{Schema, EmptyMutation, EmptySubscription};
use async_graphql_axum::{GraphQLRequest, GraphQLResponse};
use axum::response::Html;

use crate::model::QueryRoot;

pub async fn graphql_handler(schema: Schema, req: GraphQLRequest) -> GraphQLResponse {
 schema.execute(req.into_inner()).await.into()
}

pub async fn graphql_playground() -> Html {
 Html(async_graphql::http::playground_source("/graphql"))
}

src/main.rs 中注冊GraphQL路由:

use async_graphql::{Schema, EmptyMutation, EmptySubscription};
use axum::{routing::get, Router};

use crate::routes::{graphql_handler, graphql_playground};
use crate::model::QueryRoot;

#[tokio::main]
async fn main() {
 let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription).finish();

 let app = Router::new()
 .route("/graphql", get(graphql_playground).post(graphql_handler))
 .layer(async_graphql::extensions::ApolloTracing);

 let addr = SocketAddr::from(([127, 0, 0, 1], 8000));
 println!("GraphQL Playground: http://{}", addr);
 axum::Server::bind(&addr)
 .serve(app.into_make_service())
 .await
 .unwrap();
}

啟動服務(wù)后,訪問 http://localhost:8000/graphql,即可使用GraphQL Playground測試查詢。


添加指標(biāo)和跟蹤

集成Prometheus指標(biāo)

Cargo.toml 中添加以下依賴項:

[dependencies]
metrics = "0.17"
metrics-exporter-prometheus = "0.17"

src/observability/metrics.rs 中實現(xiàn)Prometheus指標(biāo)記錄器:

use metrics_exporter_prometheus::PrometheusBuilder;

pub fn setup_metrics() {
 PrometheusBuilder::new()
 .install()
 .expect("failed to install Prometheus recorder");
}

main.rs 中調(diào)用 setup_metrics 并添加 /metrics 路由。

添加OpenTelemetry跟蹤

Cargo.toml 中添加以下依賴項:

[dependencies]
tracing = "0.1"
tracing-subscriber = "0.3"
opentelemetry = "0.18"

src/observability/tracing.rs 中配置OpenTelemetry:

use opentelemetry::sdk::trace as sdktrace;
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::Registry;

pub fn setup_tracing() {
 let tracer = sdktrace::Tracer::builder().build();
 let telemetry = tracing_opentelemetry::layer().with_tracer(tracer);

 let subscriber = Registry::default().with(telemetry);
 tracing::subscriber::set_global_default(subscriber).expect("setting tracing default failed");
}

main.rs 中調(diào)用 setup_tracing


容器化服務(wù)

創(chuàng)建 .dockerignore 文件:

target

創(chuàng)建 Dockerfile

FROM rust:1.72 as builder
WORKDIR /usr/src/app
COPY . .
RUN cargo build --release

FROM debian:buster-slim
COPY --from=builder /usr/src/app/target/release/rust_graphql_api /usr/local/bin/
CMD ["rust_graphql_api"]

構(gòu)建并運(yùn)行容器:

docker build -t rust_graphql_api .
docker run -p 8000:8000 rust_graphql_api

總結(jié)

通過本指南,您已經(jīng)成功完成以下任務(wù):

恭喜您完成了這一切!繼續(xù)探索Rust和GraphQL的更多可能性吧!


原文鏈接: https://oliverjumpertz.com/blog/how-to-build-a-powerful-graphql-api-with-rust/

上一篇:

使用 Rails 構(gòu)建 RESTful API

下一篇:

使用Rust構(gòu)建高性能REST API
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個渠道
一鍵對比試用API 限時免費(fèi)

#AI深度推理大模型API

對比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費(fèi)