--- External Server Introduction ---
Lock-free asynchronous and event-driven architecture; truly lightweight. You can build a distributed network communication server without any third-party middleware.
Built-in load balancing, distributed support, and dynamic machine scale-out/scale-in.
| Name | Scaling Mode | Responsibility |
|---|---|---|
| ExternalServer | Distributed | Responsible for user connections and interaction |
| LogicServer | Distributed | Responsible for specific business logic processing |
From this architecture overview, we know the overall architecture consists of external services and logic services. They can run independently or be integrated together.
In the architecture diagram, external server is the left-side part, ExternalServer.
Introduction
This section introduces the external server and related feature extensions.
Responsibilities of external server
- Maintain long connections with users (players).
- Shield communication details and connection-method details from developers.
- Support multiple connection methods such as WebSocket, TCP, UDP, and extensibility.
- Forward user (player) requests to logic servers.
- Dynamically scale machine count up/down.
- Feature extensions, such as:
- Route existence checks.
- Route permissions.
- UserSession management.
- Heartbeat.
- Future features like circuit breaking, rate limiting, load shedding, user traffic stats, etc.
Dynamic machine scaling scenario
Its main responsibility is to maintain long connections with users. Assume one machine supports up to 5000 user connections. When users reach 7000, we can add an external server to split traffic and reduce pressure.
By increasing external server count, connection load balancing and traffic control become effective, allowing the system to better handle high concurrency. Because external server expansion is simple, supporting millions or tens of millions of concurrent players becomes much easier.
Supported connection methods
Framework already supports TCP, WebSocket, and UDP, and provides flexible switching between connection types. Switching connection method has no impact on business code, and requires no business-code changes.
Connection methods are extensible. This means if KCP/QUIC is supported later, existing projects can also switch from TCP/WebSocket/UDP to KCP/QUIC easily.
How to Install
If you are trying the framework for the first time or want a quick overview, add the following to pom.xml. run-one already includes both external and logic servers.
<dependency>
<groupId>com.iohao.net</groupId>
<artifactId>run-one</artifactId>
<version>${ionet.version}</version>
</dependency>
In real projects, it is recommended to create a dedicated module for external server and add this dependency in pom.xml:
see https://central.sonatype.com/artifact/com.iohao.net/external-netty
<dependency>
<groupId>com.iohao.net</groupId>
<artifactId>external-netty</artifactId>
<version>${ionet.version}</version>
</dependency>
As business grows, many external-server extensions may be required. Organizing these extensions in an external-server module is a good approach. These extensions include, but are not limited to:
- Heartbeat.
- Rate limiting.
- Cache.
- SSL.
- Custom codec.
- More connection methods, such as KCP and QUIC.
- More custom Netty Handlers.
Create External Server
- code 2: create external-server builder and set port and connection method.
- code 3: build external server.
ExternalServer create() {
var builder = ExternalMapper.builder(ExternalGlobalConfig.externalPort, ExternalJoinEnum.WEBSOCKET);
return builder.build();
}
How to Extensions
Refer to documents below to add extensions:
- Heartbeat settings and hooks
- User online/offline hooks
- Route access permission control
- WS token authentication/verification
- Custom external-server protocol
- How to extend Netty Handler
- Extend connection methods
Starting Multiple External Servers
This is an enterprise-level feature.
The framework allows one business-code set to support multiple connection methods simultaneously or switch methods. This example demonstrates supporting multiple connection methods in one process.
- code 9~15: get external-server list; each server supports a different method: WEBSOCKET, TCP, UDP.
- code 18: coc principle: generate different external-server ports by protocol.
final class TestOneApplication {
static void main() {
new EnterpriseRunOne()
.setExternalServer(externalServerList)
...
.startup();
}
static List<ExternalServer> listExternalServer() {
return List.of(
ofExternalServer(ExternalJoinEnum.WEBSOCKET)
, ofExternalServer(ExternalJoinEnum.TCP)
, ofExternalServer(ExternalJoinEnum.UDP)
);
}
static ExternalServer ofExternalServer(ExternalJoinEnum join) {
int port = join.cocPort(ExternalGlobalConfig.externalPort);
var externalServerBuilder = MyExternalServer.builder(port, join);
return externalServerBuilder.build();
}
}