【计算机网络实战】简易IM(二)KIM源码解读

302 阅读5分钟

前言

终于到了本系列的第二篇文章。在过去的几天中,我粗略地将小册一刷完成,我猜测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的雪花算法,在我之前的笔记文章中也有简要记录过。

image.png

  • 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

一个用于测试的库

系统架构

在了解了项目的基本结构、自主编写部分的代码以及所使用的扩展库后,再去理解它的系统架构图就变得容易了。

image.png

下期将会对深入分析源码的编写细节。

参考资料