meshserver 是一个基于 Go 1.26 与 libp2p 的服务端节点,实现了 /meshserver/session/1.0.0 会话协议、基于 Peer ID 的 challenge-response 认证、Space / channel 目录查询、频道订阅、消息发送、按 channel 递增的 seq 增量同步,以及附件 SHA-256 去重存储。
这里的层级关系按文档语义理解为 node -> space -> channel。协议字段里的 space_id、channel_id 现在都已经改成 uint32 自增数值主键。
项目目标是开箱即跑:进入 docker-compose/docker-compose.yml 所在目录后执行 docker compose up -d --build 即可启动服务和 MySQL,并把运行数据全部落在 docker-compose/data/ 下。
已实现:
- libp2p 节点启动与身份密钥持久化
- 协议
/meshserver/session/1.0.0 HELLO -> AUTH_CHALLENGE -> AUTH_PROVE -> AUTH_RESULT鉴权闭环LIST_SPACES_REQ / RESPLIST_CHANNELS_REQ / RESPSUBSCRIBE_CHANNEL_REQ / RESPJOIN_SPACE_REQ / RESPINVITE_SPACE_MEMBER_REQ / RESPKICK_SPACE_MEMBER_REQ / RESPBAN_SPACE_MEMBER_REQ / RESPLIST_SPACE_MEMBERS_REQ / RESPUNBAN_SPACE_MEMBER_REQ / RESPCREATE_GROUP_REQ / RESPCREATE_CHANNEL_REQ / RESPADMIN_SET_SPACE_MEMBER_ROLE_REQ / RESPADMIN_SET_SPACE_CHANNEL_CREATION_REQ / RESPADMIN_SET_GROUP_AUTO_DELETE_REQ / RESPSEND_MESSAGE_REQ / ACKMESSAGE_EVENTCHANNEL_DELIVER_ACKCHANNEL_READ_UPDATESYNC_CHANNEL_REQ / RESPGET_MEDIA_REQ / RESP- 按
channel_id + seq单调递增的消息序列 (channel_id, sender_user_id, client_msg_id)幂等去重- 图片/文件附件 SHA-256 去重存储
- HTTP 管理面:
/healthz、/readyz、/version - 首次启动自动迁移,不再自动创建任何默认 Space 或 channel
- 管理员可以通过 libp2p 会话修改成员角色、邀请/踢出/封禁/解封成员、分页列出成员和创建频道开关
文档里的层级关系按 node -> space -> channel 理解。现有协议字段已经统一为 uint32 类型的 space_id、channel_id。
未实现:
- 多设备身份合并
- 节点间联邦同步
- 消息编辑、撤回、reaction
- 复杂全文搜索与后台任务
- 独立的媒体上传协议
/meshserver/media/1.0.0
说明:
- 第一版为了让附件闭环可用,在
MediaImage/MediaFile上额外加入了inline_data字段,允许客户端直接通过SEND_MESSAGE_REQ内联上传二进制内容。 - 现在也支持通过 libp2p 的
GET_MEDIA_REQ直接拉取文件,返回的MediaFile.inline_data就是文件内容。
meshserver/
cmd/meshserver/ # 程序入口
internal/
app/ # 应用装配与生命周期
api/ # HTTP 管理面
auth/ # challenge-response 认证
channel/ # channel 领域模型
config/ # 配置加载
db/ # MySQL 连接与迁移执行
gen/proto/ # 已生成 protobuf Go 代码
libp2p/ # libp2p host 与 identity
logx/ # 结构化日志
media/ # blob 去重与媒体存储
message/ # message 领域模型
protocol/ # length-prefixed protobuf 编解码
repository/ # repository 接口与 MySQL 实现
space/ # space 领域模型
service/ # 跨领域业务编排
session/ # 会话管理与协议分发
storage/ # 本地文件存储
migrations/ # SQL 迁移
proto/ # protobuf 源文件
scripts/ # proto 生成与自检脚本
docker-compose/ # Compose 启动目录与持久化数据目录
核心环境变量如下,完整示例见 .env.example:
MESHSERVER_MYSQL_DSNMESHSERVER_MYSQL_ADMIN_DSNMESHSERVER_MYSQL_SERVER_PUB_KEY_PATHMESHSERVER_HTTP_LISTEN_ADDRMESHSERVER_LIBP2P_LISTEN_ADDRSMESHSERVER_LIBP2P_PROTOCOL_IDMESHSERVER_NODE_KEY_PATHMESHSERVER_BLOB_ROOTMESHSERVER_LOG_DIRMESHSERVER_MIGRATIONS_DIRMESHSERVER_CHALLENGE_TTLMESHSERVER_MAX_TEXT_LENMESHSERVER_MAX_IMAGES_PER_MESSAGEMESHSERVER_MAX_FILES_PER_MESSAGEMESHSERVER_MAX_UPLOAD_BYTESMESHSERVER_DHT_DISCOVERY_NAMESPACEMESHSERVER_DHT_BOOTSTRAP_PEERS
配置优先级:
- 环境变量
- JSON 配置文件
- 默认值
Docker Compose 示例配置模板见 meshserver.json.example。
MESHSERVER_DHT_BOOTSTRAP_PEERS 是可选的 bootstrap 多地址列表,多个地址用逗号分隔。节点启动后会在后台自动尝试连接这些 bootstrap peer,然后再做 DHT bootstrap。
MESHSERVER_DHT_DISCOVERY_NAMESPACE 是 DHT 发现使用的 rendezvous 名称,客户端和服务端需要保持一致。默认值是 meshserver。
如果你只想看“客户端如何连上服务端”,可以直接运行:
go run ./examples/connect-client \
-discover \
-discover-namespace meshserver \
-dht-bootstrap-peer /ip4/127.0.0.1/tcp/4001/p2p/12D3KooW...这个案例会先通过 DHT 找到 meshserver 节点,然后自动连接、完成认证,并打印 Space 列表。
如果你已经知道服务端的 peer_id,也可以直接按 peer_id 连接:
go run ./examples/connect-client \
-node-peer-id 12D3KooW... \
-dht-bootstrap-peer /ip4/127.0.0.1/tcp/4001/p2p/12D3KooW...这个模式会先用 DHT 根据 peer_id 解析出地址,再建立连接并完成认证。
如果你想在连接后顺便查看自己能不能创建顶层 Space,可以加上:
go run ./examples/connect-client \
-node-peer-id 12D3KooW... \
-create-space-permissions \
-dht-bootstrap-peer /ip4/127.0.0.1/tcp/4001/p2p/12D3KooW...can_create_space 和 can_create_group 是两个不同的权限:
can_create_space表示你能不能创建新的顶层 space,不需要指定 space_idcan_create_group表示你能不能在某个已有 space 里创建 group
如果你想直接创建一个新 space,可以用 admin-client:
go run ./examples/admin-client \
-node-peer-id 12D3KooW... \
-create-space=true \
-new-space-name "AI Example Space" \
-new-space-description "Created by the admin client example" \
-new-space-visibility public \
-new-space-allow-channel-creation=true \
-dht-bootstrap-peer /ip4/127.0.0.1/tcp/4001/p2p/12D3KooW...如果你想给某个 group 设置自动删除周期,可以用 admin-client 对已有 channel_id 执行:
go run ./examples/admin-client \
-node-peer-id 12D3KooW... \
-group-auto-delete-channel-id 12 \
-group-auto-delete-after-seconds 86400 \
-create-group=false \
-dht-bootstrap-peer /ip4/127.0.0.1/tcp/4001/p2p/12D3KooW...这表示该 group 中早于 86400 秒之前的消息会被后台清理。
源文件位于 session.proto。
重新生成命令:
./scripts/gen-proto.sh生成目标目录:
internal/gen/proto/meshserver/session/v1/
当前仓库已经提交了已生成的 Go 文件,因此即使本机没有 protoc,也可以直接编译项目。
- 准备 MySQL 8.4+。
- 复制
.env.example为.env并按需修改。 - 执行:
make build
make run或者:
GOMODCACHE=$(pwd)/.gomodcache GOTOOLCHAIN=auto go run ./cmd/meshserver- 进入目录:
cd docker-compose- 复制
.env.example为.env:
cp .env.example .env- 启动:
docker compose up -d --build服务包括:
mysqlmeshserver
所有运行时数据都存放在 docker-compose/data/ 下:
- docker-compose/data/mysql
- docker-compose/data/blobs
- docker-compose/data/logs
- docker-compose/data/config
容器内映射关系:
./data/mysql -> /var/lib/mysql./data/blobs -> /app/data/blobs./data/logs -> /app/data/logs./data/config -> /app/data/config
主协议:
/meshserver/session/1.0.0
传输方式:
- libp2p stream
- 4-byte big-endian length-prefixed protobuf envelope
鉴权签名原文:
protocol_id=<protocol>
client_peer_id=<client-peer-id>
node_peer_id=<node-peer-id>
nonce=<base64>
issued_at_ms=<millis>
expires_at_ms=<millis>
启动后默认没有任何 Space、Group 或 Channel。
你需要先通过 CREATE_SPACE 创建第一个 Space,再通过 CREATE_GROUP 或 CREATE_CHANNEL 创建空间内的频道。
认证成功只会创建用户账号,不会自动加入任何 Space。
如果你要写一个 Go + libp2p 的 AI 节点客户端,可以直接参考 docs/ai-libp2p-client-guide.md。
GET /healthzGET /readyzGET /version
如果开启 MESHSERVER_ENABLE_DEBUG_CONFIG=true,还会暴露:
GET /debug/config
如果启用 blob 静态路由,可通过 /blobs/<storage_path> 访问已存储的附件内容。
默认端口:
- libp2p TCP:
4001 - HTTP 管理面:
8080 - MySQL:
3306
常用命令:
make proto
make build
make run
make test
make check
make compose-up
make compose-down自检脚本:
./scripts/check.shdocker compose up -d --build时 MySQL 一直 unhealthy
当前 Compose 使用的是 MySQL 8.4 默认的 caching_sha2_password,并通过 Docker 卷保存 MySQL 数据。若你想彻底重置数据库状态,可以先执行:
cd docker-compose
docker compose down
docker volume rm docker-compose_meshserver_mysql_data
docker compose up -d --build- 宿主机
4001端口已被占用
默认映射端口仍然是 4001。如果本机已有其它 libp2p 服务占用它,可以临时覆盖宿主机映射端口,不改仓库默认值:
cd docker-compose
MESHSERVER_LIBP2P_PORT=14001 docker compose up -d --build已实现范围偏向“最小可运行版本”,优先保证:
- 可编译
- 可启动
- 可连接
- 可落库
- 可进行基本消息收发与增量同步
因此当前版本更适合作为后续扩展的基础工程,而不是已经覆盖所有高级社区功能的最终产品。