您的位置 首页 新品

Netty与WebSocket的使用事例

Netty与WebSocket的应用案例-ajax 方式实现简单,只需要定时从服务端 pull 数据即可,但也增加了很多次无效的轮询,即无形中增加服务端无效查询。
push 方式实现稍复杂,需要服务端与 PC 端保持连接,这就需要建立长连接,最终通过长连接的方式来实现 push 效果。

在京东到家商家中心体系中,商家提出了要在 Web 端完结自动打印的需求,不再需求人工盯守点击打印,直接打印小票,以节省人工本钱。

处理思路

关于问题的两种考虑逻辑:

能够用 ajax 来轮询服务端获取最新订单,也便是 pull。

能够用相似推送的规划来完结,也便是 push。

咱们评价了两种思路的优缺点:

ajax 方法完结简略,只需求守时从服务端 pull 数据即可,但也添加了很屡次无效的轮询,即无形中添加服务端无效查询。

push 方法完结稍杂乱,需求服务端与 PC 端坚持衔接,这就需求树立长衔接,终究通过长衔接的方法来完结 push 作用。

通过评论,咱们挑选了第二种,订单中心生产出的新订单,通过 MQ 的方法推送给 Web 端,终究取得一个比较好的用户体会。

计划介绍

关于长衔接计划的挑选,咱们参阅了不少帖子,终究挑选了运用 websocket 协议来完结长衔接,相似场景如 IM,服务端即时推送等都运用了这个协议。

接下来咱们比较一下 websocket 的结构,比较干流的有 netty、tomcat、sockeTIO 三个结构:

依据支撑 websocket 的容器,开发简略,例如 tomcat,但在高并发的支撑不是很好,衔接的时分简单衔接断开,还有便是依靠容器。

netty-sockeTIO 是在 netty4 根底之上做了一层封装,功率好像 netty 相同,是一个全渠道计划,友爱的 API。京东的 logbook 也是用了 sockeTIO 来传递日志,也是咱们的一个备选计划。

netty 是业界干流的 NIO 结构,netty 对 Java NIO 做了封装,让开发者更多重视事务,下降开发本钱。

许多闻名的 RPC 结构都选用了 netty 作为传输层,友爱的 API,功用强壮,内置了许多编解码协议,完结 websocket 协议也是非常便利。

那咱们横向比较一下这些结构:

Netty与WebSocket的运用事例

所以在选型方面咱们仍是定位在 sockeTIO 与 netty 上面,在统筹扩展性与灵活性的一起,咱们也考虑到 netty 能够供给 http 的功用。

终究咱们挑选了运用 netty,当然 socketIO 封装了许多功用,也是非常强壮,相比较来说 netty 更适合咱们,比较轻量。

Netty 的特性

netty 具有异步非堵塞的特性,传统 IO 是面向流的,NIO 是面向缓冲区的,这也是它的非堵塞原因地点。

netty 的线程模型如图所示:

Netty与WebSocket的运用事例

这种模型便是咱们常说的 Reactor 模型,boss 线程其实是一个独立的 NIO 线程池,用于接纳 client 恳求,默许线程池巨细为 1,worker 线程池用于处理详细的读写操作,默许线程池巨细为 2*cpu 个数。

在上述模型中要特别注意 ExecutionHandler,ExecutionHandler 是运转在 worker 线程中的,所以耗时的操作最好在线程池中运转, 比方 IO 或许核算,否则会影响整个 netty 的吞吐。

了解了这些,咱们依据自己的事务规划出流程,如下图所示:

进程 1:Web 端恳求服务端进行注册,注册成功坚持长衔接。

进程 2:服务端发送 MQ。

进程 3:netty 将收到的音讯推送给 Web 端。

进程 4:Web 端调用打印控件进行打印,打印控件需提早装置好(打印控件是 PC 上装置的一个驱动程序,用过 JS 方法来调用)。

假如调用 JS 成功,控件将把打印信息放入打印行列,假如不成功,重复进程 4。

Netty与WebSocket的运用事例

当然现在的结构仅仅单机版,不满足生产条件,那将来的结构或许会演变成如下图所示:

Netty与WebSocket的运用事例

咱们会在服务端与 netty 之间树立路由层,路由层的首要职责有:

搜集集群存活信息

记载落点,便是落在哪一台机器上面

收音讯与分发音讯

有了这三种才能,咱们就能够轻松的指定信息分发战略。咱们期望运用 http 协议来路由,这就需求 netty 有 http 短衔接接纳的才能 ,所以 netty 全体上需求长短衔接两种才能。

下面是部分代码:

