来源:blog.csdn.net/u013615903/article/details/129044283
👉 欢迎加入小哈的星球,你将获得:专属的项目实战/ Java 学习路线 / 一对一提问 / 学习打卡
目前, 正在星球内部带小伙伴做第一个项目:前后端分离博客,手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。目前已更新了105小节,累计14w+字,讲解图:684张,还在持续爆肝中.. 后续还会上新更多项目,愿景是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯等等,戳我加入学习,已有320+小伙伴加入(早鸟价超低)
-
项目背景 -
正文 -
一、项目架构 -
二、项目模块 -
三、业务流程 -
四、代码详解 -
五、测试 -
六、源码 -
后记
项目背景
最近公司某物联网项目需要使用socket长连接进行消息通讯,捣鼓了一版代码上线,结果BUG不断,本猿寝食难安,于是求助度娘,数日未眠项目终于平稳运行了,本着开源共享的精神,本猿把项目代码提炼成了一个demo项目,尽量摒弃了其中丑陋的业务部分,希望与同学们共同学习进步。
正文
一、项目架构
本项目使用了netty、redis以及springboot2.2.0
二、项目模块
本项目目录结构如下图:
netty-tcp-core
是公共模块,主要是工具类。netty-tcp-server
是netty服务端,服务端仅作测试使用,实际项目中我们只使用了客户端。netty-tcp-client
是客户端,也是本文的重点。
三、业务流程
我们实际项目中使用RocketMQ作为消息队列,本项目由于是demo项目于是改为了BlockingQueue
。数据流为:
生产者->消息队列->消费者(客户端)->tcp通道->服务端->tcp通道->客户端。
当消费者接收到某设备发送的消息后,将判断缓存中是否存在该设备与服务端的连接,如果存在并且通道活跃则使用该通道发送消息,如果不存在则创建通道并在通道激活后立即发送消息,当客户端收到来自服务端的消息时进行响应的业务处理。
四、代码详解
1.消息队列
由于本demo项目移除了消息中间件,于是需要自己创建一个本地队列模拟真实使用场景
packageorg.example.client.controller;importorg.example.client.QueueHolder;importorg.example.client.model.NettyMsgModel;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;/***@authorReWind00*@date2023/2/1513:48*/@RestController@RequestMapping("/demo")publicclassDemoController{/***间隔发送两条消息*/@GetMapping("testOne")publicvoidtestOne(){QueueHolder.get().offer(NettyMsgModel.create("87654321","HelloWorld!"));try{Thread.sleep(5000);}catch(InterruptedExceptione){e.printStackTrace();}QueueHolder.get().offer(NettyMsgModel.create("87654321","HelloWorldToo!"));}/***任意发送消息**@paramimei*@parammsg*/@GetMapping("testTwo")publicvoidtestTwo(@RequestParamStringimei,@RequestParamStringmsg){QueueHolder.get().offer(NettyMsgModel.create(imei,msg));}/***连续发送两条消息第二条由于redis锁将会重新放回队列延迟消费*/@GetMapping("testThree")publicvoidtestThree(){QueueHolder.get().offer(NettyMsgModel.create("12345678","HelloWorld!"));QueueHolder.get().offer(NettyMsgModel.create("12345678","HelloWorldToo!"));}}
测试接口代码如上,调用testOne,日志如下:
可以看到第一条消息触发了客户端创建流程,创建后发送了消息,而5秒后的第二条消息直接通过已有通道发送了。
测试接口代码如上,调用testTwo,日志如下:
发送shutdown可以主动断开已有连接。
测试接口代码如上,调用testThree,日志如下:
可以看到第二条消息重新入列并被延迟消费了。
六、源码
https://gitee.com/jaster/netty-tcp-demo
后记
本demo项目仅作学习交流使用,如果要应用到生产环境还有些许不足,有问题的同学可以留言交流。
👉 欢迎加入小哈的星球,你将获得:专属的项目实战/ Java 学习路线 / 一对一提问 / 学习打卡
目前, 正在星球内部带小伙伴做第一个项目:前后端分离博客,手摸手,后端 + 前端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,直到项目上线。目前已更新了105小节,累计14w+字,讲解图:684张,还在持续爆肝中.. 后续还会上新更多项目,愿景是将Java领域典型的项目都整一波,如秒杀系统, 在线商城, IM即时通讯等,戳我加入学习,已有320+小伙伴加入(早鸟价超低)
最近面试BAT,整理一份面试资料《Java面试BATJ通关手册》,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。
获取方式:点“在看”,关注公众号并回复Java领取,更多内容陆续奉上。
PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。
点“在看”支持小哈呀,谢谢啦
本篇文章来源于微信公众号: 小哈学Java
微信扫描下方的二维码阅读本文
Comments NOTHING