您的位置:网站首页 > net源码 > 正文

京东到家基于Netty与WebSocket的实践

类别:net源码 日期:2018-5-1 13:19:56 人气: 来源:

  在京东到家商家中心系统中,商家提出了要在 Web 端实现自动打印的需求,不再需要人工盯守点击打印,直接打印小票,以节约人工成本。

  ajax 方式实现简单,只需要定时从服务端 pull 数据即可,但也增加了很多次无效的轮询,即无形中增加服务端无效查询。

  push 方式实现稍复杂,需要服务端与 PC 端保持连接,这就需要建立长连接,最终通过长连接的方式来实现 push 效果。

  经过讨论,我们选择了第二种,订单中心生产出的新订单,通过 MQ 的方式推送给 Web 端,最终获得一个比较好的用户体验。

  关于长连接方案的选择,我们参考了不少帖子,最终选择了使用 websocket 协议来实现长连接,类似场景如 IM,服务端即时推送等都使用了这个协议。

  基于支持 websocket 的容器,开发简单,例如 tomcat,但在高并发的支持不是很好,连接的时候容易连接断开,还有就是依赖容器。

  netty-socketIO 是在 netty4 基础之上做了一层封装,效率如同 netty 一样,是一个全平台方案,友好的 API。京东的 logbook 也是用了 socketIO 来传递日志,也是我们的一个备选方案。

  netty 是业内主流的 NIO 框架,netty 对 Java NIO 做了封装,让开发者更多关注业务,降低开发成本。

  很多著名的 RPC 框架都采用了 netty 作为传输层,友好的 API,功能强大,内置了很多编解码协议,实现 websocket 协议也是十分方便。

  所以在选型方面我们还是定位在 socketIO 与 netty ,在兼顾扩展性与灵活性的同时,我们也考虑到 netty 可以提供 http 的功能。

  最终我们选择了使用 netty,当然 socketIO 封装了很多功能,也是十分强大,相比较来说 netty 更适合我们,比较轻量。

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

  这种模型就是我们常说的 Reactor 模型,boss 线程其实是一个的 NIO 线程池,用于接收 client 请求,默认线,worker 线程池用于处理具体的读写操作,默认线*cpu 个数。

  在上述模型中要特别注意 ExecutionHandler,ExecutionHandler 是运行在 worker 线程中的,所以耗时的操作最好在线程池中运行, 比如 IO 或者计算,不然会影响整个 netty 的吞吐。

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

  有了这三种能力,我们就可以轻松的指定信息分发策略。我们希望使用 http 协议来由,这就需要 netty 有 http 短连接接收的能力 ,所以 netty 整体上需要长短连接两种能力。

  netty 启动类,我们通过 spring 来启动 netty,因为 netty 启动会阻塞主线程,所以需要在子线程中来启动 netty,下面是启动参数。

  httpRequestHandler 此方法中也可以根据 URL 来过滤,自定义自己的短连接请求。

  所以在 authorize 方法中我们可以利用 get() 方法得到参数值,u 是经过加密的数据,我们需要在这里进行解密,解密失败,可认为校验失败。

  当然如果有跨应用的服务,也可以通过 Cookie 的方式来进行加密串的读写,通过 request.getHeader 是可以获取 Cookie 中的信息,这就看具体业务了。

  这个 map 可以理解为 servlet 中的 session,当有信息需要传送给某个客户端时,我们调用 map.get(key) 方式到当前该客户端的 channel,调用 writeAndFlush 方法将信息发送出去,下面举例通过接收 MQ 消息后的处理逻辑。

  最后在 Web 端,我们采用了 reconnecting-websocket,它是一个小型的 JavaScript 库,封装了 WebSocket API, 提供了在连接断开时自动重连的机制,能够帮助我们完成断开重连的操作。

  经过测试,在 ws 的 uri 后面不能传递参数,不然在 netty 实现 websocket 协议握手的时候会出现断开连接的情况。

  在读写空闲的时候尽量以发心跳包的方式连接,但在客户端由于网络不稳定或者是服务端重启,连接会断开,瞬间有可能接收不到订单消息,为此在客户端需要实现断开重连机制。

  此问题我们采用 reconnecting-websocket的 JS 框架,此框架扩展了原生 websocket 的实现,做了断开重连机制,有效的防止断开后不能及时连接。

  在测试过程中由于控件与小票机的问题,可能会出现打印异常或者小票机没纸的情况。Lodop 控件可以将打印信息放入电脑的打印队列。

  如果失败,进行重试,重试次数自定义,超过重试次数暂不做处理,此处还不太严谨,需要再进行优化。

  通过的实践,我们基本已经实现了 Web 端的自动打印,经过长时间的内部测试,服务端与客户端通信稳定,我们将灰度商家做用户体验。

  

0
0
0
0
0
0
0
0
下一篇:没有资料

网友评论 ()条 查看

姓名: 验证码: 看不清楚,换一个

推荐文章更多

热门图文更多

最新文章更多

关于联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助

CopyRight 2002-2012 技术支持 源码吧 FXT All Rights Reserved

赞助合作: