Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

🌪️ Bus Vortex: High-Performance API Gateway

Distributed, Asynchronous, Scalable, and Lightweight API Gateway


📖 Project Introduction

Bus Vortex is a distributed, fully asynchronous, high-performance, scalable, and lightweight API gateway built on Spring WebFlux. Inspired by Taobao's Open Platform, it stands on the shoulders of the Spring ecosystem to provide enterprise-grade API routing and management capabilities.


✨ Core Features

🎯 Out-of-the-Box Experience

  • Zero Configuration: Start using immediately after adding annotations to your business code
  • Automatic Parameter Validation: Built-in support for JSR-303 internationalized parameter validation
  • Modular Design: Independent implementation of validation and result return functionality for easy customization
  • Annotation-Driven: Simple API definitions using annotations for easy maintenance
  • i18n Support: Built-in internationalization for error messages
  • Digital Signature: Parameter verification using digital signatures
  • Secure Access: Platform access via appKey and secret mechanism

🛡️ Security & Reliability

  • Signature Verification: MD5, AES, RSA encryption algorithms for secure data transmission
  • Rate Limiting: Leaky bucket and token bucket strategies for traffic control
  • Permission Control: RBAC-based permission verification
  • Session Management: Support for both standalone and distributed sessions
  • Authentication: JWT and accessToken support
  • Documentation: Auto-generated API documentation

🌍 Technology Stack

  • Encryption: MD5, AES, RSA
  • Networking: Netty (encoding/decoding, long connections, auto-reconnect)
  • Rate Limiting: Leaky bucket, token bucket algorithms
  • Authorization: RBAC, validation
  • Session: Standalone, distributed session management
  • Documentation: Annotation-based documentation generation
  • Authentication: JWT, accessToken
  • SDK: Java, C#, JavaScript
  • Formats: XML, JSON

🚀 Feature 1: Parameter-Based Routing

API Interface Definition

public class Assets {

    private String id;             // Unique route asset ID
    private String namespace_id;   // Owning namespace
    private Integer type;          // Optional asset type filter, uses Type.key()
    private String app_id;         // Application identifier
    private String method;         // Logical API method name
    private Integer verb;          // HTTP verb code: 1=GET ... 9=CONNECT
    private Integer policy;        // Access policy: 0 anonymous, 1-6 secured
    private Integer sign;          // Signature verification flag
    private String version;        // API version (matches request parameter 'v')
    private String host;           // Target hostname
    private Integer port;          // Target port
    private String path;           // Downstream path prefix
    private String url;            // Target URL / endpoint
    private String description;    // API description
}

Request Parameters

Parameter Description
method API method name (e.g., xxx.xxx.xxx)
v API version number, used with method (e.g., 1.1, 1.2)
namespace Optional namespace route scope
app_id Optional application-specific route scope
type Optional registry type scope. Accepts numeric Type.key() and legacy type names
format Return format (supports json, xml)
sign If decrypt is enabled in config and request contains sign field, decrypt request

Public Route Resolution

  • Runtime candidate chain:
    • namespace:type:app_id:method:version:verb
    • namespace:type:method:version:verb
    • namespace:app_id:method:version:verb
    • namespace:method:version:verb
    • type:app_id:method:version:verb
    • type:method:version:verb
    • app_id:method:version:verb
    • method:version:verb
  • method, version, and verb are required runtime dimensions
  • namespace, type, and app_id are optional route scopes; when absent the corresponding levels are skipped
  • type always uses numeric Type.key() inside route keys
  • verb always uses the numeric verb code rather than GET / POST text
  • ApiAssets.key remains the lightweight public alias method:version:verbCode
  • Registration and lookup share the same candidate chain
  • Lookup stops at the first level that has candidates; if that level resolves to multiple assets, the gateway returns null

verbCode mapping:

  • 1 -> GET
  • 2 -> POST
  • 3 -> HEAD
  • 4 -> PUT
  • 5 -> PATCH
  • 6 -> DELETE
  • 7 -> OPTIONS
  • 8 -> TRACE
  • 9 -> CONNECT

You can override the built-in route-key strategy by providing a Spring Keying<Keying.RegistrySpec> bean. The default implementation is RegistryGenerator, and both bus-cortex and bus-vortex now consume the same Keying<Keying.RegistrySpec> rules.

Configuration File

bus:
  vortex:
    port: 8765                # Gateway port
    path: /router/rest        # Gateway path
    condition: false          # Disable custom MVC condition bridge by default
    limit:
      enabled: true           # Enable rate limiting
    performance:
      max-connections: 5000
      pending-acquire-timeout-seconds: 45
      pending-acquire-max-count: 0  # 0 derives max-connections * 2
      sanitize-null-like-parameters: true

Integration Steps

1. Add @EnableVortex Annotation to Spring Boot Main Class

@EnableVortex
@SpringBootApplication
public class TunnelApplication {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(TunnelApplication.class);
        app.run(args);
    }
}

2. AssetsRegistry Is Auto-Configured

// No custom registry bean is required for the default setup.
// bus-starter/vortex creates AssetsRegistry automatically.

3. Optionally Override the Route-Key Strategy

@Bean
public Keying<Keying.RegistrySpec> registryKeying() {
    return RegistryGenerator.INSTANCE;
}

4. Implement an AuthorizeProvider Bean for Authentication

@Component
public class AuthProviderImpl implements AuthorizeProvider {
    // Override token/apiKey/license as needed
}

5. Configure in application.yml

Extensibility

Implement WebFilter to extend gateway functionality, such as rate limiting, logging, blacklisting, circuit breaking (not yet implemented), etc.

