93 changed files with 4292 additions and 579 deletions
@ -0,0 +1,21 @@ |
|||||||
|
MIT License |
||||||
|
|
||||||
|
Copyright (c) 2018 tangmingyou |
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||||
|
of this software and associated documentation files (the "Software"), to deal |
||||||
|
in the Software without restriction, including without limitation the rights |
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||||
|
copies of the Software, and to permit persons to whom the Software is |
||||||
|
furnished to do so, subject to the following conditions: |
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all |
||||||
|
copies or substantial portions of the Software. |
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||||
|
SOFTWARE. |
||||||
@ -1,121 +1,86 @@ |
|||||||
|
## 基本介绍 |
||||||
|
|
||||||
|
`so-im` 是一款简单的可水平扩展的 `IM(即时通讯)`系统。 |
||||||
|
|
||||||
### 开发计划 |
客户端和TCP接入层通过 netty+protobuf 通信。 |
||||||
|
|
||||||
- (05-08~05-11)router 一致性 hash,新增、删除、(备份处理)[滞后] |
后端服务通过 dubbo 服务间调用。 |
||||||
- 数据同步删除后,保留id一段时间,有请求进行重定向/转发 |
|
||||||
- 新增:重算hash,发起数据同步,接收其他节点推送数据及数据更改日志,注册服务,其他节点删除数据 |
|
||||||
- 正常删除节点:重算 hash,数据和更改日志推送给其他节点,取消注册,关闭服务 |
|
||||||
- 宕机:备份服务接收全量同步数据和更改日志,服务探测到主服务不可用,注册到注册中心提供服务 |
## 功能演示 |
||||||
- (05-12~05-12) 备用计划:router 层 id 号段负载均衡 |
|
||||||
- (05-13~05-14) dubbo 服务异步处理 |
好友、群、单聊、群聊、内置命令 |
||||||
- 功能开发: |
|
||||||
- entry-http entry 节点获取功能(05-13~05-13) |
 |
||||||
- (05-13~05-13) 用户注册功能 |
|
||||||
- (05-14~05-14) 好友列表(在线状态:批量uid一致性hash, router查询) |
|
||||||
- 用户查询 |
|
||||||
- 添加好友 |
<video id="video" controls="" preload="none" poster="doc/image/README/soim.jpg"> |
||||||
- 好友在线状态列表 |
<source id="mp4" src="doc/image/README/soim.mp4" type="video/mp4"> |
||||||
- (05-15~05-15) 消息群发(im-router群消息路由,批量uid一致性哈希路由) |
</videos> |
||||||
- 创群: |
|
||||||
- 加群:发送申请,推送申请,推送回复 |
|
||||||
- 删群 |
|
||||||
- 群列表 |
## 消息转发流程 |
||||||
- (05-16~05-16) 聊天记录查询 |
|
||||||
- (05-17~05-18) das 部分接口消息队列异步写 |
 |
