前言
上一节我们使用自定义注解+反射简化了协议解包和逻辑处理分发流程。
那么到了这里登录服登录服的架构已经搭建的差不多了,一些比较简单的、并发量较低的游戏,希望使用单体服务器,其实就在这LoginServer的基础上继续开发即可。
但是一些需要能支撑高一些并发,并且希望做到能横向扩容的游戏,就需要用到分布式的思想来做。
笔者这边先简单地将其分成 登录服和游戏服。
登录服用于提供客户端信息入口,处理账号鉴权和协议转发的功能。
游戏服用于处理游戏业务的具体逻辑,可以设定不同的游戏服处理不同的功能。比如游戏服A用于跑主城地图的逻辑,游戏服B用于跑副本相关逻辑。
玩家连接到登录服(前面应该还有一层做负载均衡的nginx用来选择一个低负载的登录服),在登录服登录账号,选择一个角色,然后登录服分配一个游戏服将玩家后续协议转发到游戏服中进行处理。
这么做的好处在于,当游戏服的人数变多,一台机器无法支撑,可以随时在其他机器上创建更多的游戏服进程进行扩容。
而当一台服务器crash时,可以将玩家切换到另一台服务器上游玩。
而我们本节内容就是创建一个游戏服GameServer。
正文
首先思考一下GameServer启动需要做些什么。
- 需要与登录服连接以便接受协议转发
- 需要注册协议分发器ProtoDispatcher用于处理业务逻辑
那我们一步一步来。
创建GameServer模块
ctrl+alt+shift+s进入项目设置,选中Modules, 右键根模块创建一个gameServer子模块
创建GameMain.java作为程序入口, 让其继承BaseMain,并启动Spring容器。
@Slf4j
@Component
public class GameMain extends BaseMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(GameBeanConfig.class);
applicationContext.start();
GameMain gameMain = SpringUtils.getBean(GameMain.class);
gameMain.init();
System.exit(0);
}
@Override
protected void handleBackGroundCmd(String cmd) {
}
@Override
protected void initServer() {
}
}
修改配置
现在将登录服的端口配置到common.conf中,注意现在登录服不仅要提供一个对外的端口,还需要一个对内部服务的端口。
# mongo相关
...
# redis相关
...
# 登录服对外host 可以配置多个用逗分隔
login.player_host=127.0.0.1:9999
# 登录服对内host
login.inner_host=127.0.0.1:8888
修改CommonConfig.java
@Getter
@Component
@PropertySource("classpath:common.conf")
public class CommonConfig {
@Value("${mongodb.host}")
String mongoHost;
@Value("${mongodb.user}")
String mongoUser;
@Value("${mongodb.password}")
String mongoPassword;
@Value("${mongodb.login.db}")
String loginDbName;
@Value("${redis.host}")
String redisHost;
@Value("${redis.password}")
String redisPassword;
@Value("${login.player_host}")
String loginPlayerHost;
@Value("${login.inner_host}")
String loginInnerHost;
}
创建NettyClient连接到登录服
还记得我们在做客户端测试代码时使用了NettyClient连接到LoginServer吗?
现在GameServer也需要做一样的事情,我们将代码抽出到common模块中以便复用。
package org.common.netty;
import ...
@Slf4j
@Component
public class NettyClient {
/**
* 连接多个服务
* @param hostStr "127.0.0.1:8081,127.0.0.1:8082"
*/
public HashMap<String, Channel> start(String hostStr, BaseNettyHandler nettyHandler) {
HashMap<String, Channel> map = new HashMap<>();
String[] hostArray = hostStr.split(",");
if (hostArray.length == 0) {
log.error("hostStr split error! hostStr = {}", hostStr);
return map;
}
for (String host : hostArray) {
String[] split = host.split(":");
if (split.length != 2) {
log.error("host list config error! host = {}", host);
return map;
}
String ip = split[0];
int port = Integer.parseInt(split[1]);
Channel c