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

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


相关推荐
tg_xianheyun4 小时前
CDN节点分布如何影响网页加载速度和用户体验
服务器·cdn加速·全球访问优化
lsh曙光4 小时前
延时at指令和定时cron指令
linux·服务器·网络
布鲁飞丝4 小时前
vivo Pulsar 万亿级消息处理实践()-Ansible运维部署
运维·ansible
XR1234567885 小时前
企业全光网络架构选型技术白皮书:从物理层到运维层的全链路分析
运维·网络·架构
HiDev_5 小时前
【非标自动化】2、认识元器件(直线模组)
运维·自动化
夏殇之殁6 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
龙仔7256 小时前
人大金仓 KingbaseES V8 只读账号创建完整运维笔记
运维·笔记·sql·人大金仓
我不管我就要叫小猪6 小时前
嵌入式Linux----网络通信
linux·运维·服务器
江湖有缘7 小时前
Docker实战 :使用Docker部署OneTerm堡垒机
运维·docker·容器
泡沫冰@7 小时前
ECS 的介绍和使用
linux·服务器·网络