> ## Content Index
> Fetch the complete content index at: https://www.gogao.top/llms.txt
> Use this file to discover other available public pages before exploring further.

# OpenIM源码分析
- URL: https://www.gogao.top/openimyuan-ma-fen-xi/
- Published: 2025-09-08T14:17:30.000Z
- Updated: 2025-09-09T08:41:58.000Z
- Description: 我需要的仅仅是基础的IM聊天功能。不想花那么多钱的情况下，OpenIM是一个不错的选择.
- Author: 爱德姆
- Tags: AI & IT, #Import 2026-09-23 11:35

介绍OpenIM

研究这个框架，源于公司一个项目对于即时通讯的需要，之前涉及到这个需求，都采用商业方案，比如腾讯云提供的IM服务，环信等等，商业的云服务稳定，强大，要价高，但有的时候，我需要的仅仅是基础的IM聊天功能。不想花那么多钱的情况下，开源社区就是我最强大的后盾。OpenIM是由前微信技术专家打造的开源即时通讯解决方案，提供完整组件和一键部署能力，支持私有化部署和数据隐私保护，具备高性能、微服务、集群化特性，适用于企业级即时通讯需求。实际测试下，OpenIM对服务器的资源需求，真的不算大，官方介绍，核心服务仅需要4G内存。

部署结构分析

一、依赖服务安装

OpenIM已经准备好的依赖组件的Docker服务配置，位于项目open-im-server下。

```
$ git clone https://github.com/openimsdk/open-im-server && cd open-im-server
```

| 组件类别 | 核心依赖                       | 运维组件                          | 测试组件                 |
| ---- | -------------------------- | ----------------------------- | -------------------- |
| 组件清单 | mongodbrediskafkaMinIOetcd | prometheusalertmanagergrafana | admin-frontweb-front |
| 是否必选 | 必选                         | 可选                            | 可选                   |

依赖启动

```
$ docker compose up -d // 启动核心组件和测试前端
$ docker compose --profile m up -d // 启动运维组件
```

二、文档补充说明

1. Minio的访问配置：Minio主要用于存储用户对话过程中的文件，而这些请求是直接进minio的，因此需要配置域名，或用户可以访问的IP地址。若是内网，给Minio一个内网IP即可。端口号默认Docker启动Minio使用的端口，映射到了主体的10005，具体查看minio.yml配置确认。
2. Go的代理：golang语言没限制，不过golang依赖库的机制对github有非常强的依赖，大部分的依赖库都在github上，源码运行，需要配置go依赖的代理。

三、核心服务启动

在上面的准备基础完成之后，使用openim的指定的编译工具，mage start就可以直接启动核心服务了，这里可参考官网原文，不赘述。

如果自己的系统需要IM，那么到此为止，便可以基于OpenIM，来进行二次开发了。但如果你想直接上手试一下消息，就需要下面的AppServer演示服务接口。

四、AppServer演示接口服务

核心服务中，有USER的逻辑，但是却没有账号体系，因此上面的web-front和admin-front项目，可以打开，但却没办法登录，这需要另外的实现账号机制的后端的API服务。这个服务即AppServer，需要另外部署。

- 服务获取：

```
$ git clone https://github.com/openimsdk/chat&& cd chat
```

如果您是在本地部署，那么admin-front的默认端口应该是11002，浏览器打开http://localhost:11002即可。

系统初始的管理员账号与密码是：chatAdmin/chatAdmin。

五、核心服务结构

- 主服务：
  - openim-api：对客户端曝露的核心服务，http协议，信息查询，与消息发送请求。
  - openim-msggateway：对客户端曝露的核心服务，ws协议，处理客户端实时消息发送与监听。
  - openim-cmdutil
  - openim-crontask
  - openim-msgtransfer
  - openim-push
- 底层服务
  - openim-rpc-auth
  - openim-rpc-conversation
  - openim-rpc-friend
  - openim-rpc-group
  - openim-rpc-msg
  - openim-rpc-third
  - openim-rpc-user

主服务与底层服务之间的关系如下图：

