Rust高性能GraphQL路由库apollo-router的使用,Apollo Router为Rust开发者提供灵活可扩展的GraphQL查询分发与缓存功能

Apollo Router Core

Apollo Router

Apollo Router Core 是一个用 Rust 编写的高性能图形路由器,用于运行使用 Apollo Federation 2 的联邦超级图。它经过充分测试,定期进行基准测试,包含 Apollo Gateway 的主要功能,并服务于生产规模的工作负载。

使用 Apollo Router Core 作为库

大多数 Apollo Router Core 功能可以通过 YAML 配置定义,许多自定义可以通过 Rhai 脚本编写,这些脚本适用于已发布的 router 二进制文件,不需要编译。

如果您更喜欢用 Rust 编写自定义或需要更高级的自定义,可以了解如何将 apollo-router 用作 Rust 库。我们还在 crate 文档上发布 Rust 特定的文档。

此版本的 apollo-router 的最低支持 Rust 版本 (MSRV) 是 1.87.0

安装

全局安装

cargo install apollo-router

运行上述命令将全局安装 routersnapshot 二进制文件。

作为库安装

在项目目录中运行以下 Cargo 命令:

cargo add apollo-router

或者将以下行添加到您的 Cargo.toml:

apollo-router = "2.5.0"

完整示例

以下是一个使用 Apollo Router 的完整示例:

use apollo_router::{Router, Schema};
use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // 加载 GraphQL 模式
    let schema = Schema::parse(include_str!("schema.graphql"))?;

    // 创建路由器实例
    let router = Router::builder()
        .schema(schema)
        .build()?;

    // 启动服务器
    router.serve("127.0.0.1:4000".parse()?).await?;

    Ok(())
}
# schema.graphql
type Query {
  hello: String
}

此示例展示了如何:

  1. 加载 GraphQL 模式
  2. 创建一个路由器实例
  3. 启动服务器监听端口 4000

您可以通过添加 YAML 配置文件或 Rhai 脚本来自定义路由器的行为,或者使用原生 Rust 扩展来实现更高级的功能。

更完整示例

下面是一个更完整的 Apollo Router 使用示例,包含自定义插件:

use apollo_router::{Router, Schema, plugins::Plugin, Response};
use std::error::Error;
use tokio::sync::Mutex;
use std::sync::Arc;

// 自定义插件
#[derive(Default)]
struct MyPlugin {
    request_count: Arc<Mutex<u32>>,
}

#[async_trait::async_trait]
impl Plugin for MyPlugin {
    async fn on_request(&self, _request: &apollo_router::Request) -> Result<(), Box<dyn Error>> {
        let mut count = self.request_count.lock().await;
        *count += 1;
        println!("Request count: {}", count);
        Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // 加载 GraphQL 模式
    let schema = Schema::parse(include_str!("schema.graphql"))?;

    // 创建路由器实例并添加自定义插件
    let router = Router::builder()
        .schema(schema)
        .plugin(MyPlugin::default())
        .build()?;

    // 启动服务器
    println!("Server running on http://localhost:4000");
    router.serve("127.0.0.1:4000".parse()?).await?;

    Ok(())
}
# schema.graphql
type Query {
  hello: String
  users: [User]
}

type User {
  id: ID!
  name: String
  email: String
}

这个更完整的示例展示了:

  1. 如何定义一个自定义插件
  2. 如何在插件中跟踪请求计数
  3. 如何将插件添加到路由器
  4. 扩展了 GraphQL 模式
  5. 添加了服务器启动日志

您可以根据需要进一步扩展此示例,例如添加更多自定义插件或实现更复杂的业务逻辑。


1 回复

Rust高性能GraphQL路由库apollo-router使用指南

介绍

Apollo Router是一个用Rust编写的高性能GraphQL路由库,专为构建灵活、可扩展的GraphQL网关而设计。它为Rust开发者提供了强大的查询分发和缓存功能,能够高效地处理GraphQL请求。

主要特性:

