The Way is Nature, The Nature is The Way

English 中文

Apache ShenYu: 现代化的API网关解决方案

Published on: 周二 10 六月 2025

Apache ShenYu: 现代化的API网关解决方案

在微服务架构日益流行的今天,API网关作为微服务生态系统中的核心组件,扮演着越来越重要的角色。本文将介绍Apache ShenYu,一个功能强大的Java原生API网关,我有幸参与了该项目的开发和维护。

API网关的重要性

在微服务架构中,API网关承担着以下关键职责:

  • 请求路由:将请求转发到相应的微服务
  • 负载均衡:分散请求负载到多个服务实例
  • 协议转换:支持不同协议之间的转换(如HTTP到gRPC)
  • 认证授权:集中管理访问控制
  • 限流熔断:保护后端服务免受流量冲击
  • 监控日志:收集请求和性能指标

Apache ShenYu简介

Apache ShenYu是一个高性能、可扩展的Java原生API网关,专为微服务架构设计。它提供了丰富的功能集,包括:

核心功能:
- 动态流量控制
- 灰度发布
- 服务治理
- 多协议支持(HTTP, WebSocket, Dubbo, gRPC, Spring Cloud等)
- 插件化架构
- 高性能

架构设计

Apache ShenYu采用了模块化的架构设计,主要包括以下几个组件:

  1. Gateway Core: 核心网关引擎
  2. Admin Console: 管理控制台
  3. Sync Data: 配置同步模块
  4. Plugin System: 插件系统

Apache ShenYu架构

插件系统

ShenYu的一个显著特点是其灵活的插件系统。所有功能都以插件形式提供,可以根据需要进行组合和配置。

public class RateLimiterPlugin extends AbstractShenyuPlugin {

    private final RateLimiterHandler rateLimiterHandler;

    @Override
    public Mono<Void> execute(final ShenyuPluginChain chain, final ServerWebExchange exchange) {
        final ShenyuContext shenyuContext = exchange.getAttribute(Constants.CONTEXT);
        final RuleData rule = plugin.matchRule(exchange, handle.getSelector(), handle.getRuleData());
        return rateLimiterHandler.doRateLimit(exchange, chain, rule)
                .flatMap(result -> {
                    if (result) {
                        return chain.execute(exchange);
                    }
                    return ShenyuResponseUtils.error(exchange, "rate limit exceeded");
                });
    }

    @Override
    public int getOrder() {
        return PluginEnum.RATE_LIMITER.getCode();
    }

    @Override
    public String named() {
        return PluginEnum.RATE_LIMITER.getName();
    }
}

性能表现

在性能测试中,ShenYu展现了卓越的性能:

测试环境:
- 8核CPU,16GB内存
- 1000并发连接,持续60秒

测试结果:
- QPS: 20,000+
- 平均响应时间: 5ms
- 99%响应时间: 15ms
- CPU使用率: 65%

这样的性能足以满足大多数企业级应用的需求。

Rust客户端

作为ShenYu生态的一部分,我参与开发了ShenYu Rust Client项目。这是一个Rust实现的ShenYu客户端,允许Rust应用程序无缝集成到ShenYu网关生态系统中。

use axum::routing::post;
use axum::{routing::get, Router};
use shenyu_client_rust::axum_impl::ShenYuRouter;
use shenyu_client_rust::ci::_CI_CTRL_C;
use shenyu_client_rust::config::ShenYuConfig;
use shenyu_client_rust::core::ShenyuClient;
use shenyu_client_rust::IRouter;

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

async fn create_user_handler() -> &'static str {
    "User created"
}

#[tokio::main]
async fn main() {
    // Spawn a thread to listen for Ctrl-C events and shutdown the server
    std::thread::spawn(_CI_CTRL_C);
    // Initialize tracing
    tracing_subscriber::fmt::init();

    let app = ShenYuRouter::<()>::new("shenyu_client_app")
        .nest("/api", ShenYuRouter::new("api"))
        .route(
            "/health",
            &format!("{}::{}", env!("CARGO_PKG_NAME"), stringify!(health_handler)),
            get(health_handler),
        )
        .route(
            "/users",
            &format!(
                "{}::{}",
                env!("CARGO_PKG_NAME"),
                stringify!(create_user_handler)
            ),
            post(create_user_handler),
        );
    let config = ShenYuConfig::from_yaml_file("config.yml").unwrap();
    let client = ShenyuClient::new(config, app.app_name(), app.uri_infos(), 3000).unwrap();

    let axum_app: Router = app.into();
    client.register().expect("TODO: panic message");

    // Start Axum server
    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, axum_app)
        .with_graceful_shutdown(async move {
            tokio::signal::ctrl_c()
                .await
                .expect("failed to listen for event");
            client.offline_register();
        })
        .await
        .unwrap();
}

结论

Apache ShenYu作为一个强大而灵活的API网关解决方案,正在被越来越多的企业和组织采用。它的高性能、可扩展性和丰富的功能集使其成为微服务架构中不可或缺的组件。

如果您正在寻找一个功能完备的API网关,Apache ShenYu绝对值得考虑。欢迎加入ShenYu社区,一起为项目做出贡献!