- 后端
- 即时通讯
- 微服务
【免费下载链接】goim
goim
goim 是一个用纯 Golang 编写的即时通讯(IM)服务端及实时推送集群,支持单推、多推、房间推送与全量广播,并内置心跳、鉴权、多协议接入与基于 Kafka 的异步推送链路。本文以项目根目录 README.md 为主线,结合仓库内源码与配置,完整讲解 goim 的特性、架构、构建启动、配置项、依赖环境、客户端协议、推送 API 与官方基准测试数据,帮助读者在真实业务中快速部署并深入理解其工作原理。
核心特性:一次看懂 goim 能做什么
README.md 将 goim v2.0 的特性归纳为以下几点,这些特性全部可以在仓库源码中找到对应实现:
- 轻量级、高性能、纯 Golang:服务端全部由 Go 实现(
internal/comet、internal/logic、internal/job三个模块),不依赖任何重量级框架; - 灵活的推送粒度:支持单个推送(PushKeys)、多个推送(PushMids)、房间推送(PushRoom)以及全量广播(PushAll),对应实现见 internal/logic/push.go;
- 一键多订阅者:单个 Key(用户)可以挂载多个订阅连接,可通过配置限制最大订阅者数量,对应接入层 internal/comet/channel.go;
- 完整的心跳机制:支持应用层心跳、TCP KeepAlive 与长连接心跳,对应协议指令
OpHeartbeat(见 api/protocol/operation.go); - 安全鉴权:未授权的用户无法订阅消息,认证指令
OpAuth/OpAuthReply负责连接鉴权; - 多协议接入:支持 WebSocket、TCP(README 同时提及 HTTP 长轮询场景);
- 可水平扩展的架构:comet(接入层)与 logic(逻辑层)均为无状态/可动态扩容模块,job 可随 Kafka partition 扩展;
- 基于 Kafka 的异步推送:logic 将推送消息写入 Kafka,job 消费后路由到对应 comet,实现推送与业务解耦。
系统架构:comet、logic、job 三模块如何协同
goim v2.0 采用三层架构,三个可执行程序各自独立部署、通过 Discovery 服务发现相互协作:
- comet(接入层):负责维持客户端长连接。它启动 TCP(默认
:3101)与 WebSocket(默认:3102,可开 TLS:3103)监听端口,通过Bucket数据结构管理海量 Channel。从 internal/comet/server.go 可以看到,NewServer会按配置创建Bucket.Size个 Bucket,并通过 cityhash 将订阅 Key 均匀哈希到不同 Bucket 中,实现连接的水平切分。每个 Bucket 内部又维护多个 Room 与多路广播协程(见 internal/comet/bucket.go),配合 internal/comet/ring.go 的环形缓冲区实现高吞吐收发; - logic(逻辑层):无状态业务层,对外提供 HTTP 推送/查询接口(默认
:3111)与 gRPC 服务(默认:3119),负责鉴权、在线状态维护、Redis 存储与消息路由决策; - job(推送任务层):作为 Kafka 消费者,监听推送 topic(默认
goim-push-topic),通过 Discovery 实时感知 comet 节点列表,把消息投递到目标 comet。消费与重新平衡逻辑见 internal/job/job.go。
三个模块启动时都会将自己注册到 bilibili Discovery(注册逻辑见 cmd/comet/main.go 等入口文件),comet 还会周期性上报连接数(conn_count)与 IP 数(ip_count)等元数据,供 logic 完成负载均衡与节点发现。
快速上手:从构建到启动
构建
goim 提供了完整的 Makefile(见 Makefile),一条命令即可完成构建:
make buildbuild目标会执行以下动作:清空并创建target/目录、将三个示例配置复制为target/comet.toml、target/logic.toml、target/job.toml,然后分别编译出target/comet、target/logic、target/job三个二进制。也可以通过make test运行全量单元测试(go test -v ./...)。
启动
提供了两种启动方式。方式一是使用 Makefile 的run/stop目标(后台运行并分别输出到target/comet.log等日志文件):
make run make stop方式二是手动nohup启动,分别指定各自配置文件与运行参数(注意:三个进程必须带一致的region/zone/deploy.env参数,comet 与 logic 还需携带weight负载权重,comet 额外需要-addrs声明对外地址):
nohup target/logic -conf=target/logic.toml -region=sh -zone=sh001 -deploy.env=dev -weight=10 2>&1 > target/logic.log & nohup target/comet -conf=target/comet.toml -region=sh -zone=sh001 -deploy.env=dev -weight=10 -addrs=127.0.0.1 2>&1 > target/comet.log & nohup target/job -conf=target/job.toml -region=sh -zone=sh001 -deploy.env=dev 2>&1 > target/job.log &提示:README 示例中三个进程的日志都写到了
target/logic.log,这是文档中的笔误;实际运行时建议参照 Makefile 的run目标,为每个进程使用独立的日志文件,便于排查问题。
运行环境与命令行参数
goim 的所有运行参数都可以通过命令行 flag 或环境变量两种方式注入(两者优先级以 flag 为准,实现见 internal/comet/conf/conf.go 与 internal/logic/conf/conf.go):
env: export REGION=sh export ZONE=sh001 export DEPLOY_ENV=dev supervisor: environment=REGION=sh,ZONE=sh001,DEPLOY_ENV=dev go flag: -region=sh -zone=sh001 -deploy.env=dev常用 flag 及其含义如下(环境变量形式:REGION/ZONE/DEPLOY_ENV/WEIGHT/ADDRS/OFFLINE/DEBUG):
| Flag | 默认值 | 说明 |
|---|---|---|
-conf | 各模块的*-example.toml | 配置文件路径 |
-region | 环境变量REGION | 区域标识,如sh |
-zone | 环境变量ZONE | 可用区标识,如sh001 |
-deploy.env | 环境变量DEPLOY_ENV | 部署环境,如dev/prod |
-host | 机器 hostname | 节点 hostname,作为 comet 的 serverID |
-weight | 环境变量WEIGHT | 负载均衡权重(comet/logic) |
-addrs | 环境变量ADDRS | 对外公网地址列表(comet) |
-offline | 环境变量OFFLINE | 是否标记节点下线(comet) |
-debug | 环境变量DEBUG | 开启调试日志(comet) |
启动后,comet、logic、job 都会监听系统信号,收到SIGQUIT/SIGTERM/SIGINT时依次完成注销服务、gRPC GracefulStop、资源关闭与日志 Flush 后优雅退出(见 cmd/comet/main.go)。
配置详解:三份示例配置逐项解读
README 明确指出“可以通过查看target/comet.toml、logic.toml、job.toml中的注释来理解配置含义”,仓库根目录下即提供了三份可直接使用的示例配置。下面结合配置结构体定义逐项说明。
comet 配置:cmd/comet/comet-example.toml
[discovery] nodes = ["127.0.0.1:7171"] [rpcServer] addr = ":3109" timeout = "1s" [rpcClient] dial = "1s" timeout = "1s" [tcp] bind = [":3101"] sndbuf = 4096 rcvbuf = 4096 keepalive = false reader = 32 readBuf = 1024 readBufSize = 8192 writer = 32 writeBuf = 1024 writeBufSize = 8192 [websocket] bind = [":3102"] tlsOpen = false tlsBind = [":3103"] certFile = "../../cert.pem" privateFile = "../../private.pem" [protocol] timer = 32 timerSize = 2048 svrProto = 10 cliProto = 5 handshakeTimeout = "8s" [whitelist] Whitelist = [123] WhiteLog = "/tmp/white_list.log" [bucket] size = 32 channel = 1024 room = 1024 routineAmount = 32 routineSize = 1024配置项说明(字段定义见 internal/comet/conf/conf.go):
| 配置节 | 关键参数 | 作用 |
|---|---|---|
discovery | nodes | Discovery 服务地址列表,用于服务注册与发现 |
rpcServer | addr/timeout | 对外 gRPC 服务监听地址(默认:3109)与超时 |
rpcClient | dial/timeout | comet 调用 logic 的 gRPC 拨号与请求超时 |
tcp | bind | TCP 监听端口列表,支持绑定多个端口;sndbuf/rcvbuf为读写缓冲字节数,reader/writer为收发协程数,readBuf/writeBuf为缓冲通道容量,readBufSize/writeBufSize为单缓冲大小 |
websocket | bind/tlsOpen/tlsBind | WebSocket 监听端口;tlsOpen=true时启用 TLS,证书文件取自certFile与privateFile |
protocol | timer/timerSize | 定时器数量与大小;svrProto/cliProto为服务端/客户端协议缓冲池容量;handshakeTimeout为握手超时 |
whitelist | Whitelist/WhiteLog | 推送白名单(按 mid 配置)与白名单日志路径,由comet.InitWhitelist加载 |
bucket | size | Bucket 数量,影响连接哈希分片粒度与并发度;channel/room为 Channel、Room 初始 map 容量;routineAmount/routineSize为每个 Bucket 内的广播协程数量与消息通道容量 |
logic 配置:cmd/logic/logic-example.toml
[discovery] nodes = ["127.0.0.1:7171"] [regions] "bj" = ["北京","天津","河北","山东","山西","内蒙古","辽宁","吉林","黑龙江","甘肃","宁夏","新疆"] "sh" = ["上海","江苏","浙江","安徽","江西","湖北","重庆","陕西","青海","河南","台湾"] "gz" = ["广东","福建","广西","海南","湖南","四川","贵州","云南","西藏","香港","澳门"] [node] defaultDomain = "conn.goim.io" hostDomain = ".goim.io" heartbeat = "4m" heartbeatMax = 2 tcpPort = 3101 wsPort = 3102 wssPort = 3103 regionWeight = 1.6 [backoff] maxDelay = 300 baseDelay = 3 factor = 1.8 jitter = 0.3 [rpcServer] network = "tcp" addr = ":3119" timeout = "1s" [rpcClient] dial = "1s" timeout = "1s" [httpServer] network = "tcp" addr = ":3111" readTimeout = "1s" writeTimeout = "1s" [kafka] topic = "goim-push-topic" brokers = ["127.0.0.1:9092"] [redis] network = "tcp" addr = "127.0.0.1:6379" active = 60000 idle = 1024 dialTimeout = "200ms" readTimeout = "500ms" writeTimeout = "500ms" idleTimeout = "120s" expire = "30m"配置项说明(字段定义见 internal/logic/conf/conf.go):
regions:区域-省份映射表,用于按用户地域路由/加权分配 comet 节点;node:节点信息模板,defaultDomain/hostDomain为域名配置,tcpPort/wsPort/wssPort与 comet 各协议端口对应,heartbeat/heartbeatMax为下发给客户端的心跳周期与最大尝试次数,regionWeight为跨区域权重系数;backoff:客户端连接失败时的指数退避参数(maxDelay最大延迟秒、baseDelay初始延迟、factor增长因子、jitter抖动系数);rpcServer/rpcClient/httpServer:gRPC 服务(:3119)、gRPC 客户端与 HTTP 服务(:3111)的监听与超时配置;kafka:推送 topic 与 broker 地址列表;redis:在线状态与 Key 映射存储,expire = "30m"表示在线记录的过期时间,active/idle为连接池最大活跃/空闲连接数。
job 配置:cmd/job/job-example.toml
[discovery] nodes = ["127.0.0.1:7171"] [kafka] topic = "goim-push-topic" group = "goim-push-group-job" brokers = ["127.0.0.1:9092"]job 的配置最为精简:discovery.nodes用于发现 comet 节点,kafka节指定消费的 topic、消费者组(group)与 broker 列表。job 通过sarama-cluster以消费者组方式消费(见 internal/job/job.go),topic 的 partition 数量即决定了 job 的可扩展上限。
外部依赖:Discovery 与 Kafka
goim v2.0 有两个强依赖,README 专门列出:
- Discovery(bilibili discovery,默认地址
127.0.0.1:7171):承担服务注册与发现职责。comet 与 logic 启动时通过naming.New+resolver.Register注册 gRPC 服务(见 cmd/logic/main.go),job 则通过dis.Build("goim.comet")监听 comet 节点变更(见 internal/job/job.go); - Kafka:异步推送的消息队列。logic 收到推送请求后写入 Kafka topic,job 作为消费者取出
PushMsg(protobuf 序列化)并路由到对应 comet。这条链路保证了推送高峰期的削峰与解耦。
客户端通讯协议与推送 API
comet 客户端协议
comet 支持 WebSocket 与 TCP 两种客户端协议,完整定义见 docs/proto.md。
WebSocket:请求地址为ws://DOMAIN/sub,采用 JSON Frame,请求与返回结构一致:
{ "ver": 102, "op": 10, "seq": 10, "body": {"data": "xxx"} }其中ver为协议版本号,op为指令,seq为序列号(与响应一一对应),body为授权令牌。
TCP:请求地址为tcp://DOMAIN,采用二进制协议,包结构为:包长度(int32 大端)+ 包头长度(int16 大端)+ 版本号(int16 大端)+ 操作指令(int32 大端)+ 序列号(int32 大端)+ body(长度 = 包长度 - 包头长度)。
指令对照表(详见 api/protocol/operation.go):
| 指令 | 说明 |
|---|---|
| 0/1 | 握手 / 握手回复 |
| 2/3 | 客户端心跳 / 服务端心跳回复 |
| 4/5 | 发送消息 / 发送消息回复(下行消息) |
| 7/8 | 认证 / 认证回复 |
| 14/15 | 订阅 / 订阅回复 |
| 16/17 | 退订 / 退订回复 |
HTTP 推送 API
logic 对外暴露完整的 HTTP 推送与在线查询接口,详见 docs/push.md。统一返回格式为 JSON,错误码约定:OK = 0、RequestErr = -400、ServerErr = -500。主要接口如下:
| 接口 | 方法 | 说明 |
|---|---|---|
/goim/push/keys | POST | 按 Key 列表推送,参数operation、keys,body 为消息内容 |
/goim/push/mids | POST | 按用户 mid 列表推送,参数operation、mids |
/goim/push/room | POST | 按房间推送,参数operation、type(房间类型)、room(房间 ID) |
/goim/push/all | POST | 全量广播,参数operation、speed(推送速率限制) |
/goim/online/top | GET | 查询在线人数 Top 房间,参数type、limit |
/goim/online/room | GET | 查询指定房间在线人数,参数type、rooms |
/goim/online/total | GET | 查询总连接数与 IP 数(返回conn_count、ip_count) |
/goim/nodes/weighted | GET | 获取加权后的节点信息(域名、端口、心跳参数、退避策略),供客户端选择接入节点 |
/goim/nodes/instances | GET | 获取全部 comet 实例信息(region、zone、地址、连接数、权重等元数据) |
推送请求示例(/goim/push/keys):
POST /goim/push/keys?operation=5&keys=key1,key2 Body: {"test":1} response: { "code": 0 }这些接口分别映射到 internal/logic/push.go 中的PushKeys、PushMids、PushRoom、PushAll实现,最终经 Kafka 交给 job 异步分发。
示例客户端
仓库提供了可直接运行的示例:
- WebSocket 客户端:examples/javascript/client.js(含 examples/javascript/index.html 网页演示),展示如何连接 comet、完成握手/认证并收发消息;
- 服务端示例:examples/javascript/main.go 演示服务端调用 logic 推送接口;
- 第三方 SDK:README 同时收录了 Android 与 iOS 的社区 SDK 入口,可作客户端参考。
官方基准测试
README 记录了官方在单台服务器上完成的压测数据(详细中文报告见 docs/benchmark_cn.md,英文版见 docs/benchmark_en.md):
压测环境(1 台实例)
| CPU | 内存 | OS |
|---|---|---|
| Intel(R) Xeon(R) CPU E5-2630 v2 @ 2.60GHz | DDR3 32GB | Debian GNU/Linux 8 |
压测场景
| 项目 | 数值 |
|---|---|
| 在线连接数 | 1,000,000 |
| 压测时长 | 15 分钟 |
| 广播推送速率 | 40 条/秒(房间广播) |
| 推送消息 | {"test":1} |
| 接收统计方式 | 每秒采样 1 次,共 30 次 |
资源占用
| 项目 | 数值 |
|---|---|
| CPU | 2000% ~ 2300% |
| 内存 | 14GB |
| GC 暂停 | 504ms |
| 网络 | 入向 450MBit/s,出向 4.39GBit/s |
压测结果:消息接收速率达到35,900,000 条/秒。
以上数据为项目官方 README 记录的基准测试结果,实际性能取决于机器规格、网络环境与配置调优,请以自建压测为准。
许可协议
goim 基于MIT License开源(见根目录 LICENSE),可自由用于商业与非商业项目。需要说明的是,v2.0 版本同时依赖 bilibili Discovery 与 Kafka 两个外部服务,部署前请先准备这两套环境(Kafka 快速安装可参考 scripts/kafka.sh 与 scripts/zk.sh)。
从特性梳理、架构拆解,到 Makefile 构建、三份 TOML 配置逐项解读、协议指令与 HTTP 推送接口,再到官方压测数据,本文已完整覆盖 README.md 的全部核心内容,并辅以仓库源码级佐证。按照本文步骤搭建 Discovery 与 Kafka 后,依次启动 logic、comet、job 三个进程,即可跑通一套可水平扩展的 goim 实时推送集群。
- 后端
- 即时通讯
- 微服务
【免费下载链接】goim
goim
相关推荐
5分钟掌握SAMKeychain:iOS/macOS钥匙串安全存储终极指南
5分钟掌握SAMKeychain:iOS/macOS钥匙串安全存储终极指南 在iOS和macOS开发中,安全存储用户敏感数据一直是开发者面临的重要挑战。SAMK
应用安全Goim消息推送终极指南:单推、群推、广播性能对比与最佳实践
Goim消息推送终极指南:单推、群推、广播性能对比与最佳实践 Goim是一个高性能的即时消息推送系统,支持单个、多个、单房间以及广播消息推送等多种推送模式,能够
后端即时通讯微服务Sliver 通知集成实战:基于 nikoksr/notify 的 Pushover 推送服务接入指南
Sliver 通知集成实战:基于 nikoksr/notify 的 Pushover 推送服务接入指南 本篇技术指南以 nikoksr/notify 的 Pus
网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考