2小时快速搭建一个高可用的IM系统( 四 )

借助 Go 语言很容易搭建协程的特点 , 我专门开启了一个协程每秒向客户端发送一条消息 。
打开客户端浏览器可以看到 , Frame 中每秒的心跳数据一直在跳动 , 当长链接断开之后 , 心跳就没有了 , 就像人没有了心跳一样:

2小时快速搭建一个高可用的IM系统

文章插图
 
 
大家对 WebSocket 协议已经有了了解 , 接下来就让我们一起快速搭建一个高性能、可拓展的 IM 系统吧 。
快速搭建高性能、可拓展的 IM 系统
①系统架构和代码文件目录结构
下图是一个比较完备的 IM 系统架构:包含了 C 端、接入层(通过协议接入)、S 端处理逻辑和分发消息、存储层用来持久化数据 。
2小时快速搭建一个高可用的IM系统

文章插图
 
我们本节 C 端使用的是 Webapp, 通过 Go 语言渲染 Vue 模版快速实现功能 , 接入层使用的是 WebSocket 协议 , 前边已经进行了深入的介绍 。
S 端是我们实现的重点 , 其中鉴权、登录、关系管理、单聊和群聊的功能都已经实现 , 读者可以在这部分功能的基础上再拓展其他的功能 , 比如:视频语音聊天、发红包、朋友圈等业务模块 。
存储层我们做的比较简单 , 只是使用 MySQL 简单持久化存储了用户关系 , 然后聊天中的图片资源我们存储到了本地文件中 。
虽然我们的 IM 系统实现的比较简化 , 但是读者可以在次基础上进行改进、完善、拓展 , 依然能够作出高可用的企业级产品 。
我们的系统服务使用 Go 语言构建 , 代码结构比较简洁 , 但是性能比较优秀(这是 Java 和其他语言所无法比拟的) , 单机支持几万人的在线聊天 。
下边是代码文件的目录结构:
app │├── args ││├── contact.go ││└── pagearg.go │├── controller//控制器层 , api入口 ││├── chat.go ││├── contract.go ││├── upload.go ││└── user.go │├── main.go//程序入口 │├── model//数据定义与存储 ││├── community.go ││├── contract.go ││├── init.go ││└── user.go │├── service//逻辑实现 ││├── contract.go ││└── user.go │├── util//帮助函数││├── md5.go ││├── parse.go ││├── resp.go ││└── string.go │└── view//模版资源 ││├── ... asset//js、css文件 resource//上传资源 , 上传图片会放到这里 从入口函数 main.go 开始 , 我们定义了 Controller 层 , 是客户端 API 的入口 。Service 用来处理主要的用户逻辑 , 消息分发、用户管理都在这里实现 。
Model 层定义了一些数据表 , 主要是用户注册和用户好友关系、群组等信息 , 存储到 MySQL 。
Util 包下是一些帮助函数 , 比如加密、请求响应等 。View 下边存储了模版资源信息 , 上边所说的这些都在 App 文件夹下存储 , 外层还有 asset 用来存储 css、js 文件和聊天中会用到的表情图片等 。
Resource 下存储用户聊天中的图片或者视频等文件 。总体来讲 , 我们的代码目录机构还是比较简洁清晰的 。
了解了我们要搭建的 IM 系统架构 , 我们再来看一下架构重点实现的功能吧 。
②10 行代码万能模版渲染
Go 语言提供了强大的 html 渲染能力 , 非常简单的构建 Web 应用 , 下边是实现模版渲染的代码 , 它太简单了 , 以至于可以直接在 main.go 函数中实现:
func registerView() {tpl, err := template.ParseGlob("./app/view/**/*")if err != nil {log.Fatal(err.Error())}for _, v := range tpl.Templates() {tplName := v.Name()http.HandleFunc(tplName, func(writer http.ResponseWriter, request *http.Request) {tpl.ExecuteTemplate(writer, tplName, nil)})} } ... func main() {......http.Handle("/asset/", http.FileServer(http.Dir(".")))http.Handle("/resource/", http.FileServer(http.Dir(".")))registerView()log.Fatal(http.ListenAndServe(":8081", nil)) } Go 实现静态资源服务器也很简单 , 只需要调用 http.FileServer 就可以了 , 这样 HTML 文件就可以很轻松的访问依赖的 js、css 和图标文件了 。
使用 http/template 包下的 ParseGlob、ExecuteTemplate 又可以很轻松的解析 Web 页面 , 这些工作完全不依赖与 Nginx 。


推荐阅读