这里依赖以下第三方库组件来构建第一个游戏网关:
lombok: 节约GET|SET开发流程spring-boot: 基础依赖注入组件logback: 更新版本日志组件, spring-boot 老版本需要覆盖避免漏洞spring-boot-websocket:WebSocket传输层pekko:akka的开源替代actor模型
jvm 语言其实选择比较, 按照个人喜好就行了:
java: 老牌语言实现, 稳定性和兼容性最好groovy: 动态脚本语言, 支持 jvm 的动态热更新scala: 携带大量语法糖且高度抽象的实现编程语言语言kotlin:JetBrains官方直接支持, 开发效率很不错
实际上还是建议还是采用 Java 语言作为编程语言, 因为大部分商业游戏都是挂靠 Unity3d+C# 实现,
而 C# 大部分语法都是和 Java 近似, 所以有时候服务端+客户端有时候业务繁忙的时候客户互相帮忙编写.
另外还有
pekko挂载quickjs|lua虚拟来做动态热更新, 这种方式也能兼容游戏客户端如果采用双端脚本的方案
在正式进入之前需要说明下服务器架构选择流程:
# 1. 转发服务集群
客户端(TCP) ------|
|
|
| ------- [(同进程) NettyTCP -> GatewaActor (startProxy) ] ------- AuthorityActor
|
| ----------------------------------- WorldActor
| ----------------------------------- PlayerActor
# 2. 多端集群服务
客户端(TCP) ------|
|
| ------- [(同进程) NettyTCP -> NettyGatewaActor (startProxy) ]
|
|----- AuthorityShardingActor-A,...
|----- WorldShardingActor-A,...
|----- PlayerShardingActor-A,...
|
| ------- [(同进程) SpringBootWS->WSGatewaActor (startProxy) ]
|
客户端(WebSocket)-|
# 3. 跨端树状集群
客户端(TCP) ------|
|
|
| -------- [(TCP进程)NettyTCP-A -> WSClusterActor(startProxy)]
| -------- [(TCP进程)NettyTCP-B -> WSClusterActor(startProxy)]
|
|
[(内网分片转发网关)ShardingGatway-A] |----- AuthorityActor-A,...
[(内网分片转发网关)ShardingGatway-B] ---|----- WorldActor-A,...
[(内网分片转发网关)ShardingGatway-C] |----- PlayerActor-A,...
|
|
| -------- [(WS进程)SpringBootWS-A -> WSClusterActor(startProxy)]
| -------- [(WS进程)SpringBootWS-B -> WSClusterActor(startProxy)]
|
|
客户端(WebSocket)-|
第一套方案是常见 分区分服 游戏服务端转发架构, 好处就是 客户端端点(endpoint) 可以依赖分服来让压力分流,
通过实时确认服务器状态将人数爆满的服务器A分流到服务器B, 也是经过市场检验最多的架构设计.
第二套是以 世界服 概念把 数据传输层+网关服务 两者集成在一起, 支持多端互通让其操作交互
第三套方案也是以 世界服 概念把业务依赖集群散布在多台内网服务器上, 通过把业务分类让玩家直接让其直接互通而无需选服,
同时因为 传输层(tcp|udp|websocket) 抽离出来方便实现跨端交互( h5-websocket网页端, tcp-pc客户端 ).
第一套相对简单且方便后续扩展, 但是后续需要维护服务合服来避免某台服务器完全闲置,
也就是日常需要操作 合服滚服 避免死区导致服务器空置(总不能单台服务器支持不到10个人游玩).
第二套方案抛弃了选服概念, 让服务器尽可能针对业务运行在不同服务器上, 传输层分布在独立的服务器上并且挂载 actor 代理服务;
这样好处就是需要再把心力花费在 停服-合服 这种流程上.
第三套方案因为扩展大量集群设备, 所以每条数据会出现比较复杂转发路径(客户端进程 <-> 网络进程 <-> 内网网关 <-> 业务集群), 不过好处就是可以调动大量服务器来做运算, 对于后续动态扩容也十分有利.
还有种情况就是
CPU密集计算 > 实时转发同步就需要其他设备分布运算, 这种情况可以考虑第三套方案
如果不确定后续架构扩展的话, 其实还是选择 分区分服 这种默认方案准没错, 对于游戏服务尽可能减少内网转发(转发不超过三层).
推荐采用 多项目管理 来管理多个项目, 方便后续扩展出来的继承相同配置, 同时还方便组件统一编写在 common 之中
这里采用
maven来做组件设置(pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.meteorcat.fusion</groupId>
<packaging>pom</packaging>
<description>Java游戏网关服务游戏</description>
<!-- fusion-framework 作为主要多项目父框架名 -->
<artifactId>fusion-framework</artifactId>
<!-- 版本号我喜欢采用Y.m.d做区分, 方便确定哪一天需求当作版本 -->
<version>2024.4.19-SNAPSHOT</version>
<!-- 全局属性 -->
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>3.3.10</spring-boot.version>
<maven-compiler.version>3.13.0</maven-compiler.version>
<lombok.version>1.18.36</lombok.version>
<!-- pekko Actor -->
<pekko.version>1.1.3</pekko.version>
<scala.binary.version>2.13</scala.binary.version>
<logback.version>1.5.18</logback.version>
</properties>
<!-- 子模块定义 -->
<modules>
</modules>
<!-- 管理子项目的依赖 -->
<dependencyManagement>
<dependencies>
<!-- LOMBOK组件 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>${lombok.version}</version>
</dependency>
<!-- pekko 为SLF4J 后端 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring 组件依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- WebSocket依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- pekko Actor -->
<dependency>
<groupId>org.apache.pekko</groupId>
<artifactId>pekko-bom_${scala.binary.version}</artifactId>
<version>${pekko.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 配置子项目第三方库源 -->
<repositories>
<repository>
<id>central</id>
<url>https://maven.aliyun.com/repository/central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>netflix-candidates</id>
<name>Netflix Candidates</name>
<url>https://artifactory-oss.prod.netflix.net/artifactory/maven-oss-candidates</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<!-- 配置公共的插件管理等 -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
这里保存一下提交版本库, 这就是最开始我们的项目初始化, 后续就是准备组件库编写和测试.