从构建分布式秒杀系统聊聊WebSocket推送通知

前言

秒杀架构到后期,咱们采用了消息队列的形式实现抢购逻辑,那么以前抛出过这样一个问题:消息队列异步处理完每一个用户请求后,如何通知给相应用户秒杀成功?git

场景映射

clipboard.png

首先,咱们举一个生活中比较常见的例子:咱们去银行办理业务,通常会选择相关业务打印一个排号纸,而后就能够坐在小板凳上玩着手机,等待被小喇叭报号。当小喇叭喊到你所持有的号码,就能够拿着排号纸去柜台办理本身的业务。github

这里,假设当咱们取排号纸的时候,银行根据时间段内的排队状况,比较人性化的提示用户:排队人数较多,您是否继续等待?否的话咱们能够换个时间段再来办理。web

由此咱们把生活场景映射到真实的秒杀业务逻辑中来:数据库

  • 咱们能够把柜台比喻成商品下单处理逻辑单元
  • 拿到排号纸说明你进入相应商品处理队列
  • 拿到排号纸的请求直接返回前台,提示用户抢购进行中
  • 排号纸进入队列后,等待商品业务处理逻辑
  • 小喇叭叫到本身的排号至关于服务端通知用户秒杀成功,这时候能够进行支付逻辑
  • 那些拿不到票号的同窗,至关于队列已满直接返回秒杀失败

解决方案

经过上面的场景,咱们很容易可以想到一种方案就是服务端通知,那么如何作到服务端异步通知的呢?下面,主角开始登场了,就是咱们的Websocket。后端

clipboard.png

WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通信的网络技术。依靠这种技术能够实现客户端和服务器端的长链接,双向实时通讯。浏览器

clipboard.png

特色:缓存

  • 异步、事件触发
  • 能够发送文本,图片等流文件
  • 数据格式比较轻量,性能开销小,通讯高效
  • 使用ws或者wss协议的客户端socket,可以实现真正意义上的推送功能

缺点:服务器

  • 部分浏览器不支持,浏览器支持的程度与方式有区别,须要各类兼容写法。

集成案例

因为咱们的秒杀架构项目案例中使用了SpringBoot,所以集成webSocket也是相对比较简单的。微信

首先pom.xml引入如下依赖:websocket

clipboard.png

WebSocketConfig 配置:

clipboard.png

WebSocketServer 配置:

clipboard.png

KafkaConsumer 消费配置,通知用户是否秒杀成功:

clipboard.png

webSocket.js 前台通知逻辑:

clipboard.png

客户端API

客户端与服务器通讯

  • send() 向远程服务器发送数据
  • close() 关闭该websocket连接

监听函数 

  • onopen 当网络链接创建时触发该事件
  • onerror 当网络发生错误时触发该事件
  • onclose 当websocket被关闭时触发该事件
  • onmessage 当websocket接收到服务器发来的消息的时触发的事件,也是通讯中最重要的一个监听事件。msg.data

readyState属性

这个属性能够返回websocket所处的状态。

  • CONNECTING(0) websocket正尝试与服务器创建链接
  • OPEN(1) websocket与服务器已经创建链接
  • CLOSING(2) websocket正在关闭与服务器的链接
  • CLOSED(3) websocket已经关闭了与服务器的链接

开源方案

goeasy

GoEasy实时Web推送,支持后台推送和前台推送两种:后台推送能够选择Java SDK、 Restful API支持全部开发语言;前台推送:JS推送。不管选择哪一种方式推送代码都十分简单(10分钟可搞定)。因为它支持websocket 和polling两种链接方式因此兼顾大多数主流浏览器,低版本的IE浏览器也是支持的。

地址:http://goeasy.io/

Pushlets

Pushlets 是经过长链接方式实现“推”消息的。推送模式分为:Poll(轮询)、Pull(拉)。

地址:http://www.pushlets.com/

Pushlet

Pushlet 是一个开源的 Comet 框架,Pushlet 使用了观察者模型:客户端发送请求,订阅感兴趣的事件;服务器端为每一个客户端分配一个会话 ID 做为标记,事件源会把新产生的事件以多播的方式发送到订阅者的事件队列里。

地址:https://github.com/wjw465150/...

总结

其实前面有提过,尽管WebSocket有诸多优势,可是,若是服务端维护不少长链接也是挺耗费资源的,服务器集群以及览器或者客户端兼容性问题,也会带来了一些不肯定性因素。大致了解了一下各大厂的作法,大多数都仍是基于轮询的方式实现的,好比:腾讯PC端微信扫码登陆、京东商城支付成功通知等等。

有些小伙伴可能会问了,轮询岂不是会更耗费资源?其实在我看来,有些轮询是不可能穿透到后端数据库查询服务的,好比秒杀,一个缓存标记位就能够断定是否秒杀成功。相对于WS的长链接以及其不肯定因素,在秒杀场景下,轮询仍是相对比较合适的。

本文做者:小柒2012

阅读原文

本文为云栖社区原创内容,未经容许不得转载。

相关文章
相关标签/搜索