前言
终于到了本系列的第二篇文章。在过去的几天中,我粗略地将小册一刷完成,我猜测KIM的作者是一个有相当经验的架构师,奈何我实际项目经验缺乏、理论知识积累也不多,所以对小册中的很多内容还是没有看懂,打算到时候找个时间二刷。下文是我阅读源码时的一些笔记和心得,对于其中理解还不到位的地方,我后期也会积极勘误。
目录结构
我们可以通过对项目目录的浏览来整体把握项目的设计:
这里通过tree命令的-d参数将具体文件名字隐去了,注释是我手动加的
.
├── container //服务的运行环境,解耦服务的创建和运行过程,管理服务间的依赖关系
├── examples //测试用例
│ ├── benchmark
│ ├── dialer
│ ├── echo
│ ├── kimbench
│ ├── mock //通过假数据模拟
│ └── unittest
├── logger //日志
├── middleware //中间件
├── naming
│ └── consul
├── report
├── services
│ ├── gateway //网关
│ │ ├── conf
│ │ └── serv
│ ├── router //路由
│ │ ├── apis
│ │ ├── conf
│ │ ├── data
│ │ └── ipregion
│ ├── server //服务器配置
│ │ ├── conf
│ │ ├── handler
│ │ ├── serv
│ │ └── service
│ └── service //服务配置
│ ├── conf
│ ├── database
│ └── handler
├── storage //存储-缓存
├── tcp //底层实现-tcp
├── websocket //底层实现-websocket
└── wire //通信底层的一些实现
├── endian //机器指令以大端序读取
├── pkt //packet相关,比如格式
├── proto //rpc会用到的原型
├── rpc //rpc有关的方法(似乎是模板生成的代码)
└── token //jwt校验
由此来看,项目结构主要分为三部分:
- 底层实现
- 业务实现
- 测试相关
引用的库
虽然KIM涉及到了很多底层的内容,但是它也会用到一些现成的库来简化开发流程,提升开发效率,这从go.mod文件中能窥见一二。
- github.com/Joker/hpp v1.0.0 // indirect
HTML Pretty Print for Go,从readme文档看,似乎是将html代码重新格式化。(不过不知道是不是还有什么隐藏功能,毕竟格式化这种事情按一下编辑器的快捷键也可以实现相同效果?)
- github.com/bwmarrin/snowflake v0.3.0
生成分布式id的雪花算法,在我之前的笔记文章中也有简要记录过。
- github.com/dgrijalva/jwt-go v3.2.0+incompatible
适用于go的jwt校验
- github.com/go-redis/redis/v7 v7.4.0
缓存Redis
- github.com/go-resty/resty/v2 v2.6.0
Restful风格的http框架
- github.com/gobwas/pool v0.2.1
Tiny memory reuse helpers for Go
内存碎片重用。(最初看到名字还以为是数据库连接池相关,没想到竟然和内存复用有关,看官网示例,好像是可以指定大小范围)
- github.com/gobwas/ws v1.0.4
RFC6455 WebSocket的实现
- github.com/golang/mock v1.6.0
生成假数据
- github.com/golang/protobuf v1.4.3
github链接的readme中说现在官方库已经出了,建议使用官方版google.golang.org/protobuf
- github.com/hashicorp/consul/api v1.8.1
Consul is a distributed, highly available, and data center aware solution to connect and configure applications across dynamic, distributed infrastructure
通过上述官方介绍,能提取出一些性能关键词,而它更具体的作用在下面这段:
- Multi-Datacenter 多数据中心
- Service Mesh 为复杂的云原生应用构建相应可靠的网络请求
- Service Discovery 服务发现
- Health Checking 健康监测,比如检测一个集群节点是否存活
- Key/Value Storage 以键值方式存储有关动态配置、特征标记、节点leader选举等等的内容
总的来说,它可以理解为是构建微服务会用到的一个重要组件,涵盖了相关的基本功能。
- github.com/kataras/iris/v12 v12.2.0-alpha2.0.20210705170737-afb15b860124
go的http框架,类似的有Gin,hertz等
- github.com/kelseyhightower/envconfig v1.4.0
一个从环境变量中管理配置数据的工具。
从官方示例看,这个库的作用是:在系统的配置文件中写入了一些配置后,可以通过库的一些机制,将配置写成go结构体的形式,并且方便打印查看等等。
在KIM项目中,在其他工具的帮助下(比如viper),它还可以化身为配置文件。
以某个config.go为例:
这是配置项对应的结构体
// Config Config
type Config struct {
ServiceID string
ServiceName string `default:"wgateway"`
Listen string `default:":8000"`
...
LogLevel string `default:"DEBUG"`
MessageGPool int `default:"10000"`
ConnectionGPool int `default:"15000"`
}
该文件中还有一段初始化配置的代码:
// Init InitConfig
func Init(file string) (*Config, error) {
viper.SetConfigFile(file)
viper.AddConfigPath(".")
viper.AddConfigPath("/etc/conf")
...
return &config, nil
}
我目前的理解是这一段就是运行应用时向系统写入相关配置,无需事先手动配置。
- github.com/kr/text v0.2.0 // indirect
管理文本段落的工具包
- github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
github仓库中,作者特别提醒不要再使用该库,因为该库已不再维护。
- github.com/lestrrat-go/strftime v1.0.4 // indirect
与输出格式化相关的库
- github.com/lionsoul2014/ip2region v2.2.0-release+incompatible
一个可以通过ip定位地址和数据的框架
- github.com/mattn/go-colorable v0.1.8 // indirect
一个让windows的cmd中的输出更好看的库(说实话我不太理解这有什么用,对高可用系统来说界面好看有这么重要吗?不是windows系统的话不就用不上了?)
- github.com/mattn/go-isatty v0.0.13 // indirect
c语言中的isatty(int handle)通过文件描述符判断是否为设备类型:设备类型返回1,普通文件返回0。
这个Go语言版的也差不多。以下是github中的示例代码:
package main
import (
"fmt"
"github.com/mattn/go-isatty"
"os"
)
func main() {
if isatty.IsTerminal(os.Stdout.Fd()) {
fmt.Println("Is Terminal")
} else if isatty.IsCygwinTerminal(os.Stdout.Fd()) {
fmt.Println("Is Cygwin/MSYS2 Terminal")
} else {
fmt.Println("Is Not Terminal")
}
}
- github.com/panjf2000/ants/v2 v2.4.6
一个高性能、低损耗的go协程管理池
- github.com/prometheus/client_golang v1.11.0
用Go语言写的连接Prometheus(一款基于时序数据库的开源监控告警系统)的客户端
- github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5
看github介绍应该是支持直接向文件系统写入日志文件(多级别的)
- github.com/segmentio/ksuid v1.0.3
用于生成和解析一种称为 KSUID 的特定类型的全局唯一标识符。它遵循类似RFC 4122 UUID的标准,从头开始构建,按生成时间戳“自然”排序。
- github.com/sirupsen/logrus v1.7.0
一个日志记录工具,最新状态是维护中,不再更新新特性
- github.com/spf13/cobra v0.0.5
一个便于创建CLI(command line interface)应用的库
- github.com/spf13/viper v1.7.1
一个用来写配置的库
- github.com/stretchr/testify v1.7.0
一个用于测试的库
系统架构
在了解了项目的基本结构、自主编写部分的代码以及所使用的扩展库后,再去理解它的系统架构图就变得容易了。
下期将会对深入分析源码的编写细节。
参考资料
- 掘金小册:分布式IM原理与实战: 从0到1打造即时通讯云
- Github链接 KIM github链接