记录一下上个月实现的简单版的一个通信中心推送两个通信中心的过程。

     上个月我的通信中心出现了,可以入库mysql5.7,但是不能推送给客户第三方API的情况,我就决定把通信中心一分为三,一个通信中心专门只接收然后转发信息给另外两个通信中心,

另外两个通信中心是这样安排的,一个专门解析国家水文协议及入库操作,另一个通信中心解析水文协议完后就推送给第三方API。说明一下我的程序是基于netty通信框架的。

然后就出现异常:io.netty.util.IllegalReferenceCountException: refCnt: 0

经过网络查询知道原因是:

这是因为Netty引用计数器的原因,自从Netty 4开始,对象的生命周期由它们的引用计数(reference counts)管理,而不是由垃圾收集器(garbage collector)管理了。ByteBuf是最值得注意的,它使用了引用计数来改进分配内存和释放内存的性能。

在我们创建ByteBuf对象后,它的引用计数是1,当你释放(release)引用计数对象时,它的引用计数减1,如果引用计数为0,这个引用计数对象会被释放(deallocate),并返回对象池。

主要原因就是我第一个专门中转的通信中心收到RTU设备的信息后要转发给两个通信中心,第一次转发的时候是没有问题的,这个时候ctx.write 等一系列方法调用了ByteBuf的release方法,将其引用计数减为0了,当第二次转发的时候就报异常了。

解决的方法:

.retain();// 我们可以调用ByteBuf.retain()将引用计数加1

.duplicate();//复制当前对象,复制后的对象与前对象共享缓冲区,且维护自己的独立索引

接下就是一个通信中心推送(转发)另外两个通信中心的思路:

由于业务就是要处理RTU设备发送过来的信息再加上推送给第三方API,如果设备没有连接上来,三个通信中心也得自己互连互通。

思路如下:

第一部分:自定义自己的包头不能和水文的7E7E一样就可以了。

第二部分:安排两个字节指示剩下报文的长度。

第三部分:两个字节水文协议报文长度。

第四部分:水文协议报文内容(如果第三部分长度大于零)。

第五部分:通信中心之间的心跳信息(如果第三部分长度等于零)。

经过排查发现我用的第三方推送程序挂一两天后就是不推送了,替换另的推送程序。

问题解决后,两个处理业务的通信中心重新划分功能一个是处理数据入库及推送,另一个专门处理图片保存和推送。

BizOne2Two是中转中心,

BizPlatformServer是处理图片业务及推送给第三方API,

Biz2DataBaseServer是处理除图片之外的其他业务处理及推送给第三方API,

经过一个月了,程序已经稳定。

 

 

参考:

https://my.oschina.net/LucasZhu/blog/1799075

posted on 2019-12-14 00:17  yebinghuai2019  阅读(128)  评论(0编辑  收藏  举报

导航