netty 发动类,咱们通过 spring 来发动 netty,因为 netty 发动会堵塞主线程,所以需求在子线程中来发动 netty,下面是发动参数。

Netty与WebSocket的运用事例

接着来写咱们的 ChannelInitializer,HttpServerCodec 为编解码器,WSServerProtocolHandler 为 websocket 协议握手。

咱们更重视事务层面自定义的两个 hander,httpRequestHandler,authorizeHandler。

Netty与WebSocket的运用事例

httpRequestHandler 的作用是处理 URL 是否合法,接纳参数。

httpRequestHandler 此方法中也能够依据 URL 来过滤,自定义自己的短衔接恳求。

Netty与WebSocket的运用事例

authorizeHandler 的作用是校验数据是否正确,假如正确会将 channel 保存到 map 中,通过 map 树立起事务 ID 与通道之间的联系。

校验的进程咱们在 authorizeHandler 中的 channelRead 打开,假如未通过,直接封闭当时 channel。

假如通过校验,则通过 ctx.fireChannelRead(msg);方法将信息传入下一个 handler 去处理。

在项目里首要是以传递参数来进行数据校验的,也便是通过 URL 传参来完结。

在 httpRequestHandler 中咱们将 URL 参数 set 到 channel 的 attr 中,并传递给了下一个 handler,也便是 authorizeHandler。

所以在 authorize 方法中咱们能够使用 get() 方法得到参数值,u 是通过加密的数据,咱们需求在这里进行解密,解密失利,能够为校验失利。

当然假如有跨运用的服务,也能够通过 Cookie 的方法来进行加密串的读写,通过 request.getHeader 是能够获取 Cookie 中的信息,这就看详细事务了。

示例代码如下:

Netty与WebSocket的运用事例

这个 map 能够理解为 servlet 中的 session,当有信息需求传送给某个客户端时,咱们调用 map.get(key) 方法到当时该客户端的 channel,调用 writeAndFlush 方法将信息发送出去,下面举例通过接纳 MQ 音讯后的处理逻辑。

接下来有人或许想到,假如通道封闭了怎么办?map 中的 channel 是不是就失效了呢?

其实咱们还需求有一个相似心跳的机制去保护 channel,直接的去保护这个 map。

假如是通道正常封闭,能够通过 channelInactive 方法来监听。

假如是长期闲暇,在项目中咱们运用了添加的 IdleStateHandler 来处理,通过掩盖 userEventTriggered 方法来监听闲暇 channel,当某个 channel 抵达咱们设置的超时时刻时,netty 会回调此方法。

至此,中心部分现已处理完结,剩余的便是通过保存的 channel 来发送信息给客户端了。

最终在 Web 端,咱们选用了 reconnecting-websocket,它是一个小型的 JavaScript 库,封装了 WebSocket API, 供给了在衔接断开时自动重连的机制,能够协助咱们完结断开重连的操作。

遇到的问题

通过测验,在 ws 的 uri 后边不能传递参数,否则在 netty 完结 websocket 协议握手的时分会呈现断开衔接的状况。

针对这种状况在 websocketHandler 之前做了一层 httpHander 过滤,将传递参数放入 channel 的 attr 中,然后重写 request 的 uri,并传入下一个管道中,根本上处理了这个问题。

在读写闲暇的时分尽量以发心跳包的方法保护衔接,但在客户端因为网络不安稳或许是服务端重启,衔接会断开,瞬间有或许接纳不到订单音讯,为此在客户端需求完结断开重连机制。

此问题咱们选用 reconnecting-websocket的 JS 结构,此结构扩展了原生 websocket 的完结,做了断开重连机制,有用的避免断开后不能及时衔接。

在测验进程中因为控件与小票机的问题,或许会呈现打印反常或许小票机没纸的状况。Lodop 控件能够将打印信息放入电脑的打印行列。

假如没纸了,小票时机报警,再次放入小票纸,打印时机自动打印行列中的数据。

呈现调用控件反常偶然产生,现在处理方法是在 JS 中进行了的 try catch。

假如失利,进行重试,重试次数自定义,超越重试次数暂不做处理,此处还不太谨慎,需求再进行优化。

总结

通过上面的实践,咱们根本现已完结了 Web 端的自动打印,通过长期的内部测验,服务端与客户端通讯安稳,咱们将灰度商家做用户体会。

在特定的场景下,挑选恰当的技能会进步咱们的功率,否则会拔苗助长。

挑选长衔接,我们能够掌握这三个大原则:

服务端是否需求自动推送数据到客户端以完结操控的作用。

关于实时性的要求是否严苛。

关于客户端是否需求重视它在线状况的实时改变。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/xinpin/102799.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部