  • 高性能:基于Rust构建,提供极低延迟的GraphQL请求处理
  • 可扩展架构:支持自定义插件和中间件
  • 智能查询分发:可路由到不同的后端服务
  • 内置缓存:减少重复计算和网络请求
  • 联邦支持:兼容Apollo Federation规范

安装方法

在Cargo.toml中添加依赖:

[dependencies]
apollo-router = "1.0"
tokio = { version = "1.0", features = ["full"] }

基本使用方法

1. 创建基本路由

use apollo_router::{Router, Schema};
use async_graphql::{EmptyMutation, EmptySubscription, Object, Schema as GraphQLSchema};

struct Query;

#[Object]
impl Query {
    async fn hello(&self) -> String {
        "Hello, Apollo Router!".to_string()
    }
}

#[tokio::main]
async fn main() {
    // 创建GraphQL schema
    let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
    
    // 创建并启动路由器
    let router = Router::builder()
        .schema(schema)
        .build()
        .unwrap();
    
    router.run().await.unwrap();
}

2. 配置路由端点

use apollo_router::{Router, Schema, Endpoint};

// ...之前的Query定义...

#[tokio::main]
async fn main() {
    let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
    
    let router = Router::builder()
        .schema(schema)
        .endpoint(Endpoint::from("/graphql"))
        .endpoint(Endpoint::from("/api").disable_graphql_playground())
        .build()
        .unwrap();
    
    router.run().await.unwrap();
}

3. 添加缓存层

use apollo_router::{Router, Schema, cache::InMemoryCache};

// ...之前的Query定义...

#[tokio::main]
async fn main() {
    let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
    
    let cache = InMemoryCache::new();
    
    let router = Router::builder()
        .schema(schema)
        .cache(cache)
        .build
        .unwrap();
    
    router.run().await.unwrap();
}

高级功能

1. 自定义插件

use apollo_router::{Router, Schema, Plugin, Request, Response};
use std::task::{Context, Poll};
use tower::Service;

struct LoggingPlugin;

impl Plugin for LoggingPlugin {
    fn name(&self) -> &'static str {
        "logging-plugin"
    }
}

impl<S> Service<Request> for LoggingPlugin
where
    S: Service<Request, Response = Response>,
{
    type Response = S::Response;
    type Error = S::Error;
    type Future = S::Future;

    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, req: Request, next: S) -> Self::Future {
        println!("Received request: {:?}", req);
        next.call(req)
    }
}

#[tokio::main]
async fn main() {
    let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
    
    let router = Router::builder()
        .schema(schema)
        .plugin(LoggingPlugin)
        .build()
        .unwrap();
    
    router.run().await.unwrap();
}

2. 联邦服务支持

use apollo_router::{Router, federated::FederatedRouter};

#[tokio::main]
async fn main() {
    let router = FederatedRouter::builder()
        .subgraph("accounts", "http://localhost:4001/graphql")
        .subgraph("reviews", "http://localhost:4002/graphql")
        .subgraph("products", "http://localhost:4003/graphql")
        .build()
        .unwrap();
    
    router.run().await.unwrap();
}

性能调优

use apollo_router::{Router, Schema, cache::InMemoryCache};

#[tokio::main]
async fn main() {
    let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
    
    let cache = InMemoryCache::with_capacity(1024); // 设置缓存容量
    
    let router = Router::builder()
        .schema(schema)
        .cache(cache)
        .query_plan_cache_size(512) // 查询计划缓存大小
        .worker_threads(4) // 工作线程数
        .build()
        .unwrap();
    
    router.run().await.unwrap();
}

完整示例

下面是一个结合了基本路由、缓存和自定义插件的完整示例:

use apollo_router::{Router, Schema, Plugin, Request, Response, cache::InMemoryCache};
use async_graphql::{EmptyMutation, EmptySubscription, Object};
use std::task::{Context, Poll};
use tower::Service;

// 定义查询结构体
struct Query;

#[Object]
impl Query {
    async fn version(&self) -> String {
        "1.0.0".to_string()
    }

    async fn server_info(&self) -> String {
        "Apollo Router Server".to_string()
    }
}

// 自定义日志插件
struct RequestLogger;

impl Plugin for RequestLogger {
    fn name(&self) -> &'static str {
        "request-logger"
    }
}

impl<S> Service<Request> for RequestLogger
where
    S: Service<Request, Response = Response>,
{
    type Response = S::Response;
    type Error = S::Error;
    type Future = S::Future;

    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&mut self, req: Request, next: S) -> Self::Future {
        println!("[RequestLogger] Incoming request to path: {}", req.uri().path());
        next.call(req)
    }
}

#[tokio::main]
async fn main() {
    // 创建GraphQL schema
    let schema = Schema::build(Query, EmptyMutation, EmptySubscription).finish();
    
    // 创建内存缓存
    let cache = InMemoryCache::with_capacity(512);
    
    // 构建路由器
    let router = Router::builder()
        .schema(schema)
        .cache(cache)
        .plugin(RequestLogger)
        .endpoint("/graphql")
        .worker_threads(2)
        .build()
        .unwrap();
    
    println!("Server running at http://localhost:4000/graphql");
    router.run().await.unwrap();
}

总结

Apollo Router为Rust开发者提供了一个高性能、可扩展的GraphQL路由解决方案。通过简单的API,开发者可以快速构建GraphQL网关,并利用其强大的缓存、插件和联邦功能来优化GraphQL服务的性能和可维护性。

回到顶部