https://github.com/snow-seamless/mykob/tree/38bf415defbe0e320cd188d9c627078957420bb3
6.3 实现匹配系统微服务
项目流程
1. 改变项目结构
- 新建一个
backendcloud
,进行一些配置并添加spring-cloud
依赖 - 新建模块
matchingsystem
,添加一些依赖 - 修改每个模块的端口
- 新建
backend
将之前项目的src
拿过来,配置pom
(与之前项目一样)
2. 编写matchingsystem模块后端
- 添加
MatchingService
的接口,用MatchingServiceImpl
实现接口,再实现一个MatchingController
- 包括添加用户和删除用户
Controller
中的map
要使用MultiValueMap
- 添加
spring-security
依赖进行权限控制,添加config.SecurityConfig
类,只允许本地访问 - 将
Main
改为MatchingSystemApplication
,并加注解@SpringBootApplication
- 使用
SpringApplication.run(MatchingSystemApplication.class, args)
运行
3. 将匹配系统和后端对接
- 将
matchpool
的所有操作放入matchingsystem
- 新建
backend.config.filter.RestTemplate
,添加注解@Bean
,未来使用时直接Autowired
即可,用来在matchingsystem和backend之间进行通信 backend.consumer.WebSocketServer
中向matchingsystem
发送请求- matchingsystem中需要有
controller
和对应的url
4. matchingsystem中实现匹配(多线程)
- 思想:初始玩家只能匹配分差为0的对手,随时间推移,允许匹配的对手分差逐渐变大
- 创建
matchingsystem.service.impl.utils.matchingpool
,matchingsystem.service.impl.utils.Player
matchingpool
是多线程类,需要extends Thread
,并重载run()
- 将所有用户存储起来:
List<Player> players
,多个线程共用,涉及读写冲突问题,需要加锁 - 实现
addPlayer()
和removePlayer()
- 实现删除逻辑:枚举所有
player
,创建一个新List
将没被删的存下来,赋给原始players
- 实现删除逻辑:枚举所有
- 匹配逻辑
- 在
MatchingPool的run()
中,写一个死循环,每sleep
一秒,将所有玩家的等待时间+1 - 再用
matchPlayers()
来匹配玩家,通过checkMatched()
判断玩家是否满足配对条件,匹配成功后从匹配池中删除玩家 - 将匹配结果通过sendResult返回给backend
backend
中需要写一个controller
和对应Url
来接收结果:StartGameController
及对应的Service;记得放行接口matchingsystem
通过Restemplate
发送匹配结果,需要在MatchingPool
这个类上加@component
,注入时要使用set方法注入
- 在
MatchingServiceImpl
中往matchpool
添加或删除玩家 - 在
MatchingSystemApplication
中启动匹配线程,即在springboot
启动时就启动匹配系统
5. 优化逻辑
当一名玩家在匹配时关闭页面,会报错
原因:玩家关闭页面没有从匹配池中将玩家删除,此时WebSocketServer
中会得到一个空的玩家
因此在所有含有users.get(x.getId())
的地方需要判空