/springboot_im

使用springboot + nettysocketio开发的一个简易卡牌游戏。主要想了解游戏服务端开发流程,基本逻辑等相关知识和长连接。

Primary LanguageJava

springboot_im

使用springboot开发的一个极其简易的可以聊天或者留言的web。主要联系springboot相关知识和长连接。

接下来的任务

  1. 简单的断线重连。
  2. 完成1之后在完善客户端的返回信息,然后看看是否需要把发消息的单独提出来或者整合到RoomContext里面
  3. 增加上redis缓存,room的和user的
  4. 看是否需要room连接池和room消息队列<可以延后再延后>

ps: git常用命令

另外,git如果是第一次使用的话,需要认证身份,通过下面的步骤:

  1. git config --global user.name "yourname"
  2. git config --global user.email "youemail"
  3. 生成秘钥: ssh-keygen -t rsa -C "youemail"
  4. 之后就是让你输入连接杆github时的密码,密码确认密码,可直接3个回车略过,表示密码为空
  5. 到github上添加秘钥 中的公钥



git添加里程碑--tag

  • git commit --allow-empty -m "blank commit for annotated tag test." 创建一个空白提交
  • git tag -m '创建里程碑,初步走通游戏流程,并且可以运行!!!' tag_wyj_complete_game_1.0 添加里程碑
  • git tag -l -n1, git describe 查看里程碑信息
  • cat .git/refs/tags/tagname 查看里程碑
  • git tag -d tagname 删除里程碑
  • git tag tagname ec3edf7 如果发现删除错误,通过这句命令补救。表示将此tag指向某个commit
  • git push origin :mytag2 远程删除tag
    更加详细的里程碑内容,请参考:Git学习7:Git中的里程碑

