

Github GitHub - Tencent/flare: Flare是广泛投产于腾讯广告后台的现代化C++开发框架...
source link: https://github.com/Tencent/flare
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Flare 后台服务开发框架
腾讯广告 是腾讯公司最重要的业务之一,其后台大量采用 C++ 开发。
Flare 是我们吸收先前服务框架和业界开源项目及最新研究成果开发的现代化的后台服务开发框架,旨在提供针对目前主流软硬件环境下的易用、高性能、平稳的服务开发能力。
Flare 项目开始于 2019 年,目前广泛应用于腾讯广告的众多后台服务,拥有数以万计的运行实例,在实际生产系统上经受了足够的考验。
2021 年 5 月,本着回馈社区、技术共享的精神,正式对外开源。
- 现代 C++ 设计风格,广泛采用了 C++11/14/17/2a 的新的语法特性和标准库
- 提供了 M:N 的线程模型的微线程实现Fiber,方便业务开发人员以便利的同步调用语法编写高性能的异步调用代码
- 支持基于消息的流式 RPC支持
- 除了 RPC 外,还提供了一系列便利的基础库,比如字符串、时间日期、编码处理、压缩、加密解密、配置、HTTP 客户端等,方便快速上手开发业务代码
- 提供了灵活的扩充机制。方便支持多种协议、服务发现、负载均衡、监控告警、调用追踪等
- 针对现代体系结构做了大量的优化。比如 NUMA 感知的调度组和对象池、零拷贝缓冲区等
- 高质量的代码。严格遵守 Google C++ 代码规范,测试覆盖率达 80%
- 完善的文档和示例以及调试支持,方便快速上手
- Linux 3.10 及以上内核,暂不支持其他操作系统
- x86-64 处理器,也支持 aarch64 及 ppc64le,但是未在生产环境上实际使用过
- GCC 8 及以上版本的编译器
Flare 是开箱即用的,已经自带了所需的第三方库,因此通常不需要额外安装依赖库。只需要在 Linux 下,拉取代码,即可使用。
thirdparty/
下面的压缩包我们通过Git LFS存储,因此在拉取代码之前您需要确保git-lfs
已经正确的安装了。
我们使用blade
进行日常开发。
- 编译:
./blade build ...
, - 测试:
./blade test ...
。
之后就可以参考入门导引中的介绍,搭建一个简单的RPC服务了。
我们相信,调试体验也是开发维护过程中很重要的一部分,我们为此也做了如下一些支持:
为了改善编写单测的体验,我们提供了一些用于编写单测的工具。
这包括但不限于:
我们提供了一些使用示例以供参考,下面是一个简单的转发服务(同时包含RPC客户端及服务端的使用)。
#include "thirdparty/gflags/gflags.h" #include "flare/example/rpc/echo_service.flare.pb.h" #include "flare/example/rpc/relay_service.flare.pb.h" #include "flare/fiber/this_fiber.h" #include "flare/init.h" #include "flare/rpc/rpc_channel.h" #include "flare/rpc/rpc_client_controller.h" #include "flare/rpc/rpc_server_controller.h" #include "flare/rpc/server.h" using namespace std::literals; DEFINE_string(ip, "127.0.0.1", "IP address to listen on."); DEFINE_int32(port, 5569, "Port to listen on."); DEFINE_string(forward_to, "flare://127.0.0.1:5567", "Target IP to forward requests to."); namespace example { class RelayServiceImpl : public SyncRelayService { public: void Relay(const RelayRequest& request, RelayResponse* response, flare::RpcServerController* ctlr) override { flare::RpcClientController our_ctlr; EchoRequest echo_req; echo_req.set_body(request.body()); if (auto result = stub_.Echo(echo_req, &our_ctlr)) { response->set_body(result->body()); } else { ctlr->SetFailed(result.error().code(), result.error().message()); } } private: EchoService_SyncStub stub_{FLAGS_forward_to}; }; int Entry(int argc, char** argv) { flare::Server server{flare::Server::Options{.service_name = "relay_server"}}; server.AddProtocol("flare"); server.AddService(std::make_unique<RelayServiceImpl>()); server.ListenOn(flare::EndpointFromIpv4(FLAGS_ip, FLAGS_port)); FLARE_CHECK(server.Start()); flare::WaitForQuitSignal(); return 0; } } // namespace example int main(int argc, char** argv) { return flare::Start(argc, argv, example::Entry); }
Flare内部基于M:N的用户态线程实现,因此通过Flare同步的请求外界服务、使用Flare内置的各种客户端的同步接口均不会导致性能问题。如果有更复杂的并发或异步等需求可以参考我们的文档。
另外,示例中*.flare.pb.h
通过我们的Protocol Buffers插件生成。这样生成的接口相对于Protocol Buffers生成的cc_generic_services
而言,更易使用。
更复杂的示例
实际使用中,往往会面对需要并发请求多种后端的场景,下面的示例介绍了如何在Flare中进行这种操作:
// For illustration purpose only. Normally you wouldn't want to declare them as // global variables. flare::HttpClient http_client; flare::CosClient cos_client; EchoService_SyncStub echo_stub(FLAGS_echo_server_addr); void FancyServiceImpl::FancyJob(const FancyJobRequest& request, FancyJobResponse* response, flare::RpcServerController* ctlr) { // Calling different services concurrently. auto async_http_body = http_client.AsyncGet(request.uri()); auto async_cos_data = cos_client.AsyncExecute(flare::CosGetObjectRequest{.key = request.key()}); EchoRequest echo_req; flare::RpcClientController echo_ctlr; echo_req.set_body(request.echo()); auto async_rpc_resp = echo_stub.AsyncEcho(EchoRequest(), &echo_ctlr); // Now wait for all of them to complete. auto&& [http, cos, rpc] = flare::fiber::BlockingGet( flare::WhenAll(&async_http_body, &async_cos_data, &async_rpc_resp)); if (!http || !cos || !rpc) { FLARE_LOG_WARNING("Failed."); } else { // All succeeded. FLARE_LOG_INFO("Got: {}, {}, {}", *http->body(), flare::FlattenSlow(cos->bytes), rpc->body()); } // Now fill `response` accordingly. response->set_body("Great success."); }
这个示例中,我们:
- 通过三种不同的客户端(HTTP、腾讯云COS、RPC)发起了三个异步请求;
- 通过
flare::fiber::BlockingGet
同步等待所有请求完成。这儿我们只会阻塞用户态线程,不会存在性能问题; - 打印日志输出各个服务的响应。
出于展示目的,我们这儿请求了三个异构的服务。如果有必要,也可以通过这种方式请求同构的、或者部分同构部分异构的服务。
我们非常欢迎参与共同建设,对于希望了解 Flare 更多内部设计的开发者,或需要对 Flare 进行二次开发的开发者而言,flare/doc/
下有更多的技术文档可供参考。
详情请参考CONTRIBUTING.md。
由于业务需求的特点,我们在设计过程中更倾向于优化延迟及抖动的平稳性而非吞吐,但是也在这个前提下尽量保证性能。
出于简单的对比目的,我们提供了初步的性能数据。
在此,我们对上述项目一并致以谢意。
Recommend
-
73
由于企业希望从云部署中获得更高的效率,容器的使用率正持续增加。根据云安全平台提供商Sysdig的一项新研究,大部分增长归功于Kubernetes,以及用户正在设法更密集地部署容器。
-
67
现如今心理学和行为学已经是UX和产品设计领域当中诸多理论的来源和实践的依据,它们是UI/UX设计师和产品设计师的必修课。 系统的心理...
-
112
问与答 - @chengluyu - 刚刚在某个帖子里看到有人认为大量使用 emoji 是一种心智不成熟的表现。但是根据我的观察,在输入法给 emoji 添加了联想功能后,emoji 的使用越来越广了。包括家里的老人使用微信的时候
-
66
随着人工智能技术的发展,机器智能可以利用海量的视频数据,结合模式识别、深度学习等先进算法来改变我们的生活。利用人工智能可以将视频分析精细化、可视化、自动化、智能化。以人工智能为基础的超分辨率重建技术在视频图像压...
-
67
-
63
README.md Plato(柏拉图) A framework for distributed graph computation and machine learning at wechat scale, for more details, see
-
6
NSA 与 CIA 都广泛使用广告拦截工具
-
8
腾讯宣布PAG动画组件正式开源,已广泛用于微信、王者荣耀等 App 财经网科技1月14日讯,据IT之家消息,腾讯宣布 PAG(Porta...
-
4
广泛匹配怎么玩?来看看这个广告打法 ...
-
2
腾讯吴运声:元宇宙是广泛概念,腾讯在全真互联多领域有积累 • 3 小时前...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK