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.结语

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


相关推荐
Mortalbreeze22 分钟前
深入理解 TCP 协议(二):TCP 可靠传输与高效通信机制详解
linux·服务器·网络·网络协议·tcp/ip
bksczm27 分钟前
细谈传输层TCP协议API接口的底层原理
服务器·网络·tcp/ip
小玮看世界42 分钟前
[Python]从40分到100分:一场关于编程思维的“辩论赛”
运维·服务器
goyeer1 小时前
Liunx日志管理与journalctl
java·linux·运维·服务器·运维开发·信息化·信息化企业管理
酷可达拉斯1 小时前
自动化运维-Ansible Role综合应用案例-基于LNMP部署wordpress
linux·运维·服务器·自动化·ansible
Dovis(誓平步青云)2 小时前
从Redis指标采集到异常告警:redis_exporter + Prometheus 完整实战
服务器·数据库·人工智能·redis·架构·prometheus·vibe coding
垂钓的小鱼13 小时前
用关联图谱做量化选股:让基本面惊喜沿着网络扩散
服务器·php·apache
Lonely 净土9 小时前
Linux 运维文件写入操作
linux·运维·服务器·文件管理
城管不管9 小时前
重生——第十一次面试之挖财一面2026.8.19已OC
java·服务器·jvm·数据库·spring·面试·职场和发展
飞英思特无线充电10 小时前
严苛场景巡检机器人的无线补能设计:点位、BMS、认证与运维边界
运维·机器人