![](https://www.gogao.top/content/images/2025/09/9524b45ed3604a93ecfec3072e500865.jpg)

六、SDK结构

OpenIM的SDK支持多平台，核心使用golang编写，封装了对API服务请求，与长链接的处理逻辑。而各端的封装主要完成了客户端参数配置，与桥接Golang的部分。

![](https://www.gogao.top/content/images/2025/09/49a8abe15bcd389c3513c071b183e2df.jpg)

用户认证机制

一、概括：

客户端交互的接口都在API服务中以http接口方式实现，而消息收发都在msggateway中以websocket协议实现。以下API定义在OpenIMAPI服务中，OpenIMAPI本身只起到接口转接的作用，具体的逻辑定义在下面的RPC服务，user&auth中。

二、接口

- 用户接口

```
u := NewUserApi(user.NewUserClient(userConn), client, cfg.Discovery.RpcService)  
{      
  userRouterGroup := r.Group("/user")     
  userRouterGroup.POST("/user_register", u.UserRegister)      
  userRouterGroup.POST("/update_user_info", u.UpdateUserInfo)      
  userRouterGroup.POST("/update_user_info_ex", u.UpdateUserInfoEx)      
  userRouterGroup.POST("/set_global_msg_recv_opt", u.SetGlobalRecvMessageOpt)      
  userRouterGroup.POST("/get_users_info", u.GetUsersPublicInfo)      
  userRouterGroup.POST("/get_all_users_uid", u.GetAllUsersID)      
  userRouterGroup.POST("/account_check", u.AccountCheck)      
  userRouterGroup.POST("/get_users", u.GetUsers)      
  userRouterGroup.POST("/get_users_online_status", u.GetUsersOnlineStatus)
  userRouterGroup.POST("/get_users_online_token_detail", u.GetUsersOnlineTokenDetail)      
  userRouterGroup.POST("/subscribe_users_status", u.SubscriberStatus)    
  userRouterGroup.POST("/get_users_status", u.GetUserStatus)      
  userRouterGroup.POST("/get_subscribe_users_status", u.GetSubscribeUsersStatus)      
  userRouterGroup.POST("/process_user_command_add", u.ProcessUserCommandAdd)      
  userRouterGroup.POST("/process_user_command_delete", u.ProcessUserCommandDelete)      
  userRouterGroup.POST("/process_user_command_update", u.ProcessUserCommandUpdate)      
  auserRouterGroup.POST("/process_user_command_get", u.ProcessUserCommandGet)      
  userRouterGroup.POST("/process_user_command_get_all", u.ProcessUserCommandGetAll)      
  userRouterGroup.POST("/add_notification_account", u.AddNotificationAccount)      
  userRouterGroup.POST("/update_notification_account", u.UpdateNotificationAccountInfo)      
  userRouterGroup.POST("/search_notification_account", u.SearchNotificationAccount)  
}
```

- 认证相关

```
a := NewAuthApi(pbAuth.NewAuthClient(authConn))  
authRouterGroup := r.Group("/auth") 
authRouterGroup.POST("/get_admin_token", a.GetAdminToken) 
authRouterGroup.POST("/get_user_token", a.GetUserToken) 
authRouterGroup.POST("/parse_token", a.ParseToken) 
authRouterGroup.POST("/force_logout", a.ForceLogout) 
```

三、认证逻辑

![](https://www.gogao.top/content/images/2025/09/5924e602a8da4be323eb33ee7128d14f.jpg)

四、Token说明

- TokenKey In Redis

```
// 前缀:用户ID:登录平台
UID_PID_TOKEN_STATUS:4834513665:Web
```

- TokenValue说明：{Token:TokenFlag}

 TokenFlag取值如下，也就是说，TokenValue将以JsonMap的形式保存，最里可以看到最多4种情况

  - NormalToken = 0
  - InValidToken = 1
  - KickedToken = 2
  - ExpiredToken = 3

五、AuthDatabase Controller

database controller是openim对数据层的封装，底层可能是对mongodb或是redis的数据服务。

认证服务Auth是openim底层服务，在启动时，会实例化AuthDatabase，Auth服务实现的4四认证相关接口，便是依赖authDatabase实现认证数据的管理。

authDatabase实现的四个方法如下，即操作上面Token的方法：

```
- GetTokensWithoutError(ctx context.Context, userID string, platformID int) (map[string]int, error)
- CreateToken(ctx context.Context, userID string, platformID int) (string, error)  
- BatchSetTokenMapByUidPid(ctx context.Context, tokens []string) error  
- SetTokenMapByUidPid(ctx context.Context, userID string, platformID int, m map[string]int) error
```

消息类型说明MsgGateway提供了一个WebSocket服务，监听客户端的ws链接，并负责消息监听与处理。

一、OpenIM五种系统消息类型

- TextMessage（Ping/Pone Message）
- BinaryMessage（Chat Message)
- CloseMessage（客户端关闭连接）
- PingMessage
- PongMessage

二、BinaryMessage（Req/Resp）

```go
type Req struct {
  ReqIdentifier int32  `json:"reqIdentifier" validate:"required"`      
  Token         string `json:"token"`      
  SendID        string `json:"sendID"        validate:"required"`      
  OperationID   string `json:"operationID"   validate:"required"`      
  MsgIncr       string `json:"msgIncr"       validate:"required"`      
  Data          []byte `json:"data"`  
}
type Resp struct {      
  ReqIdentifier int32  `json:"reqIdentifier"`      
  MsgIncr       string `json:"msgIncr"`      
  OperationID   string `json:"operationID"`      
  ErrCode       int    `json:"errCode"`      
  ErrMsg        string `json:"errMsg"`      
  Data          []byte `json:"data"`  
}
```

三、ReqIdentifier

每一个消息类型，对应底层rpc服务msg都有对应的处理方法。一般用户的消息，则对应着WSSendMsg这个类型。

```
WSGetNewestSeq        = 1001 
WSPullMsgBySeqList    = 1002
WSSendMsg             = 1003  // 一般聊天消息
WSSendSignalMsg       = 1004  
WSPullMsg             = 1005  
WSGetConvMaxReadSeq   = 1006  
WsPullConvLastMessage = 1007  
WSPushMsg             = 2001  
WSKickOnlineMsg       = 2002  
WsLogoutMsg           = 2003  
WsSetBackgroundStatus = 2004  
WsSubUserOnlineStatus = 2005  
WSDataError           = 3001
```

花了两天时间，反复翻了几遍源码，结合以上核心的概念说明，OpenIM的基本结构已经相对清晰，后面有深入的分析再续。