--- 对外服介绍 ---
无锁异步化、事件驱动的架构设计;真轻量级,无需依赖任何第三方中间件就能搭建出一个分布式的网络通信服务器。
自带负载均衡、分布式支持、可动态增减机器。
| 名称 | 扩展方式 | 职责 |
|---|---|---|
| ExternalServer | 分布式 | 对外服的职责是与用户连接、交互 |
| LogicServer | 分布式 | 逻辑服的职责是处理具体业务逻辑 |
从架构简图中,我们知道了整体架构由对外服和逻辑服组成,两者既可相互独立,又可相互融合。
对外服在架构图位置的左边部分,ExternalServer。
介绍
本篇将介绍对外服这部分,及功能扩展等相关的。
对外服的职责
- 保持与用户(玩家)长的连接。
- 帮助开发者屏蔽通信细节、与连接方式的细节。
- 支持多种连接方式,如 WebSocket、TCP、UDP,并支持扩展。
- 将用户(玩家)请求转发到逻辑服
- 可动态增减机器
- 功能扩展,如
- 路由存在检测。
- 路由权限。
- UserSession 管理。
- 心跳。
- 及后续要提供但还未提供的熔断、限流、降载、用户流量统计等功能。
动态增减机器的场景
的主要职责是与用户的建立长连接。 假如我们的一台硬件支持我们建立用户连接的上限是 5000 人,当用户量达到 7000 人时,我们可以多加一个对外服务器来进行分流减压。
通过增加对外服的数量,可以有效地进行连接的负载均衡和流量控制,使得系统能够更好地承受高并发的压力。 由于对外服扩展的简单性,意味着支持同时在线玩家可以轻松的达到百万、千万甚至更多。
支持的连接方式
框架已提供了 TCP、WebSocket、UDP 连接方式的支持,并提供了灵活的方式来实现连接方式的切换。 连接方式的切换对业务代码没有任何影响,无需做出任何改动即可实现连接方式的更改。
连接方式是可扩展的,这意味着之后如果支持了 KCP、QUIC,那么将已有项目的连接方式, 如 TCP、WebSocket、UDP 切换成 KCP、QUIC 也是简单的。
如何安装
如果你是初次体验或想快速了解框架的,在 pom.xml 添加如下内容,run-one 已经包含了对外服和逻辑服。
<dependency>
<groupId>com.iohao.net</groupId>
<artifactId>run-one</artifactId>
<version>${ionet.version}</version>
</dependency>
通常在实际开发中,比较推荐的做法中单独为对外服创建一个模块,并在 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>
因为随着业务的增加,后续我们可能需要在对外服中做很多扩展,将这些与对外服相关的扩展放到对外服模块中是比较好的组织方式。 这些扩展包括,但不限于以下功能
- 心跳
- 限流
- 缓存
- SSL
- 自定义编解码
- 更多连接方式的支持,如 KCP、QUIC 等
- 以及更多自定义的 Netty Handler
创建对外服
- code 2,创建对外服构建器,并设置连接端口和连接方式。
- code 3,构建对外服。
ExternalServer create() {
var builder = ExternalMapper.builder(ExternalGlobalConfig.externalPort, ExternalJoinEnum.WEBSOCKET);
return builder.build();
}
如何扩展
可以参考下面的文档添加扩展
启动多个对外服
该功能为企业级功能
框架允许开发者使用一套业务代码,同时支持多种连接方式或切换连接方式,这里演示同进程同时支持多种连接方式的技巧。
- code 9 ~ 15,获取对外服列表,每个对外服支持了不同的连接方式,WEBSOCKET、TCP、UDP。
- code 18,coc 原则,根据连接协议生成不同的对外服端口。
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();
}
}