有点迷茫,所以就跟风做了一些轻娱乐游戏。当时为了实战,觉得需要一个实时的技术实现,于是实现了一个websocketserver。没想到这些小程序并没有成功,我们的websocketserver却进化到了无处不在的地步。下面介绍该技术的实现。光看理论肯定有点啰嗦吧?我们直接上代码。我们假设有这样一个用户支付逻辑。在写用户支付事件的时候,我们事先并不知道以后需要添加什么逻辑,所以我们先广播这个行为。以下是伪代码:req:=httplib.Post("https://ws.app.12zan.net/eventcast/user/5905e89db43fec42e3055df05ff72afe")text,er:=zanjson.Encode(order)ifer!=nil{log...该频道广播一条消息。不幸的是,目前没有客户端订阅这样的消息,所有的消息都被丢弃了。有一天,我们睿智而有权势的老板决定添加一条通知。每当有新用户付费的时候,他都会发邮件给公司的同胞,通知我们获得了一个新的付费用户,让大家开心一下。让我们都高兴得跳起来,尤其是当第一个试用客户付款时。这个时候,如果我们改变线上运行良好的支付系统,还是有点风险的。一旦有修改,我们就得走测试流程,否则出了问题,会影响公司的运势。没关系,我们之前不是广播过支付事件吗,我们现在就用。写这么一段js,在线运行,就好了。constwebSocket=require('ws');letws=newwebSocket("wss://ws.app.12zan.net/eventcast/user/5905e89db43fec42e3055df05ff72afe");ws.on('open',functionopen(){console.log("connected");});ws.on('message',functionincoming(data){letuser=JSON.parse(data);Mail.send("Ausernamed"+user.name+"好心人支付了“+user.amount+”元,求大神点赞!”);});好吧,现在一旦有人付款,我们整个公司都可以收到一封电子邮件,并及时得到好消息。让我们庆祝一下吧。在接下来的几天里,我们希望改善体验。用户支付成功后,将发送短信通知用户有效期及我们的24小时客服电话;它只需要部署这段代码并运行它。在不需要移动任何代码之前:constwebSocket=require('ws');letws=newwebSocket("wss://ws.app.12zan.net/eventcast/user/5905e89db43fec42e3055df05ff72afe");ws.on('open',functionopen(){console.log("connected");});ws.on('message',functionincoming(data){letuser=JSON.parse(data);letexpiresAt=(zan.Date.now().add("+365day").format("YYYY-mm-dd"));SMS.send(user.Mobile,"Dear"+user.name+),您成功购买十二赞旗舰版本,有效期至“+expiresAt+”,请登录:https://www.12zan.cn查看,如有疑问请拨打4006681102");});发送通知邮件和发送通知短信都是基于用户的支付动作,但是发送邮件和短信的代码是完全隔离的,根本不知道对方的存在。是不是很棒?那么接下来我们来梳理一下逻辑。概念及主要逻辑也许我们没有时间去看websocket的定义,但是我们可以简单的理解为Websocket是HTTP协议的扩展升级。发起连接时,HTTP部分有效,但连接成功后,服务端与客户端的连接是持续的,双方可以双向传输数据,服务端可以主动向客户端推送数据。下面看一下Websocket发起连接的过程(来自维基百科):客户端向服务端发起连接:GET/HTTP/1.1Upgrade:websocketConnection:UpgradeHost:example.comOrigin:http://example.comSec-WebSocket-密钥:sN9cRrP/n9NdMgdcy2VJFQ==Sec-WebSocket-版本:13从服务器返回:HTTP/1.1101切换协议升级:websocketConnection:UpgradeSec-WebSocket-Accept:fFBooB7FAkLlXgRSz0BT3v4hq5s=Sec-WebSocket-Location:ws://example.com/在HTTP协议中常见的字段,如Cookies、Host等,仍然有效。但是到了我们的应用中,十二赞的websocket服务器实现了两个小目标【好遗憾,我们没赚到2亿】:我们实现的是一个广播系统,一个广播系统就是一个地方要发送数据,n个接收者接收数据。需要支持大量客户端同时连接数据,实时接收数据。我们最终的服务端实现,全内存实现,没有使用redis或者类MySQL的数据库,只是为了实现超强的多客户端支持。我们希望用最简单最普通的文案,效率很高,支持很多客户端同时连接。我们觉得http协议比较简单,所以在发送的时候,我们使用http协议来发送数据。而且,没有安全设计,如果数据很重要,请在发送前加密。当然,我们也有一些遗憾:数据丢失是允许的。得到的就是失去的,我们允许一部分信息丢失。当数据丢失时,不影响主逻辑。就像刚才的例子一样,发送邮件通知我们有新支付的事件不触发也没关系。下午才发现有新用户付费。比如有新用户付款时,告诉我们所有的同事有新付款,或者先发短信给用户,并不是那么重要。好了,回到我们的系统,我们再做一个小总结。我们定义,每个websocket的入口是一个URL;去掉protocol和HOST部分,剩下的PATH部分代表不同的通道。例如,发起websocket时连接ws://ws.app.12zan.net/channel/hello,则通道地址为/channel/hello;所有连接到ws.app.12zan.net/channel/hello端的websocket客户端,他们将收到完全相同的消息,我们称之为订阅。同时,为了简化发起数据的过程,我们还在websocket服务器中定义:当http客户端以POST方式请求某个地址时,我们拦截url中的PATH部分,获取通道名,并将POST数据中的数据字段,作为要广播的数据,广播到对应的频道。在十二瓒中的应用:这个广播系统,在十二瓒的整个技术架构中,后来得到了广泛的应用。比如我们的部署系统zeus在网页上实现了一个客户端。当服务器重新启动、关闭或启动应用程序时,将弹出消息通知。任何人打开这个系统的网页都可以看到。比如我和同事小王都在zeus网页。我创建了一个搜索系统的新节点。节点。我在运营,我很在意这个,所以我可以放心在这个时候继续我的工作。小王准备在3号机上部署新系统。收到这个通知后,他认为这台机器可能很忙,所以他将他的新实例部署在4号机器上。再比如,我们的日志服务器负责收集所有服务器上的日志。但是如果它挂了怎么办?所以我们在这个日志服务器上运行了一个定时器,每5秒向某个频道广播一个心跳消息,告诉世界我们还活着。然后运行另一个进程来收听这个频道的广播。如果连续30秒没有收到心跳包,证明日志服务器宕机了,会发出告警信息,通知同学们检查这个服务。再比如我们在日志服务上的应用,看这里:十二赞日志系统介绍
