【brpc学习实战二】brpc client构建基本流程

news/2025/2/13 2:18:01/

client基本概念及学习指南

https://github.com/luozesong/brpc/blob/master/docs/cn/client.md

一、编写proto

这里与服务一致,实际开发中需要双端共同确定proto内容;

二、初始化channel

rpc channel可以视为socket编程中的client对象
定义一个channel,Channel可以被所有线程共用,你不需要为每个线程创建独立的Channel,也不需要用锁互斥。不过Channel的创建和Init并不是线程安全的,请确保在Init成功后再被多线程访问,在没有线程访问后再析构

三、初始化channel options

填充连接相关的的参数如超时、协议、最大重试次数、负载均衡算法等

四、channel init with options

初始化channel

五、初始化自定义service_stub

protobuf会为我们定义的rpc 函数生成一个xxx_stub用来和服务交互。我们需要用自定义service_stub初始化我们的客户端对象。如果proto没定义rpc 服务,可以用Channel.CallMethod。

六、发起访问

一般来说,我们不直接调用Channel.CallMethod,而是通过protobuf生成的桩XXX_Stub,过程更像是“调用函数”。stub内没什么成员变量,建议在栈上创建和使用,而不必new,当然你也可以把stub存下来复用。Channel::CallMethod和stub访问都是线程安全的,可以被所有线程同时访问。
XXX_Stub stub(&channel);
stub.some_method(controller, request, response, done);
这里的some_method为在proto中定义的rpc服务经过编译后得到的抽象接口,像service_stub.ParallelSearchPlans。
如果我们没定义rpc服务,用brpc内部已定义好的服务时,需要用到callmethod()发起请求。而我们可以通过addchannel组装多个请求,一次调用,可以用在提升服务的性能。下面是一个实际示例

while (request_num--) {pchan.AddChannel(channel, baidu::rpc::DOESNT_OWN_CHANNEL, rpc_call_mapper, rpc_response_merger);}uint64_t logid = UII_GET_LOGID();cntl->set_log_id(logid);AccessLogGuard access_log_guard(service_name.c_str(), "nshead", req, res, cntl);pchan.CallMethod(NULL, cntl, req, res, baidu::rpc::DoNothing());if (cntl->Failed()) {UII_LOG_WARNING("Fail to access service:%s Error:%s", service_name.c_str(), cntl->ErrorText().c_str());return -1;}

上面代码使用rpc::DoNothing()实现了一个半同步的请求响应,阻塞到所有的请求返回。

七、返回处理

我们发起访问后,可以根据controler调用cntl->Failed()判断请求是否成功。若成功,就可以对res响应进行处理。

八、基础客户端案例及释义

// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.// A client sending requests to server every 1 second.#include <gflags/gflags.h>
#include <butil/logging.h>
#include <butil/time.h>
#include <brpc/channel.h>
#include "echo.pb.h"DEFINE_string(attachment, "", "Carry this along with requests");
DEFINE_string(protocol, "baidu_std", "Protocol type. Defined in src/brpc/options.proto");
DEFINE_string(connection_type, "", "Connection type. Available values: single, pooled, short");
DEFINE_string(server, "0.0.0.0:8000", "IP Address of server");
DEFINE_string(load_balancer, "", "The algorithm for load balancing");
DEFINE_int32(timeout_ms, 100, "RPC timeout in milliseconds");
DEFINE_int32(max_retry, 3, "Max retries(not including the first RPC)"); 
DEFINE_int32(interval_ms, 1000, "Milliseconds between consecutive requests");int main(int argc, char* argv[]) {// Parse gflags. We recommend you to use gflags as well.GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true);brpc::Channel channel;// Initialize the channel, NULL means using default options.brpc::ChannelOptions options;options.protocol = FLAGS_protocol;options.connection_type = FLAGS_connection_type;options.timeout_ms = FLAGS_timeout_ms/*milliseconds*/;options.max_retry = FLAGS_max_retry;if (channel.Init(FLAGS_server.c_str(), FLAGS_load_balancer.c_str(), &options) != 0) {LOG(ERROR) << "Fail to initialize channel";return -1;}// Normally, you should not call a Channel directly, but instead construct// a stub Service wrapping it. stub can be shared by all threads as well.example::EchoService_Stub stub(&channel);// Send a request and wait for the response every 1 second.int log_id = 0;while (!brpc::IsAskedToQuit()) {// We will receive response synchronously, safe to put variables// on stack.example::EchoRequest request;example::EchoResponse response;brpc::Controller cntl;request.set_message("hello world");cntl.set_log_id(log_id ++);  // set by user// Set attachment which is wired to network directly instead of // being serialized into protobuf messages.cntl.request_attachment().append(FLAGS_attachment);// Because `done'(last parameter) is NULL, this function waits until// the response comes back or error occurs(including timedout).stub.Echo(&cntl, &request, &response, NULL);if (!cntl.Failed()) {LOG(INFO) << "Received response from " << cntl.remote_side()<< " to " << cntl.local_side()<< ": " << response.message() << " (attached="<< cntl.response_attachment() << ")"<< " latency=" << cntl.latency_us() << "us";} else {LOG(WARNING) << cntl.ErrorText();}usleep(FLAGS_interval_ms * 1000L);}LOG(INFO) << "EchoClient is going to quit";return 0;
}

