Rust异步GraphQL服务器库async-graphql-poem的使用:基于Poem框架的高性能GraphQL接口开发
Rust异步GraphQL服务器库async-graphql-poem的使用:基于Poem框架的高性能GraphQL接口开发
安装
在项目目录中运行以下Cargo命令:
cargo add async-graphql-poem
或者在Cargo.toml中添加以下行:
async-graphql-poem = "7.0.17"
完整示例代码
以下是基于Poem框架开发高性能GraphQL接口的完整示例:
use async_graphql::{
Object, EmptySubscription, Schema,
http::{GraphQLPlaygroundConfig, playground_source},
};
use async_graphql_poem::{GraphQL, GraphQLSubscription};
use poem::{
get, handler, listener::TcpListener,
web::Html, IntoResponse, Route, Server,
};
// 定义查询结构体
struct Query;
// 为Query实现Object trait
#[Object]
impl Query {
// 定义一个简单的hello字段
async fn hello(&self) -> String {
"Hello async-graphql-poem!".to_string()
}
}
// 定义Mutation结构体
struct Mutation;
#[Object]
impl Mutation {
// 定义一个简单的echo字段
async fn echo(&self, message: String) -> String {
message
}
}
// 主函数
#[tokio::main]
async fn main() {
// 创建Schema
let schema = Schema::build(Query, Mutation, EmptySubscription).finish();
// 创建路由
let app = Route::new()
// GraphQL端点
.at("/graphql", post(GraphQL::new(schema.clone())))
// GraphQL订阅端点
.at("/ws", get(GraphQLSubscription::new(schema)))
// GraphQL Playground界面
.at("/", get(handler || async {
Html(playground_source(
GraphQLPlaygroundConfig::new("/graphql")
.subscription_endpoint("/ws"),
))
}));
// 启动服务器
println!("Playground: http://localhost:8000");
Server::new(TcpListener::bind("0.0.0.0:8000"))
.run(app)
.await
.unwrap();
}
代码说明
-
Schema构建:
let schema = Schema::build(Query, Mutation, EmptySubscription).finish();
创建了一个包含Query、Mutation和EmptySubscription的GraphQL Schema。
-
路由配置:
/graphql
: 处理GraphQL查询和变更请求/ws
: 处理GraphQL订阅(WebSocket)/
: 提供GraphQL Playground界面
-
Playground配置:
GraphQLPlaygroundConfig::new("/graphql") .subscription_endpoint("/ws")
配置了GraphQL Playground的查询和订阅端点。
-
服务器启动:
Server::new(TcpListener::bind("0.0.0.0:8000")) .run(app) .await .unwrap();
在8000端口启动Poem服务器。
功能特性
- 高性能异步GraphQL服务器
- 支持查询(Query)、变更(Mutation)和订阅(Subscription)
- 内置GraphQL Playground界面
- 基于Poem框架的轻量级实现
- 支持WebSocket协议用于实时订阅
这个示例展示了如何快速搭建一个功能完整的GraphQL服务器,包含了基本查询、变更功能,并支持订阅和Playground界面。
1 回复
Rust异步GraphQL服务器库async-graphql-poem的使用
简介
async-graphql-poem
是结合了async-graphql
和Poem
框架的Rust库,用于构建高性能的GraphQL服务器。它提供了:
- 完全异步的GraphQL实现
- 基于Poem框架的高性能HTTP服务
- 类型安全的Schema定义
- 支持GraphQL订阅(WebSocket)
- 内置数据加载器(DataLoader)支持
完整示例代码
下面是一个完整的GraphQL服务器示例,包含查询、变更、订阅和DataLoader:
use async_graphql::{
dataloader::DataLoader, Context, EmptyMutation, EmptySubscription,
Object, Schema, SimpleObject, Subscription,
http::{GraphQLPlaygroundConfig, playground_source},
Loader, Result,
};
use async_graphql_poem::GraphQL;
use poem::{
handler, listener::TcpListener, middleware::Cors,
web::Html, Endpoint, EndpointExt, Route, Server,
};
use std::{
collections::HashMap,
sync::Arc,
time::Duration,
};
use tokio::time::interval;
use futures_util::stream::{Stream, StreamExt};
// 定义用户数据结构
#[derive(SimpleObject, Clone)]
struct User {
id: i32,
name: String,
email: String,
}
// 定义消息数据结构
#[derive(SimpleObject)]
struct Message {
content: String,
sender: String,
}
// 查询结构体
struct Query;
#[Object]
impl Query {
// 获取所有用户
async fn users(&self) -> Vec<User> {
vec![
User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
},
User {
id: 2,
name: "Bob".to_string(),
email: "bob@example.com".to_string(),
},
]
}
// 根据ID获取用户
async fn user(&self, id: i32) -> Option<User> {
if id == 1 {
Some(User {
id: 1,
name: "Alice".to_string(),
email: "alice@example.com".to_string(),
})
} else {
None
}
}
}
// 变更结构体
struct Mutation;
#[Object]
impl Mutation {
// 创建用户
async fn create_user(&self, name: String, email: String) -> User {
User {
id: 100,
name,
email,
}
}
}
// 用户数据加载器
struct UserLoader;
#[async_trait::async_trait]
impl Loader<i32> for UserLoader {
type Value = User;
type Error = Arc<String>;
async fn load(&self, keys: &[i32]) -> Result<HashMap<i32, Self::Value>, Self::Error> {
let mut users = HashMap::new();
for &id in keys {
users.insert(id, User {
id,
name: format!("User {}", id),
email: format!("user{}@example.com", id),
});
}
Ok(users)
}
}
// 订阅结构体
struct Subscription;
#[Subscription]
impl Subscription {
// 消息订阅
async fn messages(&self) -> impl Stream<Item = Message> {
let messages = vec![
Message {
content: "Hello".to_string(),
sender: "Alice".to_string(),
},
Message {
content: "Hi there".to_string(),
sender: "Bob".to_string(),
},
];
let mut interval = interval(Duration::from_secs(1));
let mut index = 0;
futures_util::stream::unfold((interval, messages, index), move |(mut interval, messages, mut index)| async move {
interval.tick().await;
if index >= messages.len() {
index = 0;
}
let message = messages[index].clone();
index += 1;
Some((message, (interval, messages, index)))
})
}
}
// GraphQL Playground页面
#[handler]
async fn graphql_playground() -> Html<String> {
Html(playground_source(GraphQLPlaygroundConfig::new("/graphql")))
}
#[tokio::main]
async fn main() {
// 创建Schema
let schema = Schema::build(Query, Mutation, Subscription)
.data(DataLoader::new(UserLoader, tokio::spawn))
.finish();
// 创建路由
let app = Route::new()
.at("/graphql", GraphQL::new(schema))
.at("/", graphql_playground)
.with(Cors::new());
// 启动服务器
println!("GraphQL Playground: http://localhost:8000");
Server::new(TcpListener::bind("0.0.0.0:8000"))
.run(app)
.await
.unwrap();
}
项目结构说明
-
依赖配置:
- 需要添加async-graphql, async-graphql-poem, poem和tokio依赖
- 使用tokio作为异步运行时
-
核心组件:
Query
: 定义GraphQL查询操作Mutation
: 定义GraphQL变更操作Subscription
: 定义GraphQL订阅操作UserLoader
: 实现DataLoader用于批量加载用户数据
-
功能特点:
- 支持查询、变更和订阅三种GraphQL操作类型
- 使用DataLoader解决N+1查询问题
- 内置GraphQL Playground用于测试
- 启用CORS支持跨域请求
-
启动方式:
- 服务启动后可以通过http://localhost:8000访问Playground界面
- GraphQL端点位于/graphql路径