目录
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.结语
这个消息转发子服务的功能比较单一,所以篇幅很短。
完