http://www.ppmy.cn/news/1228438.html

相关文章

【Go学习之 go mod】gomod小白入门,在github上发布自己的项目(项目初始化、项目发布、项目版本升级等)

参考 Go语言基础之包 | 李文周的博客Go mod的使用、发布、升级 | weiGo Module如何发布v2及以上版本1.2.7. go mod命令 — 新溪-gordon V1.7.9 文档golang go 包管理工具 go mod的详细介绍-腾讯云开发者社区-腾讯云Go Mod 常见错误的原因 | walker的博客 项目案例 oceanweav…

3-docker安装centos7

CentOS7.9下安装完成docker后&#xff0c;后续我们可以在其上安装centos7系统。具体操作如下&#xff1a; 1.以root用户登录CentOS7.9服务器&#xff0c;拉取centos7 images 命令&#xff1a; docker pull centos:centos7 2.加载centos7 images并登录验证 命令&#xff1a;…

【C++】【Opencv】cv::Canny()边缘检测函数详解和示例

Canny边缘检测是一种流行的边缘检测算法&#xff0c;由John F. Canny在1986年开发。它是一种多阶段过程&#xff0c;包括噪声滤波、计算图像强度的梯度、非最大值抑制以及双阈值检测。本文通过函数原型解读和示例对cv::Canny()函数进行详解&#xff0c;以帮助大家理解和使用。 …

计算机毕业设计 基于SpringBoot的健身房管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解目录

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

慢日志查询

概述 MySQL的慢查询日志是MySQL提供的一种日志记录&#xff0c;它用来记录在MySQL中响应时间超过阀值的语句&#xff0c;具体指运行时间超过 long_query_time 值的SQL&#xff0c;则会被记录到慢查询日志中&#xff0c;ong_query_time 的默认值为 10&#xff0c;意思是运行10S…

面试资料快速复习 Git常用命令(简单实用)

Git-command Git常用命令、面试复习、简单实用命令 ​ 一、概念理解 &#xff08;一&#xff09;工作区、暂存区、本地仓库、远程仓库 workspace&#xff1a;工作区staging area&#xff1a;暂存区/缓存区local repository&#xff1a;本地仓库remote repository&#xff…

PTA 7-6 数据类型判断(c++)

从键盘分别输入通过空格分割的整型(int)、浮点型(double)、字符型(String)、布尔型(boolean)&#xff0c;根据读取的内容判断他们的类型并将他们解析为正确的对象&#xff0c;并都放到一个数组中。输出各个对象的类型 输入格式: 字符串 输出格式: 数据类型 输入样例: 在这…

ARouter出现 there‘s no route matched in group问题排查

在使用ARouter时候会出现找不到映射路径的问题&#xff0c;这里给兄弟们总结下踩过的坑 所有用到的模块都要有填写依赖 android {defaultConfig {......javaCompileOptions {annotationProcessorOptions {arguments [AROUTER_MODULE_NAME: project.getName()]}}} } ... depe…