Brpc 学习(二)基本 echo 服务器与并发版本实现

 
Category: brpc

写在前面

学习一个框架, 首先是要去安装, 跑通这个框架的基本测试用例, 这次尝试搞一下 echo 服务器, 以及并发版本的实现, 这些例子在 brpc 代码库的example/目录下都有, 其实主要需要关注的就是echo_c++, multithread-echo_c++streaming-echo_c++ 这三个例子, 包括了主要的 brpc 使用场景, 下面分别分析一下.

前置知识

gflags

是一个 Google 开源的命令行参数解析库, 默认采用长格式, brpc 中主要的命令行参数解析任务都是通过这个库实现的.

这里先提几个概念, 在一个主要的命令行程序调用过程中, 有下面几个术语, 看这个例子: (参考了 gflags 的文档, 位于gflags/doc/index.html)

fgrep -l -f /var/tmp/foo johannes brahms
  1. 命令command, 即fgrep
  2. 选项option, 即-l 和-f, 其中-l 是不带参数的选项, -f 带有一个参数
  3. 参数 argument, 即-f 选项后面的值, 通过空格分割, 后面的johannes和brahms都是 fgrep 命令的参数

这里跑一下官方代码库中的实例, 即test/config/main.cc文件, 这里我改动了一下, 方便熟悉功能.

#include <gflags/gflags.h>
#include <iostream>
// 通过宏定义的方式设置要解析的参数, 下面的例子中, message 为选项的名称, 源码文件中`FLAGS_message`为具体的值, 第三个参数为描述信息, 在之后的`--help`中提到了
DEFINE_string(message, "Hello World!", "The message to print");

static bool ValidateMessage(const char *flagname, const std::string &message) {
  if (!message.empty()) {
    return true;
  }
  printf("error, empty msg\n");
  return false;
}

DEFINE_validator(message, ValidateMessage);

int main(int argc, char **argv) {
  gflags::SetUsageMessage(
      "Test CMake configuration of gflags library (gflags-config.cmake)");
  gflags::SetVersionString("0.1");
  gflags::ParseCommandLineFlags(&argc, &argv, true);
  std::cout << FLAGS_message << std::endl;
  gflags::ShutDownCommandLineFlags();
  return 0;
}

结果发现直接用 cmake 竟然报错了, 发现 cmake 文件最后一行: target_link_libraries (foo gflags::gflags) 出了问题, 应该是: target_link_libraries (foo gflags).

构建一下:

mkdir build
cd build
cmake ..
make 

测试一下:

 ==> ./foo
Hello World!
 ==> ./foo --message=hello
hello

 ==> ./foo --message world
world

 ==> ./foo --message
ERROR: flag '--message' is missing its argument; flag description: The message to print

 ==> ./foo --message ""
error, empty msg
ERROR: failed validation of new value '' for flag 'message'

--help可以打印全部参数信息: (但是不太准确, 一堆冗余信息)

 ==> ./foo --help
foo: Test CMake configuration of gflags library (gflags-config.cmake)

  Flags from /Users/hep/code/c-cpp_Proj/gflags/test/config/main.cc:
    -message (The message to print) type: string default: "Hello World!" # 这里显示了描述信息以及选项的默认值



  Flags from /tmp/gflags-20211021-3963-1mi18ai/gflags-2.2.2/src/gflags.cc:
    -flagfile (load flags from file) type: string default: ""
    -fromenv (set flags from the environment [use 'export FLAGS_flag1=value'])
      type: string default: ""
    -tryfromenv (set flags from the environment if present) type: string
      default: ""
    -undefok (comma-separated list of flag names that it is okay to specify on
      the command line even if the program does not define a flag with that
      name.  IMPORTANT: flags in this list that have arguments MUST use the
      flag=value format) type: string default: ""

  Flags from /tmp/gflags-20211021-3963-1mi18ai/gflags-2.2.2/src/gflags_completions.cc:
    -tab_completion_columns (Number of columns to use in output for tab
      completion) type: int32 default: 80
    -tab_completion_word (If non-empty, HandleCommandLineCompletions() will
      hijack the process and attempt to do bash-style command line flag
      completion on this value.) type: string default: ""

  Flags from /tmp/gflags-20211021-3963-1mi18ai/gflags-2.2.2/src/gflags_reporting.cc:
    -help (show help on all flags [tip: all flags can have two dashes])
      type: bool default: false currently: true
    -helpfull (show help on all flags -- same as -help) type: bool
      default: false
    -helpmatch (show help on modules whose name contains the specified substr)
      type: string default: ""
    -helpon (show help on the modules named by this flag value) type: string
      default: ""
    -helppackage (show help on all modules in the main package) type: bool
      default: false
    -helpshort (show help on only the main module for this program) type: bool
      default: false
    -helpxml (produce an xml version of help) type: bool default: false
    -version (show version and build info and exit) type: bool default: false

bthread

brpc 内置的线程库, 其实就是对 Pthread 的一个封装, 但是改变了 Pthread 中用户级线程和系统级(核心级)线程的一一对应, 改成了 M:N 的关系, 这样应该能让线程切换的效率提高, 具体这里就不深究了, 文档的brpc in Depth部分有提到.

protobuf

版本就是构建 brpc 时候所用的版本, 即21.12. 目前最新版 24 brpc 并不支持

这个是 Google 的 grpc 库中数据交换的基本格式, 其实就是对 C 的基本数据类型的一层封装, 使得数据可以以规定好的二进制格式传输, 提高了空间利用率, 简单熟悉一下这个格式:

基本的 echo 服务器

其实跟传统的echo没啥太大区别