黎志伟
(云南师范大学 信息学院,云南 昆明650000)
目前,随着软件市场的不断扩大,各式各样的网站、小程序、APP 应运而生,为了满足软件快速实现并简捷部署的需求,大量免费开源项目和新技术被运用来实现软件的快捷开发与部署,这种方式不仅缩短了平均开发周期,而且降低了该部分功能出现错误的可能性。本文介绍的是在web 平台下使用docker 引擎和web socket 通讯协议开发并部署一款聊天系统,即在项目中引入web socket 协议进行对应的接口实现,最后服务器安装docker 引擎来完成系统部署。
Docker 容器是一个开源的应用容器引擎,让开发者可以以统一的方式打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何安装了docker 引擎的服务器上(包括流行的Linux 机器、windows 机器),也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口(类似iPhone 的app)。几乎没有性能开销,可以很容易地在机器和数据中心中运行。最重要的是,他们不依赖于任何语言、框架包括系统。Web Socket 是一种在单个TCP 连接上进行全双工通信的协议,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
聊天系统的设计主要运用了web socket 的On open 方法和On message 两个方法,客户端首先生成一个不重复的UUID 作为用户名去与服务端建立连接。服务端收到连接并维护所有客户端的连接,连接成功后客户端加载所有与服务端建立了连接的用户,之后客户端之间再以服务端做中转站其它客户端实现通讯,最后将系统部署在docker 容器中。本系统事先会准备一些图片,作为默认用户头像,用户连接以[key,value]的存储方式保存在服务端特定集合中,本次会话的已读和未读消息也会保存在客户端特定集合中。由于本次系统的重点不在于客户端界面,客户端制作为了节省时间,系统运用了一些网络上开放的前端组件,主要包括3 个界面,系统初始界面、用户列表界面、聊天主体界面。系统的界面流程图如图所示。这里的一些组件已经定义好了基础点击事件,但系统还需对部分业务逻辑代码进行扩展,比如点击事件;同时增加了系统需要实现的某些功能,主要增加了未读消息数量提示功能,未读/已读消息保存功能,未读消息提示清空功能等。
4.1 通讯功能。若A 用户要与B 用户进行通讯,A 用户首先需要点击好友列表中的B 用户进入到聊天界面,A 用户在发送消息区域输入要发送的内容后,通过回车事件调用本地的send 方法,同时将发送的内容添加到聊天信息展示区域的左侧,之后进入到服务端的On message 方法,通过消息接收方B 的send text 方法将消息发送到接收方B,接收方B 的客户端进行一系列判断,若都通过,直接将收到的消息添加到聊天消息区域的右侧。
4.2 临时保存聊天记录。为了不影响用户的聊天体验,本系统还要实现保存当前用户和其它用户的聊天信息;本文提出两种方案,第一种就是在当前用户的本地客户端用特定集合来保存聊天信息;第二种是将所有消息以特定的格式在服务端做持久化处理,并设置过期时间;本文选取第一种简单的方案来处理。还有一点需要注意由于聊天信息保存在客户端,也未作持久化处理,在客户端保存的聊天信息失效时间点是用户关闭了浏览器,因为聊天信息是保存在本地特定的集合中,当用户关闭浏览器之后,将会丢失这些信息。
4.3 加载临时保存的聊天信息和未读消息。有了临时保存聊天信息方案,若A 用户切换聊天对象后,能恢复与B 之前的聊天信息,同时还要检查B 是否给A 发消息且A 未读这些消息,若有,在恢复完与B 之前的聊天信息后,还需要加载未读消息。具体步骤如下:通过A 的UUID 与B 的UUID 组合起来从已读消息集合中取出聊天信息Messages。遍历Messages,通过每一条消息中的标识位(not Mine 和空)来判断添加在聊天的界面左侧或者右侧。通过B的UUID 去遍历未读消息集合,消息需满足标志为未读,这是为了避免重复加载。这里是直接将未读消息添加到聊天界面的右侧,同时该条消息会被添加到对应的已读消息集合。
4.4 加载所有在线用户。A 用户运行系统,首先调用客户端的On open 方法以随机生成的UUID 码作为用户名与服务端建立连接;服务端接收到客户端的连接,同时将用户名和对应的session 保存在一个特定的[key,value]集合中;之后当前客户端加载所有在线用户并以列表的形式展示,同时通过调用服务端的On message 方法通知其它所有在线的用户,A 上线了需要重新加载好友列表。
4.5 未读消息提示。先逐一遍历本地未读消息的集合,每遍历一条消息之后都会遍历一遍A 用户的在线好友列表,如果未读消息的发送方与A 用户的好友列表中某一个用户名相等,则在A 用户对应的好友列表上将未读消息数量上加一。如图所示。
未读消息提示
4.6 未读消息清空。若A 用户打开与B 用户的聊天界面,后台会加载B 发送给A 且A 未读的消息,加载完B 发过来的消息后,需要把B 对应的未读消息数量设置为0。
首先,在linux 服务器上安装docker,修改镜像为阿里云私人镜像地址,安装完成后,直接拉取一个标准的tomcat 镜像下来;安装Docker-compose,它是docker 的服务编排工具,主要是用来构建多个服务。在docker-compose.yml 文件中写好对tomcat 的配置,其中有一个比较重要的属性就是数据卷属性,要设置宿主机目录和容器目录,这里的容器目录指的是tomcat 的webapps 目录,可以简单理解为如果在宿主机目录下放了项目war 包,那么容器目录下也会有,起一个共享数据的作用,知道了这个作用,那么直接将war 包放在服务器指定的目录下即可。一切准备就绪,通过docker-compose启动我们的服务。如果后期项目需要多个tomcat,那是不是在docker-compose 的配置文件中配置多个tomcat 即可呢,如果又需要mysql,同样可以加进来。只需要一个命令即可启动配置文件中所有定义好的服务,非常简捷。当然它的好处还有很多,这里就不一一列举了。
在整个实现过程中,编码不是特别规范,比如在某些地方采取拼接字符串来实现一些需求,这样的后果就是若后期出现大规模修改会出现bug,修改起来费时费力,因此在以后的开发中应该尽可能规划好自己的开发流程,同提升编码的健壮性。此外,本系统没有采用设计模式,一切采用最基本的编码方式,旨在于给那些学习即时通讯的同学提供一种参考,能够快速入门。