Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

trpc-cpp 如何高效的访问存储服务(redis,mysql,mongo) #65

Open
zanlichard opened this issue Oct 24, 2023 · 25 comments
Open

trpc-cpp 如何高效的访问存储服务(redis,mysql,mongo) #65

zanlichard opened this issue Oct 24, 2023 · 25 comments

Comments

@zanlichard
Copy link

这个不是trpc-client的模式
redis,mysql,mongo走链接池模式?

@helloopenworld
Copy link
Contributor

redis已经框架支持了,mysql和mongo还没有
这里的问题是指在trpc下不走trpc client情况下,怎么通过redis/mysql/mongo的原生api访问对应的存储服务?

@zanlichard
Copy link
Author

是的

@zanlichard
Copy link
Author

类似golang中的连接池模式

@zanlichard
Copy link
Author

另外就是支持类似fiber方式访问下游的存储服务

@helloopenworld
Copy link
Contributor

helloopenworld commented Oct 24, 2023

当前可以参考下面的方式,未来会提供fiber环境下专门的组件封装。

这里以在fiber的线程运行环境下使用自己封装的mysql api访问mysql为例

trpc::Status ForwardServiceImpl::Route(trpc::ServerContextPtr context,
const trpc::test::route::RouteRequest* request,
trpc::test::route::RouteReply* response) {
// ...

auto ev = std::make_unique< trpc::FiberEvent >();
int ret = 0;
util::Mysql::MysqlData data;
// 向线程池投递一个mysql读写任务
this->worker_pool_ptr_->Enqueue([&ret, &data, &ev](util::Mysql* mysql_ptr) {
ret = mysql_ptr->QueryRecord("select * from test limit 1;", &data);
ev->Set();
});

// 非堵塞的, 不会堵塞框架fiber环境的工作线程
ev->Wait();
if (ret == 0) {
for (auto const& row : data.Data()) {
for (auto const& item : row) {
TRPC_FMT_INFO("get data, key:{}, value:{}", item.first, item.second);
}
}
response->set_msg("select ok");
} else {
response->set_msg("select error");
}

// ...
}

堵塞线程的操作(比如访问mysql)放到连接池下执行,业务主体的逻辑都是非堵塞的,同步写代码。

@helloopenworld
Copy link
Contributor

helloopenworld commented Oct 24, 2023

还可以使用 https://github.com/trpc-group/trpc-cpp/blob/main/trpc/coroutine/future.h 这个里面的接口,封装了FiberEvent,使用方法可以可以参考单测

@zanlichard
Copy link
Author

相当于用serviceProxy的方式来实现连接池
既然要在线程池层面阻塞,也就是serviceProxy这里也需要使用thread-model

@helloopenworld
Copy link
Contributor

差不多这个意思,对trpc框架来说,未来框架对接各种存储系统,会有两种实现方式,一种是基于各种存储系统sdk的封装实现,一种是不使用各种存储系统的sdk,而是只实现与各种存储系统交互的通信协议,然后网络通信和运行线程则交给框架来实现,这种用户写代码上会更方便。

@zanlichard
Copy link
Author

这么说的话,c++还是没有go这么方便
c++要实现异步的方案,就必须要有协议的客户端,也就是协议包的完整性检查

@zanlichard
Copy link
Author

还有一个问题,就是这些协议中没有类似rpc这种seq-id的东西,无法完全异步,还是要有queue的方式来确定请求和响应的对应关系

@helloopenworld
Copy link
Contributor

嗯,或者使用连接池,一个连接同时承载一个请求和响应

@zanlichard
Copy link
Author

当前的版本中trpc-cpp不支持在请求所在的fiber里面继续创建新的fiber,并且在request_fiber里面阻塞等待new create fiber返回?

@helloopenworld
Copy link
Contributor

可以啊,一个fiber可以通过FiberLatch等待另外一个fiber运行完成,等待的fiber不会堵塞线程的,只是暂时休眠了

@zanlichard
Copy link
Author

如果是这样的话,那可以在request_fiber中create a new fiber to access mysql by mysql connection pool

@zanlichard
Copy link
Author

如果这种编程的方式可行,而不用另外走serviceProxy这种方式了?

@helloopenworld
Copy link
Contributor

如果是这样的话,那可以在request_fiber中create a new fiber to access mysql by mysql connection pool

这种方式有一个风险时,因为mysql api访问时是同步堵塞的,会导致fiber环境下的工作线程卡住,从而出问题,所以建议使用同步堵塞的操作时,放到专门的线程池去处理

@zanlichard
Copy link
Author

trpc的协议trpc.proto中定义了magic,RequestProtocol,ResponseProtocol,TrpcStreamCloseMeta,有没有具体的数据帧的格式说明,类似tcp/ip里面的tcp协议头的定义

@zanlichard
Copy link
Author

such as magic + body_len + body(RequestProtocol/ResponseProtocol)

@zanlichard
Copy link
Author

for example,
┌────────────────┬───────────────┬────────────────┐
│ Packet Size │ Packet ID │ Body │
│ │ │ │
│ 4 bytes │ 4 bytes │ Variable size │
└────────────────┴───────────────┴────────────────┘

@zanlichard
Copy link
Author

协议格式: fixed_header + pb_header + body

@helloopenworld
Copy link
Contributor

可以看看这个:https://github.com/trpc-group/trpc/blob/main/docs/zh/trpc_protocol_design.md

@zanlichard
Copy link
Author

网络io处理调度:由ThreadModel与WorkerThread,Acceptor,Reactor构成了一套处理体系
业务处理调度:由ScheduleGroup与FiberWorker构成了一套处理体系
这个理解有没有问题

@helloopenworld
Copy link
Contributor

ScheduleGroup与FiberWorker构成的是m:n协程体系,使用同步编码
ThreadModel与WorkerThread,Acceptor,Reactor等构成的是线程体系,使用future异步编码
两者是独立的,使用上需要选一种体系

@city-invoker
Copy link

这个trpc在内部不是已经是服务生产服务的么,mysql还不支持?

@helloopenworld
Copy link
Contributor

支持,还未开源

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants