微信截圖_1742455890415.png)
火山引擎如何接入API:從入門到實踐的技術(shù)指南
GraphQL是一種開源的數(shù)據(jù)查詢和操作語言,同時也是一種運(yùn)行時,用于根據(jù)客戶端的查詢返回數(shù)據(jù)。它最初由Facebook于2012年開發(fā),并于2016年公開發(fā)布。相比傳統(tǒng)的REST API,GraphQL為客戶端提供了更大的靈活性。客戶端可以明確指定所需的數(shù)據(jù),避免了返回冗余字段的問題。
如今,Netflix、Spotify、Shopify等許多知名公司都在使用GraphQL來構(gòu)建API。特別是聯(lián)邦GraphQL API(由多個微服務(wù)組成的大型超圖)極大地提升了靈活性,使團(tuán)隊能夠獨(dú)立開發(fā),同時為客戶端提供了統(tǒng)一的接口。
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)的理想選擇。
在開始之前,請確保您已安裝Rust工具鏈(推薦使用 rustup
)。此外,建議使用Rust版本 1.72.0
或更高版本。您可以通過以下命令檢查當(dāng)前安裝的Rust版本:
rustc --version
mkdir rust_graphql_api && cd rust_graphql_api
cargo new --bin rust_graphql_api
cd rust_graphql_api
為確保項目的穩(wěn)定性,創(chuàng)建一個名為 rust-toolchain.toml
的文件,并添加以下內(nèi)容:
[toolchain]
channel = "1.72.0"
components = ["rustfmt", "clippy"]
此文件將固定Rust版本并啟用代碼格式化工具 rustfmt
和代碼檢查工具 clippy
。
創(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
在 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)。
在 Cargo.toml
中添加以下依賴項:
[dependencies]
async-graphql = "5.0"
async-graphql-axum = "5.0"
在 src/model/mod.rs
中添加以下代碼:
use async_graphql::{Context, Object};
pub struct QueryRoot;
#[Object]
impl QueryRoot {
async fn hello(&self, _ctx: &Context) -> &str {
"Hello, 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測試查詢。
在 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
路由。
在 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
。
創(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
通過本指南,您已經(jīng)成功完成以下任務(wù):
恭喜您完成了這一切!繼續(xù)探索Rust和GraphQL的更多可能性吧!
原文鏈接: https://oliverjumpertz.com/blog/how-to-build-a-powerful-graphql-api-with-rust/