Design and Implementation of a High-Performance Backend Gateway Using Spring WebFlux and Nacos
This article details the design, architecture, implementation, testing, and performance evaluation of a high‑throughput Java gateway built with Spring WebFlux, Netty, and Nacos, covering custom routing, load balancing, canary releases, and data synchronization mechanisms.
1. Introduction
After reading the design of the Soul gateway on GitHub, I decided to build a high‑performance gateway from scratch. After two weeks the core functions of ship‑gate are completed, but the lack of a management UI is a drawback.
2. Design
2.1 Technology selection
The gateway is the entry point for all requests, so high throughput is required. Two common asynchronous solutions are:
Tomcat/Jetty + NIO + Servlet3 (Servlet3 already supports async; used by JD, Youzan, Zuul)
Netty + NIO (used by Vipshop with >300k QPS, but requires manual HTTP handling)
Because Soul gateway is based on Spring WebFlux (which uses Netty underneath) and abstracts HTTP handling, I chose Spring WebFlux.
The gateway also needs extensibility (pre‑filters, post‑filters) and service discovery. I selected Nacos as the registration center.
2.2 Feature list
Custom routing rules – support version‑based routing with DEFAUL, HEADER and QUERY match types and =, regex, like operators.
Cross‑language – HTTP is language‑agnostic.
High performance – Netty provides high‑throughput and caching of routing data in JVM.
High availability – stateless cluster mode.
Canary release – gray release with A/B testing.
Interface authentication – plug‑in based auth.
Load balancing – support random, round‑robin, weighted round‑robin via SPI.
2.3 Architecture
The system is divided into modules such as ship‑client‑spring‑boot‑starter, ship‑server, ship‑admin, etc. (diagram omitted).
2.4 Database schema
Schema diagram (omitted).
3. Implementation
3.1 ship‑client‑spring‑boot‑starter
Creates a Spring Boot starter named ship-client-spring-boot-starter . The core class AutoRegisterListener registers service information to Nacos and notifies ship‑admin on startup.
public class AutoRegisterListener implements ApplicationListener
{ ... }3.2 ship‑server
Implements dynamic routing via a WebFilter that builds a plugin chain. The PluginFilter parses the app name from the URL and assembles enabled plugins such as DynamicRoutePlugin and AuthPlugin .
public class PluginFilter implements WebFilter { ... }The PluginChain executes plugins sequentially.
public class PluginChain extends AbstractShipPlugin { ... }Core interfaces ShipPlugin define order() , name() , and execute() .
public interface ShipPlugin { Integer order(); String name(); Mono
execute(ServerWebExchange exchange, PluginChain chain); }3.3 Data synchronization
Ship‑admin periodically pushes instance weight and enabled plugins to Nacos via NacosSyncListener . Ship‑server pulls the data and updates local caches.
@Configuration public class NacosSyncListener implements ApplicationListener
{ ... }A WebSocket‑based cache sync transfers routing rules from admin to server.
public class WebsocketSyncCacheServer extends WebSocketServer { ... }4. Testing
4.1 Dynamic routing test
Deploy Nacos, ship‑admin, and two ship‑example instances with different versions. Add a header‑based routing rule (header name=ship → version gray_1.0). A POST request with the header is routed only to the gray instance.
4.2 Performance test
On a MacBook Pro (2.3 GHz i7, 16 GB RAM) using wrk with 20 threads and 500 connections, the gateway achieves about 9,400 requests per second.
5. Conclusion
Building a gateway is not as hard as it seems; the first step is the most important. The source code is available on GitHub.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.