最近在做一个微信小游戏的后台,需要使用websocket与小游戏端建立连接,实时推送数据,小游戏后台是一个单体spring boot项目,管理玩家的一些基础信息和游戏配置信息,起初在这个单体项目中加入了websocket,可以做到统计实时在线数量,并由后端主动推送消息给小游戏端。
后来发现当后台因为一些业务逻辑改动需要重新发版或业务服务出现异常需要重启时,会导致已有的websocket连接全部断开,所以决定将websocket服务独立出来,原本的业务服务与websocket服务解耦,两个服务通过http进行简单的交互。后期随着业务逻辑复杂度上升,可以考虑改用spring cloud,以微服务形式治理。
业务服务负责:玩家登录、玩家信息管理、游戏配置管理、系统公告等业务逻辑处理。
webscoket服务负责:创建socket连接、在线人数统计、上下线通知、公告推送、服务运行状态管理等。
玩家上下线
两个服务间通过HTTP协议交互,在两个服务中配置对方的IP端口及接口地址,小游戏端与websocket服务建立连接时,传入玩家id,woesocket服务将玩家id与socket session本地存储,并调用业务服务对应的上线、下线接口。后台服务做相应的逻辑处理。
@Component
@ServerEndpoint("/socket/{gamerId}")
public class WebSocketServer {
// 后台服务接口,spring 注入
private static CallbackService callBackService;
@Autowired
public void setGamerService(CallbackService callBackService) {
WebSocketServer.callBackService = callBackService;
}
//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
private static final ConcurrentHashMap<String, GamerSessionInfo> sessionPools = new ConcurrentHashMap<>();
//建立连接成功调用
@OnOpen
public void onOpen(Session session, @PathParam(value = "gamerId") String gamerId) {
GamerSessionInfo gamerSessionInfo = new GamerSessionInfo();
gamerSessionInfo.setGamerId(gamerId);
gamerSessionInfo.setSession(session);
gamerSessionInfo.setOnlineTime(new Date());
// 本地存储session
sessionPools.put(gamerId, gamerSessionInfo);
// 调用后台服务的上线接口
callBackService.onOpen(gamerId);
}
//关闭连接时调用
@OnClose
public void onClose(Session session, @PathParam(value = "gamerId") String gamerId) {
// 移除本地存储session
sessionPools.remove(gamerId);
// 调用后台服务下线接口
callBackService.onClose(gamerId);
}
}
公告推送
当业务服务需要推送消息时,调用websocket提供的消息发送http接口,传入要发送的内容,传入gamerId。
websocket服务提供以下接口,收到后台服务对以下接口的调用后,根据本地存储的session发送消息给小游戏前端。
@RestController
@RequestMapping(value = "/api/socket-server")
public class SocketController {
// 消息推送接口
@PostMapping("/message/send")
public void sendMessage(@RequestBody GamerSocketMessage gamerSocketMessage) {
WebSocketServer.sendMessage(gamerSocketMessage.getGamerId(),gamerSocketMessage.getMessage());
}
// 消息群发接口
@PostMapping("/message/broadcast")
public void broadcastMessage(@RequestBody SocketMessage socketMessage) {
WebSocketServer.broadcastMessage(socketMessage);
}
}
服务器状态管理
websocket服务本地维护一个业务服务状态标志,取值为“正常”或“异常”,小游戏前端在启动后,登录前首先连接到websocket服务,websocket服务此时自动给前端推送一条业务服务运行状态消息,若不是正常运行状态,则小游戏端提示服务正在维护,反之进入登录流程。
状态标志更新机制如下:
1、心跳轮询:业务服务提供一个无返回值的get接口,websocket服务轮询定时调用,每30秒调用一次,超时时间设置为3秒,若请求正常且响应状态码为200,则表示业务服务运行正常,标志位置为“正常”。反之,则将标志位置为“异常”。
2、主动通知:websocket服务提供一个标志位修改接口,业务服务在启动和停止时,调用此修改接口,启动时修改为“正常”,停止时修改为“异常”。
使用此方式开发的微信小游戏已上线,欢迎体验~