现在需要找到一个写接口文档的工具,其实有很多,我也知道Swagger,但是因为swagger比较复杂繁琐,所以这里并不准备用swagger。通过百度`接口文档 管理`找到了很多相关的软件,有`sosoApi`、`小幺鸡`、`ShowDoc`等。但是具体选择哪一个呢?下面 我总结了一下选择需要参考的东西。 - 首先要明确,自己需要哪些功能。 我初步总结的有,普通API的支持、socket的支持、易编辑、多用户权限管理,这几个是最最基本的,另外的加分项有 是否可以发布到自己的服务器,毕竟这个是不能公开的; 是否已支持简单的mock层,就是仿服务器数据,这样前端就不用等后台的数据了。 - 找这些接口文档工具的优缺点,是否满足自己的要求。 通过什么办法呢,就是去看官方的帮助文档了。。(自从用了NettySocketIO这个没文档的东西,就对没文档的东西产生了抵触心理,没文档就放弃吧,否则学习的太累了,而且也很难挖掘他的真正优势) - 最后决定 [`小幺鸡`](http://www.xiaoyaoji.cn)

springboot 学习教程

基础教程参考的是:翟永超的springboot教程专栏,里面还附有git地址。
基础提高教程可以参考:zheting的springboot干货系列
包括:


[Spring Boot加载配置文件](https://www.cnblogs.com/moonandstar08/p/7368292.html)
[springboot打包发布教程](https://www.cnblogs.com/honger/p/6886017.html)
java 后台运行 `nohup java -jar test.jar &`
[Spring Boot干货系列:常用属性汇总](http://tengj.top/2017/02/28/springbootconfig/)



Spring-jpa学习



阿里druid 数据库连接池与tomcat-jdbc连接池比较:http://www.cnblogs.com/barrywxx/p/6343303.html。

结论是:druid在连接次数多了之后,比如上万,平均时间相比于tomcat-jdbc更稳定一点,用时少一点。如果连接次数没有很多的话,tomcat-jdbc用时更少。

druid语法可以参考 Druid连接池-阿里巴巴开源JDBC组件

关于Spring-boot的debug调试

springboot 中踩过的坑

@Value

之前采用这种方式注入,然后该类里面的成员总是为null,我现在只想说, 这TMD 不是废话么!!!能TM有值么!! 对象你都实例化完成了,注入到系统中了,你还让系统怎么给这个对象赋值,使用@Component完成注入(好像这种认识并不正确)

@Bean
public NettySocketServer socketServer() {
	return new NettySocketServer();
}


后来发现了问题的真正所在 -> 我tm在构造方法中使用成员变量 还tm问 为什么一直为空,当然tmd为空了,对象还没初始化完呢,怎么能初始化里面的成员变量,真tmd愚啊,后来使用了@PostConstruct注解 解决了该问题 另外一个是@PreDestroy

netty-socketio 学习资源

初级教程,也是源码git项目推荐的demo
因为没有guide,所以只能多看项目,一下是在网上参考的一些项目,给了我很大的帮助:

基本使用

这里总结一下NettySocketIO的基本使用,只是说一下大概流程,具体细节实现看代码:

  1. 配置com.corundumstudio.socketio.Configuration 并实例化 SocketIOServer server = new SocketIOServer(config)
  2. 通过com.corundumstudio.socketio.annotation.OnConnect 等注解 来实现监听socket连接、断开、接收消息等。然后通过依赖注入 new SpringAnnotationScanner(SocketIOServer socketIOServer) ,通过该类来扫描@OnConnect, OnEvent等注解,注册正真的监听器。
  3. 当然了,也可以通过 Configuration.setXxxListenerSocketIOServer.addEventListener 来注册监听器,算是2步骤的扩展。
  4. 最后客户端就可以通过 io.connect('http://localhost:9090?token='+userName); 来连接到socket,然后就可以通信了。因为NettySocketIO是通过集成socket.io这个库来实现socket的,所以客户端语言不限,但是必须也要使用socketio的库,socketio官网

理解NettySocketIO server框架

NettySocketIO是一个集成了Netty服务器和socketio的,很方便实现长连接的框架。

Netty服务器是一个使用了java nio-非阻塞流来处理http请求的,相比于tomcat,tomcat是一个线程处理一个请求,当这个请求比较慢的时候(如网络状态不好)这个线程也会阻塞,直到等到客户端数据,而Netty使用的同步非阻塞IO开启一个线程就可以处理多个请求,所以Netty能够支持高并发,可达百万级。而且Netty减少了拷贝,支持多种协议包括websocket。

Netty采用的是 NIO+Reactor 的线程模型。

更多了解Netty、NIO、Reactor线程模型的,可以参考下面的文章:

炸金花游戏逻辑

参考网上的状态模式
扎金花大小比较算法(Java版)

初步完成整个游戏逻辑流程,没有页面,只有一个粗糙的按钮界面(baseUrl/static/index2.html),下面是后台服务器的日志: 游戏流程后台日志

断线重连逻辑

经过慎重仔细的思考,根据现在的游戏逻辑与信息存储模型,最大的问题其实就是当这个用户再连接回来的时候,不能根据已有的信息回溯到原来的所有信息,并建立连接(其实一般都会遇到这种问题)。 网上有的建议说当用户第一次建立房间的时候维护一个在服务器和本地都不会变的client_id,这样,当用户再次连接的时候,就可以根据此id来检查服务器有没有已经进入的房间信息,然后达到重连的效果。

其实,这可以说是一种解决办法,因为它能解决现在遇到的问题,但是总感觉这种实现怪怪的,怪就可能有他的不合理之处,或者说和现实中的处理流程不一样(就像我在开发过程对总押注的计算,和对最后结果的处理,虽然一开始都得到了正确的结果,但是因为没有按照现实中的流程来计算,按照本来的模型来存储,导致后来简单的修改就导致了结果计算不正确),虽然结果一样,但是在未来的不断修改增加的需求过程中,总会出现问题的。

最后,我决定使用一个掉线用户池,就是说如果服务器发现某个用户掉线了,则把相关必要信息存储在一个掉线用户池中,当一个用户连接上来的时候,先根据id检查该池中是否有该用户,如果有则能找到原来所有用户的信息,当然数据的恢复也就是断线重连也就很简单了。