ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

brpc rpc_view 使用指南:用 HTTP 代理穿透端口限制,在浏览器中排查任意 server 内置服务

brpc rpc_view 使用指南:用 HTTP 代理穿透端口限制,在浏览器中排查任意 server 内置服务 brpc rpc_view 使用指南用 HTTP 代理穿透端口限制在浏览器中排查任意 server 内置服务【免费下载链接】brpcbrpc is an Industrial-grade RPC framework using C Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. brpc means better RPC.项目地址: https://gitcode.com/GitHub_Trending/brpc/brpc导读brpc 为每个服务内置了一整套基于 HTTP 的调试页面status、vars、connections、rpcz、cpu profiler 等但生产环境中服务端口往往被防火墙或策略限制导致浏览器无法直接访问这些内置服务只能退回到命令行 curl 查看纯文本既看不到历史趋势与动态曲线也无法点击链接跳转排查问题很不方便。rpc_view 正是为解决这一问题而生的工具它是一个特殊的 HTTP 反向代理把浏览器对自身的所有访问转发到目标 server 的内置服务让你在浏览器中完整、交互地查看原本无法直接访问的服务状态。读完本文你将掌握rpc_view 的编译与启动方法、通过 URL 参数动态切换目标 server 的技巧以及它作为http_master_service的底层转发原理与关键源码实现。rpc_view 是什么rpc_view 位于 tools/rpc_view 目录是一个独立的 C 命令行工具。它的核心思路非常简单把对 rpc_view 自身的所有 HTTP 访问原样转发为对目标 server 内置服务的访问。典型的应用场景是目标 server 的端口不在浏览器可访问的白名单范围内例如百度内只有 8000-8999 的端口能被笔记本直接访问服务端口被限浏览器无法打开它的内置服务页面你仍然可以在命令行下用curl查看纯文本但缺少历史趋势、动态曲线等可视化信息也无法点击页面上的链接逐级排查于是你在开发机上启动 rpc_view把 rpc_view 的端口默认 8888暴露给浏览器浏览器访问 rpc_view就能看到目标 server 原本看不见的内置服务页面且页面功能与直接访问几乎完全一致。从 docs/cn/builtin_service.md 可以看到brpc 内置服务本身包含 /status、/vars、/connections、/flags、/rpcz、cpu profiler、heap profiler、contention profiler 等多个页面rpc_view 可以把它们全部搬到可访问的端口上。获取工具编译 rpc_view前置条件先编译好 brpcrpc_view 依赖 brpc 库本身因此需要先按照 Getting Started 编译好 brpc产出output/include与output/lib再单独编译 rpc_view。在 Ubuntu 系环境下可以先安装依赖并编译 brpcsudo apt-get install -y git g make libssl-dev libgflags-dev libprotobuf-dev libprotoc-dev protobuf-compiler libleveldb-dev sh config_brpc.sh --headers/usr/include --libs/usr/lib make编译 rpc_view 本身进入 tools/rpc_view 目录执行make即可。目录下提供了 Makefile它通过BRPC_PATH ../../引入 brpc 根目录的config.mk链接output/lib/libbrpc.a静态库并声明了rpc_view这一目标BRPC_PATH ../../ include $(BRPC_PATH)/config.mk ... STATIC_LINKINGS $(BRPC_PATH)/output/lib/libbrpc.a ... all: rpc_view编译产物rpc_view为一个可执行文件直接运行即可无需部署任何额外服务端组件。提示文档提到在 CentOS 6.3 上如果出现找不到libssl.so.4的错误可执行ln -s /usr/lib64/libssl.so.6 libssl.so.4临时解决。此问题与旧系统的 OpenSSL 库版本有关现代发行版一般不会遇到。访问目标 server启动 rpc_view运行方式确保你的机器能访问目标 server开发机通常可以部分测试机可能因网络隔离不行然后运行./rpc_view server-address其中server-address是目标 server 的ip:port地址。例如$ ./rpc_view 10.46.130.53:9970 TRACE: 02-14 12:12:20: * 0 src/brpc/server.cpp:762] Server[rpc_view_server] is serving on port8888. TRACE: 02-14 12:12:20: * 0 src/brpc/server.cpp:771] Check out http://XXX.com:8888 in web browser.从日志可以看到rpc_view 内部其实是一个名为rpc_view_server的 brpc Server源码中通过server.set_version(rpc_view_server)设置见 tools/rpc_view/rpc_view.cpp默认监听 8888 端口。之后在浏览器中打开http://rpc_view所在机器:8888例如在 secureCRT 中按住 Ctrl 点击 URL看到的就是目标 server 的内置服务页面。命令行参数源码通过 gflags 定义了三个参数见 tools/rpc_view/rpc_view.cpp参数默认值说明-port8888rpc_view 自身监听的 TCP 端口-target空字符串要查看的目标 server 地址ip:port也可作为命令行位置参数传入-timeout_ms5000转发调用目标 server 的超时时间毫秒三种启动等价写法./rpc_view 10.46.130.53:9970 # 位置参数指定 target ./rpc_view -target10.46.130.53:9970 # gflags 方式指定 target ./rpc_view -port9999 -target10.46.130.53:9970 # 同时修改监听端口主函数中有一个细节tools/rpc_view/rpc_view.cpp当-target为空且没有位置参数时会打印Usage: ./rpc_view ip:port并退出启动时还会把defer_close_second设置为10这样动态创建的 channel 不会立刻关闭连接便于复用已有连接降低频繁转发时的建连开销。页面与直接访问基本一致打开页面后你会发现这就是目标 server 的内置服务页面顶部导航包含 status、vars、connections、flags、rpcz、cpu、heap、growth、contention、more 等标签方法与连接统计一应俱全。唯一的区别在于右下角有一个黑色的固定提示标签标注着rpc_view: target见上图中的右下角提醒你当前看到的是经由 rpc_view 转发出来的内容。这个提示是源码有意为之——在 handle_response 中转发响应时会在/body之前插入一段固定定位的 CSS 样式与rpc_view: target文本确保用户随时清楚自己正在查看哪个目标避免混淆。除此之外你可以像直接访问一样点击任意 tab、执行任意操作。更换目标 server浏览器内动态切换如果你需要查看另一台 server最简单的方式是停掉 rpc_view 重新启动并更换目标地址。但 rpc_view 也支持在浏览器中直接切换无需重启进程给当前 URL 加上?changetargetnew-server-address即可。例如之前停留在原目标 server 的/connections页面http://rpc_view所在机器:8888/connections将其改为http://rpc_view所在机器:8888/connections?changetarget10.46.130.54:8765页面会立刻跳转到新目标 server 的/connections页面之后点击其他 tab 展示的也都是新目标 server 的内容直到再次携带changetarget参数为止。changetarget 的底层实现在 ViewServiceImpl::default_method 中每次请求都会先检查 URL 查询参数中是否存在changetargetconst std::string* newtarget server_cntl-http_request().uri().GetQuery(changetarget); if (newtarget) { if (GFLAGS_NAMESPACE::SetCommandLineOption(target, newtarget-c_str()).empty()) { server_cntl-SetFailed(Fail to change value of -target); return; } target *newtarget; } else { // 读取当前 -target 的值 }这段代码有两个值得注意的点动态修改 gflags切换目标实际是通过SetCommandLineOption(target, ...)在运行期修改 gflags 实现的这与直接启动时指定-target效果一致线程安全处理源码注释明确说明不直接访问FLAGS_target因为 string 类型的 gflags 不是线程安全的见 tools/rpc_view/rpc_view.cpp因此通过GetCommandLineOption读取、SetCommandLineOption写入保证并发请求下目标地址的读写安全。深入原理rpc_view 的转发机制rpc_view 之所以能做到对自身的一切访问都转发到目标 server关键在于它把自己注册成了 brpc Server 的http_master_serviceHTTP 主服务。下面结合源码拆解它的实现。1. 注册为 http_master_servicebrpc 的ServerOptions支持设置一个http_master_service见 src/brpc/server.h。当 brpc Server 收到 HTTP 请求、且设置了http_master_service时会把请求直接交给它的default_method处理而不是走普通的 URI 路由见 src/brpc/policy/http_rpc_protocol.cppif (server-options().http_master_service) { // If http_master_service is on, just call it. google::protobuf::Service* svc server-options().http_master_service; const google::protobuf::MethodDescriptor* md svc-GetDescriptor()-FindMethodByName(common-DEFAULT_METHOD); ... return svc-CallMethod(md, cntl, nullptr, nullptr, done); }也就是说无论浏览器请求 rpc_view 的哪个路径/status、/vars、/connections 还是任意子路径最终都会进入 ViewServiceImpl 的default_method从而实现对任意目标路径的统一转发。rpc_view 的服务定义在 tools/rpc_view/view.proto 中只声明了一个空请求/空响应的default_methodsyntaxproto2; option cc_generic_services true; message HttpRequest {}; message HttpResponse {}; service ViewService { rpc default_method(HttpRequest) returns (HttpResponse); };与之呼应的是 brpc Server 启动时的约束校验src/brpc/server.cpphttp_master_service必须包含名为default_method的方法且其请求、响应类型都不能有字段——rpc_view 的定义正好满足这一要求。主函数中注册并启动服务tools/rpc_view/rpc_view.cppbrpc::Server server; server.set_version(rpc_view_server); brpc::ServerOptions server_opt; server_opt.http_master_service new ViewServiceImpl; if (server.Start(FLAGS_port, server_opt) ! 0) { ... } server.RunUntilAskedToQuit();2. 动态创建 HTTP channel 转发请求在default_method中rpc_view 以目标 server 地址为准现场创建一个 HTTP 协议的brpc::Channeltools/rpc_view/rpc_view.cppbrpc::Channel http_chan; brpc::ChannelOptions http_chan_opt; http_chan_opt.protocol brpc::PROTOCOL_HTTP; if (http_chan.Init(target.c_str(), http_chan_opt) ! 0) { server_cntl-SetFailed(brpc::EINTERNAL, Fail to connect to %s, target.c_str()); return; }随后把浏览器发来的 HTTP 请求原样搬运到目标 server拷贝请求 URIpath query fragment确保/connections、/vars?...等路径与参数完整透传tools/rpc_view/rpc_view.cpp移除Accept-Encoding请求头因为代码需要在/body前插入 rpc_view 标识文本禁止目标 server 压缩响应可以简化插入逻辑tools/rpc_view/rpc_view.cpp移除Host头让 RPC 框架在序列化时写入正确的目标 server 地址而不是 rpc_view 自身的 Hosttools/rpc_view/rpc_view.cpp保留请求体如 POST 内容原样透传tools/rpc_view/rpc_view.cpp。3. 动态超时与响应回传对于耗时较长的页面如 /hotspots 这类带seconds查询参数的页面rpc_view 会智能地延长转发超时默认超时-timeout_ms5000ms基础上把查询参数seconds的数值换算成毫秒叠加进去tools/rpc_view/rpc_view.cppconst std::string* seconds server_cntl-http_request().uri().GetQuery(seconds); int64_t timeout_ms FLAGS_timeout_ms; if (seconds) { timeout_ms atoll(seconds-c_str()) * 1000; } client_cntl-set_timeout_ms(timeout_ms);响应返回后由回调 handle_response 处理先整体拷贝目标 server 的 HTTP 响应头与响应体再在/body前插入右下角的rpc_view: target提示最后通过server_done-Run()把结果送回浏览器。值得一提的是即便目标 server 返回 HTTP 错误如 4xx/5xxrpc_view 也不会把 RPC 标记为失败而是把原始错误页面原样透传给用户保证看到的是目标 server 的真实内容而非被框架替换的错误文案。使用注意事项与建议网络可达性rpc_view 转发的前提是它所在机器能访问目标 server。开发机通常满足条件但部分测试机可能因网络隔离无法访问需要先确认连通性。端口选择默认监听 8888若冲突可通过-port指定其他端口同时建议选择浏览器可访问的端口来运行 rpc_view这正是它的价值所在。目标切换善用?changetargetip:port在同一浏览器会话内快速切换多台 server减少反复重启进程的麻烦。安全边界rpc_view 会把目标 server 的完整内置服务暴露在浏览器可访问的端口上且支持运行期切换目标本质上是一个通用 HTTP 代理使用时请确保其监听端口在受控环境内不要暴露到不可信网络。brpc 对直接对外服务的 server 本身也有隐藏内置服务的安全模式rpc_view 的场景与之类似应遵循同样的安全原则。性能定位rpc_view 面向的是偶尔打开页面排查问题的场景源码中主动移除了响应压缩、并依赖defer_close_second复用连接来降低开销但不应将其当作高并发流量入口或生产链路中的代理组件使用。小结rpc_view 用极少的代码量核心逻辑集中在 tools/rpc_view/rpc_view.cpp 一个文件解决了一个很实际的运维痛点借助 brpc 的http_master_service机制把任意 server 的内置服务搬到浏览器可访问的端口上并支持通过changetarget参数随时切换目标。理解它的实现也能让你对 brpc 的 HTTP 协议栈、http_master_service 与动态 channel 用法有更深入的认识。如果需要进一步了解 brpc 内置服务各页面的具体含义可继续阅读 docs/cn/builtin_service.md。【免费下载链接】brpcbrpc is an Industrial-grade RPC framework using C Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. brpc means better RPC.项目地址: https://gitcode.com/GitHub_Trending/brpc/brpc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表