前言
之前一直没有独立写过比较大型的项目,对很多知识点只是模糊的了解,现在自己落地去实现一些需求,才对这些知识有了更加具象的认识,以后要养成写总结的习惯。
websocket长连接
需求分析
之前项目里实现了一些基本的数据增删改查功能,无非就是get、post、push、delete这几种请求的使用,建立了用户与服务器的交互能力,但是这种交互是请求/应答模式的,即客户端发起一个请求,服务端根据请求内容回应数据,是无法实现服务器主动推送消息给客户端的。然而用户与用户之间的交互是需要服务器具有主动推送消息的能力的,用户A给用户B发送消息,这个过程是A发送消息给服务器,服务器再转发给B,转发给B是这个过程即服务器主动发送消息给客户端,即我们要建立一个全双工的通讯。区别于http1.1的半双工。
技术分析
本文使用websocket构建长连接能力,但在谈websocket之前先说说http,因为长连接这个词在http中早已出现。我们知道http1.0是单工的模式,创建的是短连接,即客户端请求,服务端回复,来回一次会话连接就被关闭,到了http1.1之后开始支持长连接能力,且是默认开启(connect:keep-alive),但是它是半双工的模式,即虽然建立了长连接,但是服务器仍然不具备主动推送消息的能力,仍然是客户端请求/服务器应答的模式,说到这似乎有点不能理解什么是长连接了。
什么是长连接
所谓连接应该是传输层协议(tcp)的概念,http是基于tcp协议实现的应用层协议,所以我们说的http长连接本质上是tcp的长连接(tcp连接是全双工的),即多个http请求可以复用同一个tcp连接,减少了每次请求都需要先建立tcp连接的时间开销。http1.1的长连接是半双工的,这是http1.1自身的行为导致的。http2.0之后便实现了全双工的长连接。(更多计算机网络的知识可以关注“小林coding“公众号,我个人感觉他的图解计算机网络写的很好)
全双工的websocket
上面说到了http1.1虽然支持长连接但是是半双工的,我们需要一个全双工通讯的长连接,这就用到了websocket协议,它也是应用层的协议,它依赖于http协议进行一次握手建立连接,连接建立后数据直接在tcp通道传输。即websocket先利用http建立通讯连接,最终利用tcp全双工的能力进行数据传输,摆脱了http自身的一些行为。下图为websocket握手阶段的请求头,Upgrade:websocket字段告知服务器这个http连接是升级的websocket协议。
具体应用
这一节在我原本的项目基础上增加了点赞、评论等消息实时推送给up主的功能,是对websocket长连接的简单实践。
服务器部分
服务器端使用的websocket库:github.com/gorilla/web…
下图为服务端建立websocket连接的代码段(gin框架)
服务器维护一张在线用户的长连接map,用户A发送消息给B,服务器根据userid找到B的长连接,将消息转发给B。这个部分没有考虑离线消息的存储,后续可以再细化一下。 还是很容易使用的,连接建立好之后就可以按照自己的需求写业务代码了。
移动端部分
移动端使用的websocket库:github.com/facebook/So…
下图为SockeRocket里比较重要的一些接口:
这些接口的含义还是很清晰的,使用也非常容易(API Boy),具体实现的时候要定时发送心跳数据给服务器进行连接保活,端上一个长连接可能会用于多个对象中,也可以做成单例。
最终效果
redis缓存
需求分析
MySQL是我们接触到比较多比较早的数据库,每次数据的存取都要进行I/O操作,是比较耗时的,对于一些高频操作,比如点赞、取消点赞、浏览视频等产生的数据,如果每次都进行I/O操作,是很消耗资源的。因此对于一些高频改动的数据,如果直接能在内存中对其进行增删改查工作,而不需要每次都操作硬盘,或许更加合理一些,这便是redis缓存。(其实我也没有大型项目的经验,但是大家都这么说哈哈哈)
redis与MySQL的一些区别
说到这两者的区别,说到最多的就是非关系型数据库与关系型数据库的区别,这两个的概念就不多纠结了,只说我自己使用的一些体会:首先redis是基于内存操作的,MySQL是基于磁盘工作的,可以理解redis是用空间换时间,数据读写速率是比MySQL快很多的,但也正是如此,redis存储的数据量是有限的,redis也有持久化的能力,持久化到磁盘里才是真正意义上的数据库功能,内存中的只是缓存,断电是会丢失的。其次,redis是没有严格的表结构的,它是基于一些基本的数据结构对数据进行存储,因此不需要像MySQL需要花费比较多的时间对表进行设计,使用起来灵活性更高一些。
redis使用
redis命令文档:redisdoc.com
redis库(go语言):github.com/go-redis/re…
这个库的方法命名和参数与redis命令一致,感觉很好用。
数据库的项目:github.com/roseduan/ro… 这里推荐了一个大佬写的数据库项目,个人感觉写的还是很好的,至少我能看的懂,数据对于互联网行业是很重要的,所有的技术最终都是为了数据服务,看一看数据库的项目有利于自己对数据的理解,最终促进对业务的理解与实现。redis也是开源的,有兴趣可以看看。
利用redis与websocket进行数据的动态展示
客户端获取到服务端返回的资源后渲染到屏幕上,一般情况下这些数据就不会再改变了。要改变页面上的数据有两种方式,一种是被动改变,即用户刷新页面,获取到最新数据,二是主动改变,即前端写一个轮询,每隔一段时间就从服务器获取最新数据,本节对第二种方案做一个简单的实现。
后记
没事自己写一些玩具感觉还挺有意思的,各个框架也真是很好用,以前写c++服务器时还要对请求头进行一行一行的解析,后来接触框架后,这些基本的逻辑都被封装好了,开发者只需更多的关注业务需求就好,前端与后端交互变得像调用远端程序块一样容易。写业务能够提升自己对产品的理解,面对新的项目时能够自主的将项目的技术块抽离出来,对整体有更好的把握,不过真正的技术成长还是应该贴近底层一些,看看别人的框架源码或者自己写一些框架才是真的有利于技术成长。但是做一个API BOY真的很爽啊......