@Component
@Order("123")
public class CustomFilter implements WebFilter {
    // TODO: Implement filter logic
}

🚀 Feature 2: Version-Based Routing

@ApiVersion

Automatically merges a version-prefixed path to RequestMappingInfo. Recommendation: Configure major versions at class level, minor versions can be configured at method level (will override class-level major version).

@ClientVersion

Routes to different handler methods based on cv and terminal parameters in request headers (extends getCustomCondition method in RequestMappingHandlerMapping).

@VersionMapping

Combines RequestMapping functionality with configurations for both @ApiVersion and @ClientVersion.

Business Scenarios

  • ApiVersion: Replaces version-defined paths that require redefining classes or writing conditional logic in code for API upgrades
  • ClientVersion: Elegantly avoids writing extensive version logic when dealing with interfaces already in use by clients

Example Usage

@RequestMapping("/t")
@RestController
@ApiVersion("5")
public class TController {
    // Request path: /4/t/get
    @RequestMapping(value = "/get")
    public String get1() {
        return "Old API";
    }

    // Request path: /5.1/t/get
    @RequestMapping(value = "/get", params = "data=tree")
    @ApiVersion("5.1")
    // Method's @ApiVersion takes precedence over class-level, convenient for minor version upgrades
    public String get2() {
        return "New data";
    }

    // All three request paths are /c,
    // Routes to different methods based on client type in header
    // (can be modified to use URL parameters by changing TerminalVersionExpression)
    @GetMapping("/c")
    @ClientVersion(expression = {"1>6.0.0"})
    public String cvcheck1() {
        return "Type 1 client, version 6.0.0+";
    }

    @GetMapping("/c")
    @ClientVersion({@TerminalVersion(terminals = 2, op = VersionOperator.GT, version = "6.0.0")})
    public String cvcheck2() {
        return "Type 2 client, version > 6.0.0";
    }

    @GetMapping("/c")
    @ClientVersion({@TerminalVersion(terminals = 2, op = VersionOperator.LTE, version = "6.0.0")})
    public String cvcheck3() {
        return "Type 2 client, version <= 6.0.0";
    }
}

Using @VersionMapping

@RestController
@VersionMapping(value = "/t", apiVersion = "5")
public class TController {

    @VersionMapping(value = "a", terminalVersion = @TerminalVersion(terminals = 1, op = VersionOperator.EQ, version = "3.0"))
    public String t() {
        return "5";
    }
}

📋 Quick Start

Maven Dependency

<dependency>
    <groupId>org.miaixz</groupId>
    <artifactId>bus-starter</artifactId>
    <version>x.x.x</version>
</dependency>

Enable Gateway

@EnableVortex
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Configure Application Properties

bus:
  vortex:
    port: 8765
    path: /router/rest
    performance:
      max-connections: 5000
      pending-acquire-timeout-seconds: 45
      pending-acquire-max-count: 0
      sanitize-null-like-parameters: true

Null-like Parameter Sanitization

When bus.vortex.performance.sanitize-null-like-parameters=true, the gateway removes Java null, "null", and "undefined" consistently at request ingestion, context enrichment, and outbound forwarding.

Context#getParameters() preserves the familiar Map usage style, but the returned map is a controlled Parameter instance, so put / putAll / remove still pass through the shared sanitization rules. Query parameters remain read-only.

context.getParameters().put("status", status);
context.getParameters().putAll(payload);
context.putQueryParameter("lang", "en");

💡 Use Cases

  • Microservices Gateway: Unified entry point for microservices architecture
  • API Version Management: Smooth API upgrades with version-based routing
  • Traffic Control: Rate limiting and traffic shaping for high-concurrency scenarios
  • Security Enhancement: Signature verification, encryption, and access control
  • Multi-Tenant Routing: Route requests based on tenant-specific parameters

🔧 Configuration Reference

Core Configuration

Property Type Default Description
bus.vortex.port int 8765 Gateway server port
bus.vortex.path String /router/rest Gateway routing path
bus.vortex.condition boolean false Enable custom Spring MVC condition bridge
bus.vortex.limit.enabled boolean false Enable rate limiting
bus.vortex.performance.max-connections int 5000 Maximum outbound HTTP connection pool size
bus.vortex.performance.pending-acquire-timeout-seconds int 45 Maximum time to wait for a pooled outbound connection
bus.vortex.performance.pending-acquire-max-count int 0 Maximum pending outbound connection acquisitions; 0 derives max-connections * 2
bus.vortex.performance.sanitize-null-like-parameters boolean true Remove null / "null" / "undefined" parameters before routing

🔄 Version Compatibility

Bus Vortex Version Spring Boot Version JDK Version
8.x 3.x+ 17+
7.x 2.x+ 11+

📊 Performance Characteristics

  • Asynchronous Non-Blocking: Built on WebFlux for high concurrency
  • Low Latency: Minimal routing overhead
  • High Throughput: Efficient request handling
  • Scalable: Horizontal scaling support

🛠️ Advanced Topics

Custom Filters

Implement WebFilter for custom request/response processing:

@Component
@Order(1)
public class LoggingFilter implements WebFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
        // Custom logic
        return chain.filter(exchange);
    }
}

Dynamic Routing

Register and update routes dynamically using Registry implementation.

Load Balancing

Integrate with service discovery for automatic load balancing.


❓ FAQ

Q: How to add custom encryption algorithms?

A: Implement the encryption interface and configure it in the application properties.

Q: How to handle high concurrency?

A: Enable rate limiting and configure thread pools appropriately.

Q: Can multiple versions coexist?

A: Yes, use @ApiVersion and @ClientVersion for version-specific routing.


🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.