IM项目——消息转发子服务

目录

1.引言

2.代码实现

3.结语


1.引言

消息转发子服务,人不如其名,它干的不是消息转发,而是告诉网关要将收到的消息转发给哪些用户,除此之外,还将消息进行组装,得到完整的信息后,转发给消息队列,供消息管理子服务从消息队列中消费,进行持久化存储。

2.代码实现

消息转发子服务仅仅提供了一个接口,它完成的就是上面提到功能。

实现流程:首先要提取出请求中的用户ID,明确是谁发的,然后还要提取出所属的聊天会话,这样才能够知道这些消息发给谁,其次就是对这条消息进行封装,转发给消息队列,最后就是遍历会话成员表chat_session_member获取这个会话的所有成员,然后通过响应告诉网关转发列表即可。

cpp 复制代码
void GetTransmitTarget(google::protobuf::RpcController* controller,
            const ::pcz::NewMessageReq* request,
            ::pcz::GetTransmitTargetRsp* response,
            ::google::protobuf::Closure* done) override {

            brpc::ClosureGuard rpc_guard(done);
            //组织错误响应
            auto err_response = [response](const std::string& id, const std::string& errmsg) {
                response->set_request_id(id);
                response->set_success(false);
                response->set_errmsg(errmsg);
            };
            //从请求中提取用户ID,消息内容,所属聊天会话
            std::string user_id = request->user_id();
            const MessageContent& content = request->message();
            std::string session_id = request->chat_session_id();
            //根据user_id获取用户的完整信息,通过channel_manager获取用户连接信息
            auto channel = _channel_manager->choose(_user_service_name);
            if (!channel) {
                err_response(request->request_id(), "获取用户服务信道失败");
                LOG_ERROR("获取用户服务信道失败 user_id={}", user_id);
                return;
            }
            //通过RPC调用用户服务,获取用户的连接信息
            UserService_Stub stub(channel.get());
            GetUserInfoReq req;
            GetUserInfoRsp rsp;
            req.set_request_id(request->request_id());
            req.set_user_id(user_id);
            brpc::Controller cntl;
            stub.GetUserInfo(&cntl, &req, &rsp, nullptr);
            if (cntl.Failed() == true || rsp.success() == false) {
                LOG_ERROR("{} - 用户子服务调用失败:{}!", request->request_id(), cntl.ErrorText());
                return err_response(request->request_id(), "用户子服务调用失败!");
            }
            //组织消息发送到消息队列
            MessageInfo message;
            message.set_message_id(uuid());
            message.set_chat_session_id(session_id);
            message.set_timestamp(time(nullptr));
            message.mutable_sender()->CopyFrom(rsp.user_info());
            message.mutable_message()->CopyFrom(content);
            bool publish_ok = _mq_client->publish(
                _exchange_name, message.SerializeAsString(), _routing_key
            );
            if (!publish_ok) {
                err_response(request->request_id(), "消息发布失败");
                LOG_ERROR("消息发布失败 user_id={}", user_id);
                return;
            }
            //组织响应
            //获取消息转发列表
            auto member_list = _mysql_session_member_table->members(session_id);
            for (const auto& member : member_list) {
                // 排除发送者自己,避免向自己转发
                if (member == user_id) continue;
                response->add_target_id_list(member);
            }
            response->set_request_id(request->request_id());
            response->mutable_message()->CopyFrom(message);
            response->set_success(true);
        }

3.结语

这个消息转发子服务的功能比较单一,所以篇幅很短。


相关推荐
JY.yuyu24 分钟前
Docker常用命令——数据卷管理 / 端口映射 / 容器互联
运维·docker·容器
alice--小文子1 小时前
cursor-mcp工具使用
java·服务器·前端
lpruoyu1 小时前
【Docker进阶-06】docker-compose & docker swarm
运维·docker·容器
China_Yanhy2 小时前
入职 Web3 运维日记 · 第 8 日:黑暗森林 —— 对抗 MEV 机器人的“三明治攻击”
运维·机器人·web3
艾莉丝努力练剑2 小时前
hixl vs NCCL:昇腾生态通信库的独特优势分析
运维·c++·人工智能·cann
酉鬼女又兒2 小时前
每天一个Linux命令_printf
linux·运维·服务器
翼龙云_cloud2 小时前
国际云代理商:2026年国际云注册风控升级实战指南 8 大平台无卡解决方案对比
服务器·阿里云·云计算
虾说羊2 小时前
docker容器化部署项目流程
运维·docker·容器
Trouvaille ~2 小时前
TCP Socket编程实战(三):线程池优化与TCP编程最佳实践
linux·运维·服务器·网络·c++·网络协议·tcp/ip
大大大反派2 小时前
CANN 生态中的自动化部署引擎:深入 `mindx-sdk` 项目构建端到端 AI 应用
运维·人工智能·自动化