||||||
- (05-19~05-20) 集群部署:docker swarm |
|
||||||
- 监控:log4j2完善 + prometheus + grafana + loki + arthas |
|
||||||
- (05-21~05-21) prometheus 服务发现,exporter(服务发现) 开发 |
|
||||||
- (05-22~05-22) 容器监控,主机监控,数据库监控,日志收集 |
## 内置命令 |
||||||
- (05-23~05-24) 应用监控 |
|
||||||
- (Dubbo线程池监控)[https://cloud.tencent.com/developer/article/1800906] |
| 命令 | 选项 | 描述 | |
||||||
- 通讯指标监控,请求量,吞吐量,延时,请求节点分布,链路追踪 |
| ------- | ------------------------------------------------------------ | ---------------------------------------------------- | |
||||||
- 数据库连接池监控 |
| login | -u 账号<br />-p 密码 | 登录并连接tcp接入层 | |
||||||
- (05-25~05-25) 压测:压测开发 |
| send | -u 好友id 单聊消息<br />-g 群id 群消息 | 发送消息 | |
||||||
- (05-26~05-26) client: 控制台完善,grallvm 打包 |
| users | | 在线用户列表 | |
||||||
- 后续: |
| friends | | 我的好友列表 | |
||||||
- 通讯加密,服务链路SSL |
| group | | 查询我的群聊列表 | |
||||||
- websocket 网关 |
| group | create 群聊名称<br />search 群聊名称(右模糊)<br />join 群聊id<br />users | 创建群聊<br />搜索群聊<br />加入群聊<br />群用户列表 | |
||||||
- web 页面开发 |
| search | -u 用户账号(右模糊) | 搜索用户 | |
||||||
- 异/同设备,多地登录 |
| add | -u 用户id | 添加好友 | |
||||||
|
| me | | 我的信息 | |
||||||
|
| exit | | 退出客户端 | |
||||||
### 资料 |
|
||||||
一致性hash算法能否解决数据迁移的问题? |
|
||||||
https://www.zhihu.com/question/521159623 |
|
||||||
|
## TODO LIST |
||||||
dubbo + protobuf 兼容到 2.7.15 |
|
||||||
|
- [x] 好友、基础单聊 |
||||||
### TODO |
- [x] 群搜索、添加、列表、基础群聊 |
||||||
|
- [x] 消息通过MQ持久化到MySQL分表库 |
||||||
- router -> entry 负载均衡 |
- [x] 启动路由层新节点根据一致性hash迁移其他节点内存数据 |
||||||
- router 新增节点顺时针相邻节点数据一致性哈希迁移 |
- [x] 接入层负载均衡 |
||||||
- router 冗余节点存储数据不提供服务 |
- [x] 分布式分段id生成服务 |
||||||
- dubbo 服务异步处理提升吞吐量 |
- [ ] 聊天记录查询 |
||||||
- das 消息队列异步写 |
- [ ] 优化命令行客户端打印输出 |
||||||
- entry 监控,http 查询 entry 地址返回接口 |
- [ ] 群聊,单聊 消息已读确认 |
||||||
- 功能开发: |
- [ ] 未读离线消息推送 |
||||||
- 消息群发(im-router 群消息路由,批量uid一致性哈希路由) |
- [ ] 客户端接入层消息加密 |
||||||
- 好友列表(在线状态:批量uid一致性hash, router查询) |
- [ ] dubbo service SSL 加密 |
||||||
- 聊天记录查询 |
- [ ] 路由层状态服务冗余节点备份,自动切换 |
||||||
- 异/同设备,多地登录 |
|
||||||
- 集群部署, docker swarm, k8s, jenkens |
|
||||||
- 服务监控 |
|
||||||
- websocket 网关 |
|
||||||
- 考虑 dubbo 使用 grpc service |
|
||||||
|
## 启动步骤 |
||||||
|
|
||||||
模块列表 |
### 创建数据库 |
||||||
- 接入层 entry |
|
||||||
- 逻辑层 logic |
 |
||||||
- 内存存储层 router |
|
||||||
- 固化存储层 das |
|
||||||
|
|
||||||
功能组件: |
### 中间件配置 |
||||||
1.0 |
|
||||||
|
配置 nacos、mysql、rabbitmq、redis 服务地址 |
||||||
- IOC: guice |
|
||||||
- 通信层: netty |
 |
||||||
- 序列化: protobuf |
|
||||||
- 内存存储: |
|
||||||
- Caffeine |
|
||||||
- Memcache |
### 启动如下服务 |
||||||
- 分布式缓存:redis |
|
||||||
- 注册中心:etcd、直连 |
 |
||||||
- 处理队列:disruptor |
|
||||||
- 持久化: |
|
||||||
- mysql 存储全量历史消息 |
|
||||||
- mongodb 存储直接拉取的未读消息 |
|
||||||
- 日志:log4j2 |
|
||||||
- 监控:prometheus、grafana |
|
||||||
|
|
||||||
- ID生成器 |
|
||||||
|
|
||||||
2.0 |
|
||||||
|
|
||||||
- quarkus |
|
||||||
|
|
||||||
集群负载均衡: |
|
||||||
子网1,子网2,公网 |
|
||||||
子网1和2不相通 |
|
||||||
|
|
||||||
dubbo native image |
|
||||||
https://dubbo.apache.org/zh/docs/references/graalvm/support-graalvm/ |
|
||||||
|
|
||||||
|
|
||||||
entry <--> client 通信 |
|
||||||
- serviceId --> paramClass --> serviceHandler |
|
||||||
|
|
||||||
entry <--> logic dubbo service |
|
||||||
client jconsle cmd |
|
||||||
|
|
||||||
router <--> cache |
|
||||||
das <--> db |
|
||||||
router <--> das |
|
||||||
|
|
||||||
|
|
||||||
das shardingjdbc |
|
||||||
table struct, sharding roles |
|
||||||
logic biz |
|
||||||
|
|
||||||
请求响应消息队列异步处理,减少线程 cpu 占用, dubbo async |
|
||||||
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.0 MiB |
|
After Width: | Height: | Size: 286 KiB |
Binary file not shown.
@ -0,0 +1,782 @@ |
|||||||
|
/* |
||||||
|
Navicat Premium Data Transfer |
||||||
|
|
||||||
|
Source Server : mysql |
||||||
|
Source Server Type : MySQL |
||||||
|
Source Server Version : 80022 |
||||||
|
Source Host : 127.0.0.1:3306 |
||||||
|
Source Schema : soim_db |
||||||
|
|
||||||
|
Target Server Type : MySQL |
||||||
|
Target Server Version : 80022 |
||||||
|
File Encoding : 65001 |
||||||
|
|
||||||
|
Date: 12/06/2022 15:11:15 |
||||||
|
*/ |
||||||
|
|
||||||
|
SET NAMES utf8mb4; |
||||||
|
SET FOREIGN_KEY_CHECKS = 0; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_friend_0 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_friend_0`; |
||||||
|
CREATE TABLE `im_friend_0` ( |
||||||
|
`id` bigint(0) NOT NULL, |
||||||
|
`relation_id` bigint(0) NOT NULL COMMENT '好友关系id(消息存储路由分片)', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`fid` bigint(0) NOT NULL COMMENT '好友id', |
||||||
|
`status` tinyint(0) NOT NULL COMMENT '状态:0删除,1正常,2临时好友(群单聊)', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NOT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友关系表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_friend_1 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_friend_1`; |
||||||
|
CREATE TABLE `im_friend_1` ( |
||||||
|
`id` bigint(0) NOT NULL, |
||||||
|
`relation_id` bigint(0) NOT NULL COMMENT '好友关系id(消息存储路由分片)', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`fid` bigint(0) NOT NULL COMMENT '好友id', |
||||||
|
`status` tinyint(0) NOT NULL COMMENT '状态:0删除,1正常,2临时好友(群单聊)', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NOT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友关系表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_friend_2 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_friend_2`; |
||||||
|
CREATE TABLE `im_friend_2` ( |
||||||
|
`id` bigint(0) NOT NULL, |
||||||
|
`relation_id` bigint(0) NOT NULL COMMENT '好友关系id(消息存储路由分片)', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`fid` bigint(0) NOT NULL COMMENT '好友id', |
||||||
|
`status` tinyint(0) NOT NULL COMMENT '状态:0删除,1正常,2临时好友(群单聊)', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NOT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友关系表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_friend_3 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_friend_3`; |
||||||
|
CREATE TABLE `im_friend_3` ( |
||||||
|
`id` bigint(0) NOT NULL, |
||||||
|
`relation_id` bigint(0) NOT NULL COMMENT '好友关系id(消息存储路由分片)', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`fid` bigint(0) NOT NULL COMMENT '好友id', |
||||||
|
`status` tinyint(0) NOT NULL COMMENT '状态:0删除,1正常,2临时好友(群单聊)', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NOT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友关系表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_friend_4 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_friend_4`; |
||||||
|
CREATE TABLE `im_friend_4` ( |
||||||
|
`id` bigint(0) NOT NULL, |
||||||
|
`relation_id` bigint(0) NOT NULL COMMENT '好友关系id(消息存储路由分片)', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`fid` bigint(0) NOT NULL COMMENT '好友id', |
||||||
|
`status` tinyint(0) NOT NULL COMMENT '状态:0删除,1正常,2临时好友(群单聊)', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NOT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友关系表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_friend_5 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_friend_5`; |
||||||
|
CREATE TABLE `im_friend_5` ( |
||||||
|
`id` bigint(0) NOT NULL, |
||||||
|
`relation_id` bigint(0) NOT NULL COMMENT '好友关系id(消息存储路由分片)', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`fid` bigint(0) NOT NULL COMMENT '好友id', |
||||||
|
`status` tinyint(0) NOT NULL COMMENT '状态:0删除,1正常,2临时好友(群单聊)', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NOT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友关系表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_friend_6 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_friend_6`; |
||||||
|
CREATE TABLE `im_friend_6` ( |
||||||
|
`id` bigint(0) NOT NULL, |
||||||
|
`relation_id` bigint(0) NOT NULL COMMENT '好友关系id(消息存储路由分片)', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`fid` bigint(0) NOT NULL COMMENT '好友id', |
||||||
|
`status` tinyint(0) NOT NULL COMMENT '状态:0删除,1正常,2临时好友(群单聊)', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NOT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友关系表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_friend_7 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_friend_7`; |
||||||
|
CREATE TABLE `im_friend_7` ( |
||||||
|
`id` bigint(0) NOT NULL, |
||||||
|
`relation_id` bigint(0) NOT NULL COMMENT '好友关系id(消息存储路由分片)', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`fid` bigint(0) NOT NULL COMMENT '好友id', |
||||||
|
`status` tinyint(0) NOT NULL COMMENT '状态:0删除,1正常,2临时好友(群单聊)', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NOT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '好友关系表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_0 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_0`; |
||||||
|
CREATE TABLE `im_group_0` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`master_uid` bigint(0) NOT NULL COMMENT '群主id', |
||||||
|
`status` int(0) NOT NULL COMMENT '状态:0删除,1.正常,3禁用,4.解散', |
||||||
|
`group_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '群聊名称', |
||||||
|
`user_limit` int(0) NOT NULL COMMENT '群聊人数限制', |
||||||
|
`user_num` int(0) NOT NULL COMMENT '当前群聊人数', |
||||||
|
`create_time` datetime(0) NOT NULL COMMENT '创建时间', |
||||||
|
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_1 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_1`; |
||||||
|
CREATE TABLE `im_group_1` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`master_uid` bigint(0) NOT NULL COMMENT '群主id', |
||||||
|
`status` int(0) NOT NULL COMMENT '状态:0删除,1.正常,3禁用,4.解散', |
||||||
|
`group_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '群聊名称', |
||||||
|
`user_limit` int(0) NOT NULL COMMENT '群聊人数限制', |
||||||
|
`user_num` int(0) NOT NULL COMMENT '当前群聊人数', |
||||||
|
`create_time` datetime(0) NOT NULL COMMENT '创建时间', |
||||||
|
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_2 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_2`; |
||||||
|
CREATE TABLE `im_group_2` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`master_uid` bigint(0) NOT NULL COMMENT '群主id', |
||||||
|
`status` int(0) NOT NULL COMMENT '状态:0删除,1.正常,3禁用,4.解散', |
||||||
|
`group_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '群聊名称', |
||||||
|
`user_limit` int(0) NOT NULL COMMENT '群聊人数限制', |
||||||
|
`user_num` int(0) NOT NULL COMMENT '当前群聊人数', |
||||||
|
`create_time` datetime(0) NOT NULL COMMENT '创建时间', |
||||||
|
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_3 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_3`; |
||||||
|
CREATE TABLE `im_group_3` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`master_uid` bigint(0) NOT NULL COMMENT '群主id', |
||||||
|
`status` int(0) NOT NULL COMMENT '状态:0删除,1.正常,3禁用,4.解散', |
||||||
|
`group_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '群聊名称', |
||||||
|
`user_limit` int(0) NOT NULL COMMENT '群聊人数限制', |
||||||
|
`user_num` int(0) NOT NULL COMMENT '当前群聊人数', |
||||||
|
`create_time` datetime(0) NOT NULL COMMENT '创建时间', |
||||||
|
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_0 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_0`; |
||||||
|
CREATE TABLE `im_group_message_0` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_1 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_1`; |
||||||
|
CREATE TABLE `im_group_message_1` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_2 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_2`; |
||||||
|
CREATE TABLE `im_group_message_2` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_3 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_3`; |
||||||
|
CREATE TABLE `im_group_message_3` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_4 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_4`; |
||||||
|
CREATE TABLE `im_group_message_4` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_5 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_5`; |
||||||
|
CREATE TABLE `im_group_message_5` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_6 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_6`; |
||||||
|
CREATE TABLE `im_group_message_6` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_7 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_7`; |
||||||
|
CREATE TABLE `im_group_message_7` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_8 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_8`; |
||||||
|
CREATE TABLE `im_group_message_8` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_9 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_9`; |
||||||
|
CREATE TABLE `im_group_message_9` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_10 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_10`; |
||||||
|
CREATE TABLE `im_group_message_10` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_11 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_11`; |
||||||
|
CREATE TABLE `im_group_message_11` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_12 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_12`; |
||||||
|
CREATE TABLE `im_group_message_12` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_13 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_13`; |
||||||
|
CREATE TABLE `im_group_message_13` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_14 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_14`; |
||||||
|
CREATE TABLE `im_group_message_14` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_message_15 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_message_15`; |
||||||
|
CREATE TABLE `im_group_message_15` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_user_0 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_user_0`; |
||||||
|
CREATE TABLE `im_group_user_0` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NULL DEFAULT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`last_active` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊用户列表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_user_1 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_user_1`; |
||||||
|
CREATE TABLE `im_group_user_1` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NULL DEFAULT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`last_active` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊用户列表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_user_2 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_user_2`; |
||||||
|
CREATE TABLE `im_group_user_2` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NULL DEFAULT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`last_active` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊用户列表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_user_3 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_user_3`; |
||||||
|
CREATE TABLE `im_group_user_3` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NULL DEFAULT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`last_active` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊用户列表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_user_4 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_user_4`; |
||||||
|
CREATE TABLE `im_group_user_4` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NULL DEFAULT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`last_active` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊用户列表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_user_5 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_user_5`; |
||||||
|
CREATE TABLE `im_group_user_5` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NULL DEFAULT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`last_active` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊用户列表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_user_6 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_user_6`; |
||||||
|
CREATE TABLE `im_group_user_6` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NULL DEFAULT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`last_active` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊用户列表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_group_user_7 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_group_user_7`; |
||||||
|
CREATE TABLE `im_group_user_7` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`group_id` bigint(0) NOT NULL COMMENT '群聊id', |
||||||
|
`uid` bigint(0) NOT NULL COMMENT '用户id', |
||||||
|
`unread_num` int(0) NOT NULL COMMENT '群未读消息数量', |
||||||
|
`unread_offset_id` bigint(0) NULL DEFAULT NULL COMMENT '群未读消息id偏移量(大于等于该id的都未读)', |
||||||
|
`last_active` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '群聊用户列表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_message_0 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_message_0`; |
||||||
|
CREATE TABLE `im_message_0` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`relation_id` bigint(0) NULL DEFAULT NULL, |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送人id', |
||||||
|
`receiver` bigint(0) NOT NULL COMMENT '接受者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_message_1 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_message_1`; |
||||||
|
CREATE TABLE `im_message_1` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`relation_id` bigint(0) NULL DEFAULT NULL, |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送人id', |
||||||
|
`receiver` bigint(0) NOT NULL COMMENT '接受者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_message_2 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_message_2`; |
||||||
|
CREATE TABLE `im_message_2` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`relation_id` bigint(0) NULL DEFAULT NULL, |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送人id', |
||||||
|
`receiver` bigint(0) NOT NULL COMMENT '接受者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_message_3 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_message_3`; |
||||||
|
CREATE TABLE `im_message_3` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`relation_id` bigint(0) NULL DEFAULT NULL, |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送人id', |
||||||
|
`receiver` bigint(0) NOT NULL COMMENT '接受者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_message_4 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_message_4`; |
||||||
|
CREATE TABLE `im_message_4` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`relation_id` bigint(0) NULL DEFAULT NULL, |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送人id', |
||||||
|
`receiver` bigint(0) NOT NULL COMMENT '接受者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_message_5 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_message_5`; |
||||||
|
CREATE TABLE `im_message_5` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`relation_id` bigint(0) NULL DEFAULT NULL, |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送人id', |
||||||
|
`receiver` bigint(0) NOT NULL COMMENT '接受者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_message_6 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_message_6`; |
||||||
|
CREATE TABLE `im_message_6` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`relation_id` bigint(0) NULL DEFAULT NULL, |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送人id', |
||||||
|
`receiver` bigint(0) NOT NULL COMMENT '接受者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_message_7 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_message_7`; |
||||||
|
CREATE TABLE `im_message_7` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`relation_id` bigint(0) NULL DEFAULT NULL, |
||||||
|
`sender` bigint(0) NOT NULL COMMENT '发送人id', |
||||||
|
`receiver` bigint(0) NOT NULL COMMENT '接受者id', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`content` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '消息内容', |
||||||
|
PRIMARY KEY (`id`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '聊天消息' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_segment_id |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_segment_id`; |
||||||
|
CREATE TABLE `im_segment_id` ( |
||||||
|
`biz_tag` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务标签', |
||||||
|
`current_id` bigint(0) NOT NULL COMMENT '当前id值', |
||||||
|
`init_step` bigint(0) NOT NULL COMMENT '业务标签初始步长', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', |
||||||
|
`version` bigint(0) NOT NULL COMMENT '版本号', |
||||||
|
PRIMARY KEY (`biz_tag`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '分段id' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_segment_id |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_segment_id`; |
||||||
|
CREATE TABLE `im_segment_id` ( |
||||||
|
`biz_tag` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '业务标签', |
||||||
|
`current_id` bigint(0) NOT NULL COMMENT '当前id值', |
||||||
|
`init_step` bigint(0) NOT NULL COMMENT '业务标签初始步长', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', |
||||||
|
`version` bigint(0) NOT NULL COMMENT '版本号', |
||||||
|
PRIMARY KEY (`biz_tag`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '分段id' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Records of im_segment_id |
||||||
|
-- ---------------------------- |
||||||
|
INSERT INTO `im_segment_id` VALUES ('im_friend', 12002, 1000, '2022-06-03 19:45:15', '2022-06-12 13:08:59', 2); |
||||||
|
INSERT INTO `im_segment_id` VALUES ('im_friend_relation_id', 12002, 1000, '2022-06-03 19:45:15', '2022-06-12 13:08:59', 2); |
||||||
|
INSERT INTO `im_segment_id` VALUES ('im_group', 12002, 1000, '2022-06-05 09:52:41', '2022-06-07 17:39:39', 2); |
||||||
|
INSERT INTO `im_segment_id` VALUES ('im_group_message', 16006, 1000, '2022-06-07 16:45:41', '2022-06-12 13:09:48', 6); |
||||||
|
INSERT INTO `im_segment_id` VALUES ('im_group_user', 13003, 1000, '2022-06-05 09:52:42', '2022-06-07 17:39:39', 3); |
||||||
|
INSERT INTO `im_segment_id` VALUES ('im_message', 35025, 1000, '2022-06-03 19:55:01', '2022-06-12 13:09:10', 25); |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_user_0 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_user_0`; |
||||||
|
CREATE TABLE `im_user_0` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`status` int(0) NOT NULL COMMENT '状态:0删除,1.正常,2.禁用', |
||||||
|
`account` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '登录账号', |
||||||
|
`nickname` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户昵称', |
||||||
|
`password` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', |
||||||
|
`phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间', |
||||||
|
`last_active_time` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE, |
||||||
|
INDEX `idx_account_status_0`(`account`, `status`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Records of im_user_0 |
||||||
|
-- ---------------------------- |
||||||
|
INSERT INTO `im_user_0` VALUES (728220, 1, 'zeus', '宙斯', '123456', '17882451901', '2022-04-14 10:50:55', NULL, NULL); |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_user_1 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_user_1`; |
||||||
|
CREATE TABLE `im_user_1` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`status` int(0) NOT NULL COMMENT '状态:0删除,1.正常,2.禁用', |
||||||
|
`account` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '登录账号', |
||||||
|
`nickname` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户昵称', |
||||||
|
`password` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', |
||||||
|
`phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间', |
||||||
|
`last_active_time` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE, |
||||||
|
INDEX `idx_account_status`(`account`, `status`) USING BTREE, |
||||||
|
INDEX `idx_account_status_1`(`account`, `status`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Records of im_user_1 |
||||||
|
-- ---------------------------- |
||||||
|
INSERT INTO `im_user_1` VALUES (727717, 1, 'prometheus', '普罗米修斯', '123456', '17882451908', '2022-04-14 10:46:23', NULL, NULL); |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_user_2 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_user_2`; |
||||||
|
CREATE TABLE `im_user_2` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`status` int(0) NOT NULL COMMENT '状态:0删除,1.正常,2.禁用', |
||||||
|
`account` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '登录账号', |
||||||
|
`nickname` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户昵称', |
||||||
|
`password` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', |
||||||
|
`phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间', |
||||||
|
`last_active_time` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE, |
||||||
|
INDEX `idx_account_status`(`account`, `status`) USING BTREE, |
||||||
|
INDEX `idx_account_status_2`(`account`, `status`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Records of im_user_2 |
||||||
|
-- ---------------------------- |
||||||
|
INSERT INTO `im_user_2` VALUES (729726, 1, 'poros', '波罗斯', '123456', '17882451902', '2022-04-14 10:53:39', NULL, NULL); |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Table structure for im_user_3 |
||||||
|
-- ---------------------------- |
||||||
|
DROP TABLE IF EXISTS `im_user_3`; |
||||||
|
CREATE TABLE `im_user_3` ( |
||||||
|
`id` bigint(0) NOT NULL COMMENT 'id', |
||||||
|
`status` int(0) NOT NULL COMMENT '状态:0删除,1.正常,2.禁用', |
||||||
|
`account` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '登录账号', |
||||||
|
`nickname` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户昵称', |
||||||
|
`password` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '密码', |
||||||
|
`phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '手机号', |
||||||
|
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', |
||||||
|
`last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间', |
||||||
|
`last_active_time` datetime(0) NULL DEFAULT NULL COMMENT '最后活跃时间', |
||||||
|
PRIMARY KEY (`id`) USING BTREE, |
||||||
|
INDEX `idx_account_status_3`(`account`, `status`) USING BTREE |
||||||
|
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '用户表' ROW_FORMAT = Dynamic; |
||||||
|
|
||||||
|
-- ---------------------------- |
||||||
|
-- Records of im_user_3 |
||||||
|
-- ---------------------------- |
||||||
|
SET FOREIGN_KEY_CHECKS = 1; |
||||||
@ -0,0 +1,40 @@ |
|||||||
|
package net.sopod.soim.das.user.cache; |
||||||
|
|
||||||
|
import com.google.common.collect.HashBasedTable; |
||||||
|
import com.google.common.collect.Table; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.util.function.BiFunction; |
||||||
|
|
||||||
|
/** |
||||||
|
* FriendRelationCache |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-12 09:38 |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
public class FriendRelationCache { |
||||||
|
|
||||||
|
private final Table<Long, Long, Long> friendRelationTable = HashBasedTable.create();; |
||||||
|
|
||||||
|
public Long computeIfAbsent(Long uid, Long fid, BiFunction<Long, Long, Long> mappingFunction) { |
||||||
|
Long relationId; |
||||||
|
if (null != (relationId = friendRelationTable.get(uid, fid))) { |
||||||
|
return relationId; |
||||||
|
} |
||||||
|
// TODO lockFunc(uid, fid)
|
||||||
|
synchronized (FriendRelationCache.class) { |
||||||
|
if (null != (relationId = friendRelationTable.get(uid, fid))) { |
||||||
|
return relationId; |
||||||
|
} |
||||||
|
relationId = mappingFunction.apply(uid, fid); |
||||||
|
friendRelationTable.put(uid, fid, relationId); |
||||||
|
} |
||||||
|
return relationId; |
||||||
|
} |
||||||
|
|
||||||
|
public Long remove(Long uid, Long fid) { |
||||||
|
return friendRelationTable.remove(uid, fid); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,176 @@ |
|||||||
|
package net.sopod.soim.entry.http.client; |
||||||
|
|
||||||
|
import com.google.protobuf.MessageLite; |
||||||
|
import io.netty.bootstrap.Bootstrap; |
||||||
|
import io.netty.channel.Channel; |
||||||
|
import io.netty.channel.ChannelInitializer; |
||||||
|
import io.netty.channel.ChannelOption; |
||||||
|
import io.netty.channel.nio.NioEventLoopGroup; |
||||||
|
import io.netty.channel.socket.SocketChannel; |
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel; |
||||||
|
import io.netty.util.AttributeKey; |
||||||
|
import net.sopod.soim.common.constant.AppConstant; |
||||||
|
import net.sopod.soim.common.dubbo.exception.SoimException; |
||||||
|
import net.sopod.soim.common.util.netty.Varint32FrameCodec; |
||||||
|
import net.sopod.soim.data.msg.monitor.EntryMonitor; |
||||||
|
import net.sopod.soim.data.serialize.ImMessage; |
||||||
|
import net.sopod.soim.data.serialize.ImMessageCodec; |
||||||
|
import net.sopod.soim.entry.http.service.ImMessageReqHolder; |
||||||
|
import org.apache.commons.lang3.tuple.Pair; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import java.util.Objects; |
||||||
|
import java.util.concurrent.CompletableFuture; |
||||||
|
|
||||||
|
/** |
||||||
|
* EntryClient |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-11 13:17 |
||||||
|
*/ |
||||||
|
public class EntryClient { |
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(EntryClient.class); |
||||||
|
|
||||||
|
public static AttributeKey<EntryClient> IM_ENTRY_CLIENT_KEY = AttributeKey.valueOf(EntryClient.class, "IM_ENTRY_CLIENT_KEY"); |
||||||
|
|
||||||
|
private final String entryAddress; |
||||||
|
|
||||||
|
private final ImMessageReqHolder imMessageReqHolder; |
||||||
|
|
||||||
|
private Channel clientChannel; |
||||||
|
|
||||||
|
private NioEventLoopGroup eventLoopGroup; |
||||||
|
|
||||||
|
private int entryConnections; |
||||||
|
|
||||||
|
private long updateTime; |
||||||
|
|
||||||
|
public EntryClient(String entryAddress) { |
||||||
|
this.entryAddress = entryAddress; |
||||||
|
this.imMessageReqHolder = new ImMessageReqHolder(); |
||||||
|
} |
||||||
|
|
||||||
|
public boolean connect() { |
||||||
|
this.eventLoopGroup = new NioEventLoopGroup(2); |
||||||
|
Bootstrap b = new Bootstrap() |
||||||
|
.group(this.eventLoopGroup) |
||||||
|
.channel(NioSocketChannel.class) |
||||||
|
.handler(new ChannelInitializer<SocketChannel>() { |
||||||
|
@Override |
||||||
|
protected void initChannel(SocketChannel ch) throws Exception { |
||||||
|
ch.pipeline() |
||||||
|
.addLast(new Varint32FrameCodec()) |
||||||
|
.addLast(new ImMessageCodec.ImMessage2ByteEncoder()) |
||||||
|
.addLast(new ImMessageInboundHandler()); |
||||||
|
} |
||||||
|
}) |
||||||
|
.option(ChannelOption.TCP_NODELAY, true); |
||||||
|
String[] hostPort = this.entryAddress.split(":"); |
||||||
|
try { |
||||||
|
this.clientChannel = b.connect(hostPort[0], Integer.parseInt(hostPort[1])).await().channel(); |
||||||
|
} catch (InterruptedException e) { |
||||||
|
logger.error("im-entry 连接失败: ", e); |
||||||
|
return false; |
||||||
|
} |
||||||
|
// 设置 MessageHolder 到 channel
|
||||||
|
this.clientChannel.attr(ImMessageReqHolder.IM_MESSAGE_HOLDER_KEY).set(this.imMessageReqHolder); |
||||||
|
// 设置 client 到 channel
|
||||||
|
this.clientChannel.attr(EntryClient.IM_ENTRY_CLIENT_KEY).set(this); |
||||||
|
EntryMonitor.ReqMonitorAuth req = EntryMonitor.ReqMonitorAuth.newBuilder() |
||||||
|
.setSecurity(AppConstant.IM_ENTRY_MONITOR_SECURITY) |
||||||
|
.build(); |
||||||
|
CompletableFuture<?> future = this.send0(req); |
||||||
|
EntryMonitor.ResMonitorAuth res = (EntryMonitor.ResMonitorAuth) future.join(); |
||||||
|
if (!res.getSuccess()) { |
||||||
|
logger.error("{} 认证失败", this.entryAddress); |
||||||
|
// 关闭连接
|
||||||
|
this.close(); |
||||||
|
return false; |
||||||
|
} |
||||||
|
logger.info("认证成功: {}", this.entryAddress); |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
private CompletableFuture<?> send0(MessageLite message) { |
||||||
|
if (this.clientChannel == null |
||||||
|
|| !this.clientChannel.isActive()) { |
||||||
|
// TODO 尝试重连
|
||||||
|
throw new SoimException("连接已关闭"); |
||||||
|
} |
||||||
|
// 构建 ImMessage
|
||||||
|
ImMessage imMessage = ImMessageCodec.encodeImProto(message); |
||||||
|
// serialNo, Future
|
||||||
|
Pair<Integer, CompletableFuture<Object>> futurePair = imMessageReqHolder.nextSerialNo(); |
||||||
|
imMessage.setSerialNo(futurePair.getLeft()); |
||||||
|
try { |
||||||
|
Throwable cause = this.clientChannel.writeAndFlush(imMessage).await().cause(); |
||||||
|
if (cause != null) { |
||||||
|
throw new SoimException(cause); |
||||||
|
} |
||||||
|
} catch (InterruptedException e) { |
||||||
|
throw new SoimException("发送消息失败", e); |
||||||
|
} |
||||||
|
return futurePair.getRight(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 发送消息 |
||||||
|
*/ |
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
public <T> CompletableFuture<T> send(MessageLite message) { |
||||||
|
return (CompletableFuture<T>) send0(message); |
||||||
|
} |
||||||
|
|
||||||
|
public String getEntryAddress() { |
||||||
|
return entryAddress; |
||||||
|
} |
||||||
|
|
||||||
|
public void updateEntryStatus(int connections, long time) { |
||||||
|
// logger.info("{} entry status: conns={}", this.entryAddress, connections);
|
||||||
|
this.entryConnections = connections; |
||||||
|
this.updateTime = time; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 关闭 monitor client 连接 |
||||||
|
*/ |
||||||
|
public void close() { |
||||||
|
if (this.clientChannel != null) { |
||||||
|
this.clientChannel.close(); |
||||||
|
this.clientChannel.attr(ImMessageReqHolder.IM_MESSAGE_HOLDER_KEY).set(null); |
||||||
|
this.clientChannel.attr(EntryClient.IM_ENTRY_CLIENT_KEY).set(null); |
||||||
|
logger.info("entry monitor client {} closed.", this.entryAddress); |
||||||
|
} |
||||||
|
if (this.eventLoopGroup != null) { |
||||||
|
this.eventLoopGroup.shutdownGracefully(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public int getEntryConnections() { |
||||||
|
return entryConnections; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean equals(Object o) { |
||||||
|
if (this == o) return true; |
||||||
|
if (o == null || getClass() != o.getClass()) return false; |
||||||
|
EntryClient that = (EntryClient) o; |
||||||
|
return Objects.equals(entryAddress, that.entryAddress); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int hashCode() { |
||||||
|
return Objects.hash(entryAddress); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String toString() { |
||||||
|
return "EntryClient{" + |
||||||
|
"entryAddress='" + entryAddress + '\'' + |
||||||
|
", entryConnections=" + entryConnections + |
||||||
|
", updateTime=" + updateTime + |
||||||
|
'}'; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,48 @@ |
|||||||
|
package net.sopod.soim.entry.http.client; |
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf; |
||||||
|
import io.netty.channel.ChannelHandlerContext; |
||||||
|
import io.netty.channel.SimpleChannelInboundHandler; |
||||||
|
import net.sopod.soim.data.serialize.ImMessage; |
||||||
|
import net.sopod.soim.data.serialize.ImMessageCodec; |
||||||
|
import net.sopod.soim.entry.http.service.ImMessageReqHolder; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
/** |
||||||
|
* ImMessageInboundHandler |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-11 15:12 |
||||||
|
*/ |
||||||
|
public class ImMessageInboundHandler extends SimpleChannelInboundHandler<ByteBuf> { |
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ImMessageInboundHandler.class); |
||||||
|
|
||||||
|
@Override |
||||||
|
public void channelActive(ChannelHandlerContext ctx) throws Exception { |
||||||
|
super.channelActive(ctx); |
||||||
|
logger.info("channel active..."); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception { |
||||||
|
EntryClient entryClient = ctx.channel().attr(EntryClient.IM_ENTRY_CLIENT_KEY).get(); |
||||||
|
if (entryClient != null) { |
||||||
|
entryClient.close(); |
||||||
|
} |
||||||
|
super.channelInactive(ctx); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception { |
||||||
|
ImMessage imMessage = ImMessageCodec.decodeImMessage(byteBuf); |
||||||
|
// 请求序列号,complete 对应 CompletableFuture
|
||||||
|
int serialNo = imMessage.getSerialNo(); |
||||||
|
|
||||||
|
ImMessageReqHolder imMessageReqHolder = ctx.channel().attr(ImMessageReqHolder.IM_MESSAGE_HOLDER_KEY).get(); |
||||||
|
imMessageReqHolder.complete(serialNo, imMessage.getDecodeBody()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,65 +0,0 @@ |
|||||||
package net.sopod.soim.entry.http.config; |
|
||||||
|
|
||||||
import com.alibaba.nacos.api.NacosFactory; |
|
||||||
import com.alibaba.nacos.api.exception.NacosException; |
|
||||||
import com.alibaba.nacos.api.naming.NamingService; |
|
||||||
import com.alibaba.nacos.api.naming.listener.Event; |
|
||||||
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
|
||||||
import com.alibaba.nacos.api.naming.pojo.Instance; |
|
||||||
import net.sopod.soim.common.constant.AppConstant; |
|
||||||
import org.apache.dubbo.common.URL; |
|
||||||
import org.slf4j.Logger; |
|
||||||
import org.slf4j.LoggerFactory; |
|
||||||
import org.springframework.beans.factory.annotation.Value; |
|
||||||
import org.springframework.boot.context.event.ApplicationReadyEvent; |
|
||||||
import org.springframework.context.ApplicationListener; |
|
||||||
import org.springframework.context.annotation.Configuration; |
|
||||||
import org.springframework.core.Ordered; |
|
||||||
|
|
||||||
import java.util.List; |
|
||||||
import java.util.Properties; |
|
||||||
|
|
||||||
/** |
|
||||||
* ApplicationOnReady |
|
||||||
* |
|
||||||
* @author tmy |
|
||||||
* @date 2022-06-09 11:16 |
|
||||||
*/ |
|
||||||
@Configuration |
|
||||||
public class ApplicationOnReady implements ApplicationListener<ApplicationReadyEvent>, Ordered { |
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ApplicationOnReady.class); |
|
||||||
|
|
||||||
private final String serverAddress; |
|
||||||
|
|
||||||
public ApplicationOnReady(@Value("${dubbo.registry.address}") String serverAddress) { |
|
||||||
this.serverAddress = URL.valueOf(serverAddress).getAddress(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void onApplicationEvent(ApplicationReadyEvent readyEvent) { |
|
||||||
// NamingServer 获取 im-entry 实例,连接上,
|
|
||||||
Properties properties = new Properties(); |
|
||||||
properties.put("serverAddr", serverAddress); |
|
||||||
|
|
||||||
NamingService namingService = null; |
|
||||||
try { |
|
||||||
namingService = NacosFactory.createNamingService(properties); |
|
||||||
List<Instance> allInstances = namingService.getAllInstances(AppConstant.APP_IM_ENTRY_NAME); |
|
||||||
logger.info("im-entry instance...: {}", allInstances); |
|
||||||
namingService.subscribe(AppConstant.APP_IM_ENTRY_NAME, (Event event) -> { |
|
||||||
NamingEvent ne = (NamingEvent) event; |
|
||||||
logger.info("namingEvent: {}", ne); |
|
||||||
}); |
|
||||||
|
|
||||||
} catch (NacosException e) { |
|
||||||
e.printStackTrace(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public int getOrder() { |
|
||||||
return Ordered.HIGHEST_PRECEDENCE; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,175 @@ |
|||||||
|
package net.sopod.soim.entry.http.config; |
||||||
|
|
||||||
|
import com.alibaba.nacos.api.NacosFactory; |
||||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||||
|
import com.alibaba.nacos.api.naming.pojo.Instance; |
||||||
|
import net.sopod.soim.common.constant.AppConstant; |
||||||
|
import net.sopod.soim.common.dubbo.exception.SoimException; |
||||||
|
import net.sopod.soim.common.util.Collects; |
||||||
|
import net.sopod.soim.common.util.netty.FastThreadLocalThreadFactory; |
||||||
|
import net.sopod.soim.data.msg.monitor.EntryMonitor; |
||||||
|
import net.sopod.soim.entry.http.client.EntryClient; |
||||||
|
import org.apache.dubbo.common.URL; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
import org.springframework.beans.factory.annotation.Value; |
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent; |
||||||
|
import org.springframework.context.ApplicationListener; |
||||||
|
import org.springframework.core.Ordered; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import java.util.*; |
||||||
|
import java.util.concurrent.*; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* ApplicationOnReady |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-09 11:16 |
||||||
|
*/ |
||||||
|
@Component |
||||||
|
// @Configuration
|
||||||
|
public class ImEntryMonitor implements ApplicationListener<ApplicationReadyEvent>, Ordered { |
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ImEntryMonitor.class); |
||||||
|
|
||||||
|
private final String nacosServerAddress; |
||||||
|
|
||||||
|
private NamingService namingService; |
||||||
|
|
||||||
|
private final Map<String, EntryClient> entryClientMap = new ConcurrentHashMap<>(8); |
||||||
|
|
||||||
|
private final ScheduledExecutorService scheduledExecutorService; |
||||||
|
|
||||||
|
public ImEntryMonitor(@Value("${dubbo.registry.address}") String nacosServerAddress) { |
||||||
|
this.nacosServerAddress = URL.valueOf(nacosServerAddress).getAddress(); |
||||||
|
this.scheduledExecutorService = Executors.newScheduledThreadPool(1, |
||||||
|
new FastThreadLocalThreadFactory("entry-monitor-%d", Thread.NORM_PRIORITY)); |
||||||
|
this.scheduledExecutorService.scheduleWithFixedDelay(() -> { |
||||||
|
try { |
||||||
|
for (Map.Entry<String, EntryClient> entry : entryClientMap.entrySet()) { |
||||||
|
try { |
||||||
|
EntryClient entryClient = entry.getValue(); |
||||||
|
// 定时获取状态信息
|
||||||
|
EntryMonitor.ReqEntryStatus req = EntryMonitor.ReqEntryStatus.newBuilder().build(); |
||||||
|
CompletableFuture<EntryMonitor.ResEntryStatus> future = entryClient.send(req); |
||||||
|
EntryMonitor.ResEntryStatus res = future.join(); |
||||||
|
entryClient.updateEntryStatus(res.getConnections(), res.getStatusTime()); |
||||||
|
} catch (SoimException e) { |
||||||
|
logger.error("获取状态信息失败", e); |
||||||
|
entryClientMap.remove(entry.getKey(), entry.getValue()); |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (Exception e) { |
||||||
|
logger.error("定时拉取状态信息错误", e); |
||||||
|
} |
||||||
|
}, 5, 5, TimeUnit.SECONDS); |
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> { |
||||||
|
if (namingService != null) { |
||||||
|
try { |
||||||
|
namingService.shutDown(); |
||||||
|
} catch (NacosException e) { |
||||||
|
logger.error("nacos naming server shutdown exception", e); |
||||||
|
} |
||||||
|
scheduledExecutorService.shutdownNow(); |
||||||
|
entryClientMap.values().forEach(EntryClient::close); |
||||||
|
logger.info("entry monitor shutdown."); |
||||||
|
} |
||||||
|
})); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void onApplicationEvent(ApplicationReadyEvent readyEvent) { |
||||||
|
// NamingServer 获取 im-entry 实例,连接上,
|
||||||
|
Properties properties = new Properties(); |
||||||
|
properties.put("serverAddr", nacosServerAddress); |
||||||
|
try { |
||||||
|
this.namingService = NacosFactory.createNamingService(properties); |
||||||
|
// 初次启动获取所有 im-entry 服务节点
|
||||||
|
List<Instance> imEntryInstances = this.namingService.getAllInstances(AppConstant.APP_IM_ENTRY_NAME); |
||||||
|
this.buildEntryMonitorMap(imEntryInstances); |
||||||
|
// 监听 im-entry 服务变化
|
||||||
|
this.namingService.subscribe(AppConstant.APP_IM_ENTRY_NAME, (Event event) -> { |
||||||
|
if (!(event instanceof NamingEvent)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
NamingEvent ne = (NamingEvent) event; |
||||||
|
try { |
||||||
|
this.buildEntryMonitorMap(ne.getInstances()); |
||||||
|
}catch (Exception e) { |
||||||
|
logger.error("构建im-entry服务节点失败:", e); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
} catch (NacosException e) { |
||||||
|
logger.error("nacos exception", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 重新构建 im-entry 服务节点记录 |
||||||
|
*/ |
||||||
|
private synchronized void buildEntryMonitorMap(List<Instance> imEntryInstances) { |
||||||
|
HashSet<String> instanceAddresses = new HashSet<>(Collects.mapCapacity(imEntryInstances.size())); |
||||||
|
imEntryInstances.forEach(instance -> { |
||||||
|
String address = instance.getIp() + ":" + (instance.getPort() + AppConstant.IM_ENTRY_SERVER_OFFSET); |
||||||
|
instanceAddresses.add(address); |
||||||
|
}); |
||||||
|
logger.info("im-entry instances: {}", instanceAddresses); |
||||||
|
// 关闭失效im-entry
|
||||||
|
List<String> invalidateAddresses = new ArrayList<>(); |
||||||
|
for (Map.Entry<String, EntryClient> entry : entryClientMap.entrySet()) { |
||||||
|
if (!instanceAddresses.contains(entry.getKey())) { |
||||||
|
invalidateAddresses.add(entry.getKey()); |
||||||
|
} |
||||||
|
} |
||||||
|
for (String invalidateAddress : invalidateAddresses) { |
||||||
|
EntryClient invalidClient = entryClientMap.remove(invalidateAddress); |
||||||
|
invalidClient.close(); |
||||||
|
logger.info("invalid im-entry {} closed.", invalidateAddress); |
||||||
|
} |
||||||
|
|
||||||
|
// 添加新的 im-entry 连接
|
||||||
|
for (String instanceAddress : instanceAddresses) { |
||||||
|
if (entryClientMap.containsKey(instanceAddress)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
// nacos 注册时, entry server 还未启动完成,延时 5s 连接
|
||||||
|
this.scheduledExecutorService.schedule(() -> { |
||||||
|
EntryClient entryClient = new EntryClient(instanceAddress); |
||||||
|
logger.info("连接: {}", instanceAddress); |
||||||
|
boolean connected = entryClient.connect(); |
||||||
|
if (!connected) { |
||||||
|
logger.error("im-entry {} 连接失败", instanceAddress); |
||||||
|
return; |
||||||
|
} |
||||||
|
entryClientMap.put(instanceAddress, entryClient); |
||||||
|
}, 5, TimeUnit.SECONDS); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取一个活跃的 im-entry 服务器地址 |
||||||
|
*/ |
||||||
|
public String getOneActiveImEntryAddress() { |
||||||
|
if (entryClientMap.size() == 0) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
Collection<EntryClient> clients = entryClientMap.values(); |
||||||
|
List<EntryClient> sortedClients = clients.stream() |
||||||
|
.sorted(Comparator.comparing(EntryClient::getEntryConnections)) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
logger.info("entrys: {}", sortedClients); |
||||||
|
return sortedClients.get(0).getEntryAddress(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getOrder() { |
||||||
|
return Ordered.HIGHEST_PRECEDENCE; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,37 @@ |
|||||||
|
package net.sopod.soim.entry.http.controller; |
||||||
|
|
||||||
|
import com.alibaba.nacos.api.naming.pojo.healthcheck.impl.Http; |
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import net.sopod.soim.entry.http.client.EntryClient; |
||||||
|
import net.sopod.soim.entry.http.config.ImEntryMonitor; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
import org.springframework.http.HttpRequest; |
||||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||||
|
import org.springframework.web.bind.annotation.RequestMapping; |
||||||
|
import org.springframework.web.bind.annotation.RestController; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import java.util.Iterator; |
||||||
|
|
||||||
|
/** |
||||||
|
* MonitorController |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-11 16:13 |
||||||
|
*/ |
||||||
|
@RestController |
||||||
|
@AllArgsConstructor |
||||||
|
@RequestMapping("/monitor") |
||||||
|
public class MonitorController { |
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(EntryClient.class); |
||||||
|
|
||||||
|
private ImEntryMonitor imEntryMonitor; |
||||||
|
|
||||||
|
@GetMapping("/entryHost") |
||||||
|
public String getEntryHost() { |
||||||
|
return imEntryMonitor.getOneActiveImEntryAddress(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,13 +1,30 @@ |
|||||||
package net.sopod.soim.entry.http.service; |
package net.sopod.soim.entry.http.service; |
||||||
|
|
||||||
|
import com.alibaba.nacos.api.NacosFactory; |
||||||
|
import com.alibaba.nacos.api.exception.NacosException; |
||||||
|
import com.alibaba.nacos.api.naming.NamingService; |
||||||
|
import com.alibaba.nacos.api.naming.listener.Event; |
||||||
|
import com.alibaba.nacos.api.naming.listener.NamingEvent; |
||||||
|
import com.alibaba.nacos.api.naming.pojo.Instance; |
||||||
|
import net.sopod.soim.common.constant.AppConstant; |
||||||
|
import net.sopod.soim.entry.http.config.ImEntryMonitor; |
||||||
|
import org.apache.dubbo.common.URL; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
import org.springframework.beans.factory.annotation.Value; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Properties; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
/** |
/** |
||||||
* ImMonitorService |
* ImMonitorService |
||||||
* |
* |
||||||
* @author tmy |
* @author tmy |
||||||
* @date 2022-04-13 23:27 |
* @date 2022-04-13 23:27 |
||||||
*/ |
*/ |
||||||
|
@Service |
||||||
public class ImEntryMonitorService { |
public class ImEntryMonitorService { |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} |
} |
||||||
|
|||||||
@ -0,0 +1,58 @@ |
|||||||
|
package net.sopod.soim.entry.http.service; |
||||||
|
|
||||||
|
import com.google.protobuf.MessageLite; |
||||||
|
import io.netty.util.AttributeKey; |
||||||
|
import org.apache.commons.lang3.tuple.Pair; |
||||||
|
import org.slf4j.Logger; |
||||||
|
import org.slf4j.LoggerFactory; |
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture; |
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
import java.util.concurrent.atomic.AtomicInteger; |
||||||
|
|
||||||
|
/** |
||||||
|
* MessageQueueHolder |
||||||
|
* 发送一条消息产生一个序列号,在队列中等待响应消息 |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-02 17:29 |
||||||
|
*/ |
||||||
|
public class ImMessageReqHolder { |
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ImMessageReqHolder.class); |
||||||
|
|
||||||
|
public static AttributeKey<ImMessageReqHolder> IM_MESSAGE_HOLDER_KEY = AttributeKey.valueOf(ImMessageReqHolder.class, "IM_MESSAGE_HOLDER_KEY"); |
||||||
|
|
||||||
|
private final AtomicInteger serialNoGen; |
||||||
|
|
||||||
|
// TODO 超时处理
|
||||||
|
private final ConcurrentHashMap<Integer, CompletableFuture<Object>> futureMap; |
||||||
|
|
||||||
|
public ImMessageReqHolder() { |
||||||
|
this.serialNoGen = new AtomicInteger(); |
||||||
|
this.futureMap = new ConcurrentHashMap<>(); |
||||||
|
} |
||||||
|
|
||||||
|
public Pair<Integer, CompletableFuture<Object>> nextSerialNo() { |
||||||
|
serialNoGen.compareAndSet(Integer.MAX_VALUE, 0); |
||||||
|
int serialNo = serialNoGen.incrementAndGet(); |
||||||
|
CompletableFuture<Object> future = new CompletableFuture<>(); |
||||||
|
futureMap.put(serialNo, future); |
||||||
|
logger.debug("put future: {}", serialNo); |
||||||
|
return Pair.of(serialNo, future); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* TODO complete fail |
||||||
|
*/ |
||||||
|
public void complete(int serialNo, MessageLite msg) { |
||||||
|
CompletableFuture<Object> completableFuture = futureMap.remove(serialNo); |
||||||
|
if (completableFuture != null) { |
||||||
|
completableFuture.complete(msg); |
||||||
|
} else { |
||||||
|
// TODO dispatch im-entry 主动消息
|
||||||
|
logger.warn("no future wait for msg: {}", msg); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,5 @@ |
|||||||
|
FROM openjdk:11 |
||||||
|
ARG JAR_FILE |
||||||
|
ENV JAR_FILE ${JAR_FILE} |
||||||
|
ADD target/${JAR_FILE} / |
||||||
|
CMD java -jar $JAVA_OPTS /${JAR_FILE} |
||||||
@ -0,0 +1,33 @@ |
|||||||
|
package net.sopod.soim.entry.handlers.monitor; |
||||||
|
|
||||||
|
import com.google.protobuf.MessageLite; |
||||||
|
import lombok.AllArgsConstructor; |
||||||
|
import net.sopod.soim.common.util.ImClock; |
||||||
|
import net.sopod.soim.data.msg.monitor.EntryMonitor; |
||||||
|
import net.sopod.soim.entry.server.AccountRegistry; |
||||||
|
import net.sopod.soim.entry.server.handler.ImContext; |
||||||
|
import net.sopod.soim.entry.server.handler.MonitorMessageHandler; |
||||||
|
import net.sopod.soim.entry.server.session.Monitor; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
/** |
||||||
|
* ReqEntryStatusHandler |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-11 14:39 |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
@AllArgsConstructor |
||||||
|
public class ReqEntryStatusHandler extends MonitorMessageHandler<EntryMonitor.ReqEntryStatus> { |
||||||
|
|
||||||
|
private final AccountRegistry accountRegistry; |
||||||
|
|
||||||
|
@Override |
||||||
|
public MessageLite handle(ImContext ctx, Monitor monitor, EntryMonitor.ReqEntryStatus req) { |
||||||
|
return EntryMonitor.ResEntryStatus.newBuilder() |
||||||
|
.setConnections(accountRegistry.getRegistryAccountSize()) |
||||||
|
.setStatusTime(ImClock.millis()) |
||||||
|
.build(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
package net.sopod.soim.entry.handlers.monitor; |
||||||
|
|
||||||
|
import com.google.protobuf.MessageLite; |
||||||
|
import net.sopod.soim.common.constant.AppConstant; |
||||||
|
import net.sopod.soim.common.util.ImClock; |
||||||
|
import net.sopod.soim.data.msg.monitor.EntryMonitor; |
||||||
|
import net.sopod.soim.data.msg.task.Tasks; |
||||||
|
import net.sopod.soim.entry.delay.NetUserDelayTaskManager; |
||||||
|
import net.sopod.soim.entry.server.handler.ImContext; |
||||||
|
import net.sopod.soim.entry.server.handler.NetUserMessageHandler; |
||||||
|
import net.sopod.soim.entry.server.session.Monitor; |
||||||
|
import net.sopod.soim.entry.server.session.NetUser; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
|
||||||
|
/** |
||||||
|
* ReqMonitorAuthHandler |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-11 14:30 |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
public class ReqMonitorAuthHandler extends NetUserMessageHandler<EntryMonitor.ReqMonitorAuth> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public MessageLite handle(ImContext ctx, NetUser netUser, EntryMonitor.ReqMonitorAuth msg) { |
||||||
|
EntryMonitor.ResMonitorAuth.Builder resBuilder = EntryMonitor.ResMonitorAuth.newBuilder(); |
||||||
|
if (!AppConstant.IM_ENTRY_MONITOR_SECURITY.equals(msg.getSecurity())) { |
||||||
|
// 认证失败 6 秒后会关闭连接
|
||||||
|
return resBuilder.setSuccess(false).build(); |
||||||
|
} |
||||||
|
Monitor monitor = new Monitor(netUser.channel()); |
||||||
|
netUser.upgradeMonitor(monitor); |
||||||
|
return resBuilder.setSuccess(true).build(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -1,40 +0,0 @@ |
|||||||
package net.sopod.soim.entry.server; |
|
||||||
|
|
||||||
import net.sopod.soim.entry.config.EntryServerConfig; |
|
||||||
import net.sopod.soim.entry.worker.WorkerGroup; |
|
||||||
import org.slf4j.Logger; |
|
||||||
import org.slf4j.LoggerFactory; |
|
||||||
import org.springframework.boot.ApplicationArguments; |
|
||||||
import org.springframework.boot.ApplicationRunner; |
|
||||||
import org.springframework.stereotype.Component; |
|
||||||
|
|
||||||
/** |
|
||||||
* ServerRunner |
|
||||||
* |
|
||||||
* @author tmy |
|
||||||
* @date 2022-03-29 00:22 |
|
||||||
*/ |
|
||||||
// @Component
|
|
||||||
@Deprecated |
|
||||||
public class EntryServerRunner implements ApplicationRunner { |
|
||||||
private static final Logger logger = LoggerFactory.getLogger(EntryServerRunner.class); |
|
||||||
|
|
||||||
private final EntryServerConfig config; |
|
||||||
|
|
||||||
public EntryServerRunner(EntryServerConfig config) { |
|
||||||
this.config = config; |
|
||||||
} |
|
||||||
|
|
||||||
@Override |
|
||||||
public void run(ApplicationArguments args) { |
|
||||||
EntryServer entryServer = new EntryServer(this.config.getName(), this.config.getPort()); |
|
||||||
entryServer.startServer(err -> { |
|
||||||
logger.error("EntryServer 启动失败:", err); |
|
||||||
}); |
|
||||||
Runtime.getRuntime().addShutdownHook(new Thread(entryServer::shutdown)); |
|
||||||
|
|
||||||
// 启动消息消费队列组
|
|
||||||
WorkerGroup.init(config.getWorkerSize()); |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
@ -0,0 +1,30 @@ |
|||||||
|
package net.sopod.soim.entry.server.handler; |
||||||
|
|
||||||
|
import com.google.protobuf.MessageLite; |
||||||
|
import net.sopod.soim.common.dubbo.exception.SoimException; |
||||||
|
import net.sopod.soim.entry.server.session.Account; |
||||||
|
import net.sopod.soim.entry.server.session.Monitor; |
||||||
|
import net.sopod.soim.entry.server.session.NetUser; |
||||||
|
|
||||||
|
/** |
||||||
|
* MonitorMessageHandler |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-11 14:41 |
||||||
|
*/ |
||||||
|
public abstract class MonitorMessageHandler<T> implements MessageHandler<T> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void exec(ImContext ctx, NetUser netUser, T req) { |
||||||
|
if (!netUser.isMonitor()) { |
||||||
|
throw new SoimException("NetUser is not Monitor!" + netUser); |
||||||
|
} |
||||||
|
MessageLite res = this.handle(ctx, (Monitor) netUser, req); |
||||||
|
if (res != null) { |
||||||
|
netUser.writeNow(ctx, res); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public abstract MessageLite handle(ImContext ctx, Monitor monitor, T req); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,32 @@ |
|||||||
|
package net.sopod.soim.entry.server.session; |
||||||
|
|
||||||
|
import io.netty.channel.Channel; |
||||||
|
|
||||||
|
/** |
||||||
|
* Monitor |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-11 14:31 |
||||||
|
*/ |
||||||
|
public class Monitor extends NetUser { |
||||||
|
|
||||||
|
private long lastActive; |
||||||
|
|
||||||
|
public Monitor(Channel channel) { |
||||||
|
super(channel); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isMonitor() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public void setLastActive(long lastActive) { |
||||||
|
this.lastActive = lastActive; |
||||||
|
} |
||||||
|
|
||||||
|
public long getLastActive() { |
||||||
|
return lastActive; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,27 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||||
|
<parent> |
||||||
|
<artifactId>so-im</artifactId> |
||||||
|
<groupId>net.sopod</groupId> |
||||||
|
<version>1.0.0</version> |
||||||
|
</parent> |
||||||
|
<modelVersion>4.0.0</modelVersion> |
||||||
|
|
||||||
|
<artifactId>im-launcher</artifactId> |
||||||
|
|
||||||
|
<dependencies> |
||||||
|
<dependency> |
||||||
|
<groupId>org.springframework.boot</groupId> |
||||||
|
<artifactId>spring-boot-starter</artifactId> |
||||||
|
<exclusions><!-- 去掉springboot默认logback日志配置 --> |
||||||
|
<exclusion> |
||||||
|
<groupId>org.springframework.boot</groupId> |
||||||
|
<artifactId>spring-boot-starter-logging</artifactId> |
||||||
|
</exclusion> |
||||||
|
</exclusions> |
||||||
|
</dependency> |
||||||
|
</dependencies> |
||||||
|
|
||||||
|
</project> |
||||||
@ -0,0 +1,15 @@ |
|||||||
|
package net.sopod.soim.launcher; |
||||||
|
|
||||||
|
import org.springframework.core.Ordered; |
||||||
|
|
||||||
|
/** |
||||||
|
* LauncherService |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-10 21:33 |
||||||
|
*/ |
||||||
|
public interface LauncherService extends Ordered { |
||||||
|
|
||||||
|
void launcher(); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
package net.sopod.soim.launcher; |
||||||
|
|
||||||
|
import net.sopod.soim.launcher.util.PropsUtil; |
||||||
|
import org.springframework.boot.SpringApplication; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
import java.util.*; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* SoimApplication |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-10 19:48 |
||||||
|
*/ |
||||||
|
public class SoimApplication { |
||||||
|
|
||||||
|
public static void run(Class<?> primarySource, String...args) { |
||||||
|
buildApplicationProperties(); |
||||||
|
SpringApplication.run(primarySource, args); |
||||||
|
} |
||||||
|
|
||||||
|
private static void buildApplicationProperties() { |
||||||
|
List<LauncherService> launcherServices = new ArrayList<>(); |
||||||
|
ServiceLoader.load(LauncherService.class).forEach(launcherServices::add); |
||||||
|
launcherServices.stream().sorted(Comparator.comparing(LauncherService::getOrder)) |
||||||
|
.collect(Collectors.toList()) |
||||||
|
.forEach(LauncherService::launcher); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,52 @@ |
|||||||
|
package net.sopod.soim.launcher.service; |
||||||
|
|
||||||
|
import net.sopod.soim.launcher.LauncherService; |
||||||
|
import net.sopod.soim.launcher.util.PropsUtil; |
||||||
|
import org.springframework.core.Ordered; |
||||||
|
import org.springframework.core.io.Resource; |
||||||
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.InputStreamReader; |
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Properties; |
||||||
|
|
||||||
|
/** |
||||||
|
* PropertiesLauncherService |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-10 21:34 |
||||||
|
*/ |
||||||
|
public class PropertiesLauncherService implements LauncherService { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void launcher() { |
||||||
|
System.out.println("启动参数初始化..."); |
||||||
|
PathMatchingResourcePatternResolver resourceResolver = new PathMatchingResourcePatternResolver(); |
||||||
|
Resource resource = resourceResolver.getResource("classpath:launcher.properties"); |
||||||
|
try { |
||||||
|
InputStream launcherPropsIn = resource.getInputStream(); |
||||||
|
// InputStream launcherPropsIn = this.getClass().getResourceAsStream("launcher.properties");
|
||||||
|
InputStreamReader launcherPropsReader = new InputStreamReader(launcherPropsIn, StandardCharsets.UTF_8); |
||||||
|
Properties properties = new Properties(); |
||||||
|
Properties sysProps = System.getProperties(); |
||||||
|
properties.load(launcherPropsReader); |
||||||
|
// 设置 properties
|
||||||
|
for (Map.Entry<Object, Object> entry : properties.entrySet()) { |
||||||
|
String key = String.valueOf(entry.getKey()); |
||||||
|
String value = String.valueOf(entry.getValue()); |
||||||
|
PropsUtil.setProperty(sysProps, key, value); |
||||||
|
} |
||||||
|
} catch (IOException e) { |
||||||
|
throw new IllegalStateException("启动参数初始化失败", e); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getOrder() { |
||||||
|
return Ordered.HIGHEST_PRECEDENCE; |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,21 @@ |
|||||||
|
package net.sopod.soim.launcher.util; |
||||||
|
|
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
|
||||||
|
import java.util.Properties; |
||||||
|
|
||||||
|
/** |
||||||
|
* PropsUtil |
||||||
|
* |
||||||
|
* @author tmy |
||||||
|
* @date 2022-06-10 20:03 |
||||||
|
*/ |
||||||
|
public class PropsUtil { |
||||||
|
|
||||||
|
public static void setProperty(Properties props, String key, String value) { |
||||||
|
if (StringUtils.isEmpty(props.getProperty(key))) { |
||||||
|
props.setProperty(key, value); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1 @@ |
|||||||
|
net.sopod.soim.launcher.service.PropertiesLauncherService |
||||||
@ -0,0 +1,55 @@ |
|||||||
|
# dubbo registry nacos |
||||||
|
dubbo.registry.address=nacos://ip:port |
||||||
|
dubbo.registry.group=so-im |
||||||
|
|
||||||
|
|
||||||
|
# shardingsphere datasource (before DataSourceAutoConfiguration) |
||||||
|
spring.shardingsphere.datasource.names=ds1 |
||||||
|
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource |
||||||
|
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driver |
||||||
|
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://ip:port/soim_db?serverTimezone=GMT%2B8 |
||||||
|
spring.shardingsphere.datasource.ds1.username=username |
||||||
|
spring.shardingsphere.datasource.ds1.password=password |
||||||
|
spring.shardingsphere.datasource.ds1.minimumIdle=1 |
||||||
|
spring.shardingsphere.datasource.ds1.maximumPoolSize=4 |
||||||
|
spring.shardingsphere.datasource.ds1.connectionTimeout=2000 |
||||||
|
spring.shardingsphere.datasource.ds1.idleTimeout=300000 |
||||||
|
spring.shardingsphere.datasource.ds1.maxLifeTime=600000 |
||||||
|
spring.shardingsphere.datasource.ds1.keepaliveTime=30000 |
||||||
|
spring.shardingsphere.datasource.ds1.validateTimeout=2000 |
||||||
|
|
||||||
|
|
||||||
|
# spring datasource DataSourceAutoConfiguration |
||||||
|
spring.datasource.type=com.zaxxer.hikari.HikariDataSource |
||||||
|
spring.datasource.url=jdbc:mysql://ip:port/soim_db?serverTimezone=GMT%2B8 |
||||||
|
spring.datasource.username=username |
||||||
|
spring.datasource.password=password |
||||||
|
spring.datasource.hikari.minimum-idle=1 |
||||||
|
spring.datasource.hikari.maximum-pool-size=8 |
||||||
|
spring.datasource.hikari.connection-timeout=2000 |
||||||
|
# 5分钟空闲关闭 |
||||||
|
spring.datasource.hikari.idle-timeout=300000 |
||||||
|
# 10分钟最大存活时间 |
||||||
|
spring.datasource.hikari.max-lifetime=600000 |
||||||
|
spring.datasource.hikari.validation-timeout=2000 |
||||||
|
# datasource.hikari.connection-init-sql: select 1 |
||||||
|
# 连接存活时间,小于maxLifetime, 最小30秒, 空闲30秒后移除连接测试通过再添加回池 |
||||||
|
spring.datasource.hikari.keepalive-time=30000 |
||||||
|
|
||||||
|
|
||||||
|
# rabbitmq |
||||||
|
spring.rabbitmq.host=ip |
||||||
|
spring.rabbitmq.port=port |
||||||
|
spring.rabbitmq.username=username |
||||||
|
spring.rabbitmq.password=password |
||||||
|
|
||||||
|
|
||||||
|
# redis |
||||||
|
redis.host=ip |
||||||
|
redis.port=port |
||||||
|
redis.password=password |
||||||
|
redis.lettuce.pool.max-active=100 |
||||||
|
redis.lettuce.pool.max-idle=100 |
||||||
|
redis.lettuce.pool.max-wait=1000 |
||||||
|
redis.lettuce.pool.min-idle=2 |
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,29 @@ |
|||||||
|
syntax="proto3"; |
||||||
|
|
||||||
|
option java_multiple_files = false; |
||||||
|
option java_outer_classname = "EntryMonitor"; |
||||||
|
|
||||||
|
package net.sopod.soim.data.msg.monitor; |
||||||
|
|
||||||
|
// im-entry 监控消息 |
||||||
|
|
||||||
|
message ReqMonitorAuth { |
||||||
|
// string host = 1; |
||||||
|
string security = 2; |
||||||
|
} |
||||||
|
|
||||||
|
message ResMonitorAuth { |
||||||
|
bool success = 1; |
||||||
|
} |
||||||
|
|
||||||
|
message ReqEntryStatus { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
message ResEntryStatus { |
||||||
|
// 状态生成时间 |
||||||
|
int64 statusTime = 5; |
||||||
|
// 连接数 |
||||||
|
int32 connections = 6; |
||||||
|
// TODO...其他信息 |
||||||
|
} |
||||||
@ -1,30 +1,34 @@ |
|||||||
net.sopod.soim.data.msg.group.Group$ReqUserGroups=10000 |
net.sopod.soim.data.msg.user.UserMsg$UserInfo=10000 |
||||||
net.sopod.soim.data.msg.group.Group$GroupInfo=10001 |
net.sopod.soim.data.msg.group.Group$ReqGroupUsers=10001 |
||||||
net.sopod.soim.data.msg.group.Group$ResSearchGroup=10002 |
net.sopod.soim.data.msg.group.Group$ResSearchGroup=10002 |
||||||
net.sopod.soim.data.msg.hello.HelloPB$Hello=10003 |
net.sopod.soim.data.msg.hello.HelloPB$Hello=10003 |
||||||
net.sopod.soim.data.msg.user.Friend$ReqAddFriend=10004 |
net.sopod.soim.data.msg.user.UserGroup$ReqOnlineUserList=10004 |
||||||
net.sopod.soim.data.msg.auth.Auth$ResTokenAuth=10005 |
net.sopod.soim.data.msg.group.Group$ResUserGroups=10005 |
||||||
net.sopod.soim.data.msg.chat.Chat$TextChat=10006 |
net.sopod.soim.data.msg.user.Friend$ResFriendList=10006 |
||||||
net.sopod.soim.data.msg.user.AccountSearch$ReqAccountSearch=10007 |
net.sopod.soim.data.msg.task.Tasks$NetUserDelayCloseTask=10007 |
||||||
net.sopod.soim.data.msg.net.HeartBeat$Pong=10008 |
net.sopod.soim.data.msg.group.Group$ReqSearchGroup=10008 |
||||||
net.sopod.soim.data.msg.auth.Auth$ReqTokenAuth=10009 |
net.sopod.soim.data.msg.net.HeartBeat$Pong=10009 |
||||||
net.sopod.soim.data.msg.group.Group$ReqGroupUsers=10010 |
net.sopod.soim.data.msg.chat.Chat$TextChat=10010 |
||||||
net.sopod.soim.data.msg.user.UserGroup$ResOnlineUserList=10011 |
net.sopod.soim.data.msg.group.Group$ReqGroupMessage=10011 |
||||||
net.sopod.soim.data.msg.user.AccountSearch$ResAccountSearch=10012 |
net.sopod.soim.data.msg.user.UserGroup$ResOnlineUserList=10012 |
||||||
net.sopod.soim.data.msg.group.Group$ReqCreateGroup=10013 |
net.sopod.soim.data.msg.common.Res$ResState=10013 |
||||||
net.sopod.soim.data.msg.user.Friend$ResFriendList=10014 |
net.sopod.soim.data.msg.user.AccountSearch$ResAccountSearch=10014 |
||||||
net.sopod.soim.data.msg.group.Group$ReqSearchGroup=10015 |
net.sopod.soim.data.msg.group.Group$ReqJoinGroup=10015 |
||||||
net.sopod.soim.data.msg.group.Group$ReqGroupMessage=10016 |
net.sopod.soim.data.msg.monitor.EntryMonitor$ResEntryStatus=10016 |
||||||
net.sopod.soim.data.msg.group.Group$ResGroupUsers=10017 |
net.sopod.soim.data.msg.hello.HelloPB$World=10017 |
||||||
net.sopod.soim.data.msg.hello.HelloPB$World=10018 |
net.sopod.soim.data.msg.user.Friend$ReqFriendList=10018 |
||||||
net.sopod.soim.data.msg.group.Group$ReqJoinGroup=10019 |
net.sopod.soim.data.msg.net.HeartBeat$Ping=10019 |
||||||
net.sopod.soim.data.msg.user.UserGroup$ReqOnlineUserList=10020 |
net.sopod.soim.data.msg.monitor.EntryMonitor$ReqEntryStatus=10020 |
||||||
net.sopod.soim.data.msg.group.Group$UserInfo=10021 |
net.sopod.soim.data.msg.user.AccountSearch$ReqAccountSearch=10021 |
||||||
net.sopod.soim.data.msg.group.Group$ResGroupMessage=10022 |
net.sopod.soim.data.msg.user.Friend$ResAddFriend=10022 |
||||||
net.sopod.soim.data.msg.user.UserMsg$UserInfo=10023 |
net.sopod.soim.data.msg.group.Group$ResGroupUsers=10023 |
||||||
net.sopod.soim.data.msg.group.Group$ResUserGroups=10024 |
net.sopod.soim.data.msg.group.Group$ReqCreateGroup=10024 |
||||||
net.sopod.soim.data.msg.user.Friend$ResAddFriend=10025 |
net.sopod.soim.data.msg.group.Group$ResGroupMessage=10025 |
||||||
net.sopod.soim.data.msg.net.HeartBeat$Ping=10026 |
net.sopod.soim.data.msg.monitor.EntryMonitor$ReqMonitorAuth=10026 |
||||||
net.sopod.soim.data.msg.task.Tasks$NetUserDelayCloseTask=10027 |
net.sopod.soim.data.msg.group.Group$ReqUserGroups=10027 |
||||||
net.sopod.soim.data.msg.user.Friend$ReqFriendList=10028 |
net.sopod.soim.data.msg.group.Group$UserInfo=10028 |
||||||
net.sopod.soim.data.msg.common.Res$ResState=10029 |
net.sopod.soim.data.msg.user.Friend$ReqAddFriend=10029 |
||||||
|
net.sopod.soim.data.msg.auth.Auth$ReqTokenAuth=10030 |
||||||
|
net.sopod.soim.data.msg.monitor.EntryMonitor$ResMonitorAuth=10031 |
||||||
|
net.sopod.soim.data.msg.group.Group$GroupInfo=10032 |
||||||
|
net.sopod.soim.data.msg.auth.Auth$ResTokenAuth=10033 |
||||||
|
|||||||
Loading…
Reference in new issue