专栏首页C++开源框架源码分析GRPC-C++源码分析(三)--main线程
原创

GRPC-C++源码分析(三)--main线程

如果没有特殊喜好,推荐从example/cpp/helloworld/greeter_server.cc开始阅读。前期分析的是同步部分的代码。

1 BuildAndStart

ServerBuilder::BuildAndStart()是main线程一切的开端,这里会列出其中重要的代码段并简单阐述。

1.1 初始化ServerCompletionQueue

  std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
      sync_server_cqs(std::make_shared<
                      std::vector<std::unique_ptr<ServerCompletionQueue>>>());

…………

  if (has_sync_methods) {
    grpc_cq_polling_type polling_type =
        is_hybrid_server ? GRPC_CQ_NON_POLLING : GRPC_CQ_DEFAULT_POLLING;

    // Create completion queues to listen to incoming rpc requests
    for (int i = 0; i < sync_server_settings_.num_cqs; i++) {
      sync_server_cqs->emplace_back(
          new ServerCompletionQueue(GRPC_CQ_NEXT, polling_type, nullptr));
    }
  }
  • 创建了ServerCompletionQueue(简写为scq)类型的vector sync_server_cqs,并初始化了具体类型的scq
  • scq是同步server中非常重要的角色。ServerCompletionQueue可以有多个,它们用来监听外界的请求。还记得第一章中的网络模型,同一个listenfd被分配到了多个epoll中么?那些epoll就在ServerCompletionQueue中。
  • 创建了default-executor和resolver-executor线程,等待任务到来

1.2 创建Server

  std::unique_ptr<Server> server(new Server(
      max_receive_message_size_, &args, sync_server_cqs,
      sync_server_settings_.min_pollers, sync_server_settings_.max_pollers,
      sync_server_settings_.cq_timeout_msec, resource_quota_,
      std::move(interceptor_creators_)));

Server的构造函数中干了两件事儿:

  • 根据sync_server_cqs中的scq个数创建了数目等同的SyncRequestThreadManager(第二章中出现过这个名字),并将scq的指针放到了其中,后面有大用处
  • 创建了grpc_server* server_,它才是Server中真正干活的人

1.3 将sync_server_cqs指针放到server_

  for (auto it = cqs_.begin(); it != cqs_.end(); ++it) {
    grpc_server_register_completion_queue(server->server_, (*it)->cq(),
                                          nullptr);
  }

确切的说,是将sync_server_cqs中的每个scq中的cq_变量放到_server中的grpc_completion_queue** cqs数组中

1.4 注册具体service

  for (auto service = services_.begin(); service != services_.end();
       service++) {
    if (!server->RegisterService((*service)->host.get(), (*service)->service)) {
      return nullptr;
    }
  }

这块代码在第二章线程模型的DoWork中会被用到

1.5 bind和listen

  bool added_port = false;
  for (auto port = ports_.begin(); port != ports_.end(); port++) {
    int r = server->AddListeningPort(port->addr, port->creds.get());
    if (!r) {
      if (added_port) server->Shutdown();
      return nullptr;
    }
    added_port = true;
    if (port->selected_port != nullptr) {
      *port->selected_port = r;
    }
  }

AddListeningPort方法的实际入口在InsecureServerCredentialsImpl类中,执行了bind和listen操作

1.6 server->Start

  auto cqs_data = cqs_.empty() ? nullptr : &cqs_[0];
  server->Start(cqs_data, cqs_.size());
  • 将start_listener任务放到default-executor线程中,创建epoll,注册listen描述符,注册accept描述符
  • 启动SyncRequestThreadManager线程,进入epoll_wait等待,响应读写事件
  • 在SyncRequestThreadManager中处理1.4节中注册的service业务逻辑

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • GRPC-C++源码分析(九)--Server

    对应《GRPC-C++源码分析(三)--main线程》中的1.2节 创建Server

    路小饭
  • GRPC-C++源码分析(十一)--bind&listen

    路小饭
  • GRPC-C++源码分析(十二)--Start

    这一节可能才是最核心的部分,包括大家理解的怎样注册listen和accept描述符,怎样处理读写事件,怎样处理业务逻辑等等。

    路小饭
  • 集群限流

    基于sentine-1.4.2,在dashboard想要更好的查看集群限流相关配置,需要一些小修改

    spilledyear
  • 解码Redis最易被忽视的CPU和内存占用高问题

    作者介绍 张鹏义,腾讯云数据库高级工程师,曾参与华为Taurus分布式数据研发及腾讯CynosDB for PG研发工作,现从事腾讯云Redis数据库研发工...

    腾讯云数据库 TencentDB
  • 解码Redis最易被忽视的CPU和内存占用高问题

    张鹏义,腾讯云数据库高级工程师,曾参与华为Taurus分布式数据研发及腾讯CynosDB for pg研发工作,现从事腾讯云Redis数据库研发工作。

    jeanron100
  • 详解 RestTemplate 操作

    作为开发人员,我们经常关注于构建伟大的软件来解决业务问题。数据只是软件完成工作时  要处理的原材料。但是如果你问一下业务人员,数据和软件谁更重要的话,他们很可...

    业余草
  • 通用AlphaGo诞生?DeepMind的MuZero在多种棋类游戏中超越人类

    MuZero 算法在国际象棋、日本将棋、围棋和雅达利(Atari)游戏训练中的评估结果。横坐标表示训练步骤数量,纵坐标表示 Elo评分。黄色线代表 AlphaZ...

    机器之心
  • 中秋快乐版二维码生成器实现v1.2

           大家好,今天就继续昨天做的二维码生成器,再这基础之上增加了扫描功能,加入了欢迎页,在生成的EditText中加入了判断,如果内容为空就抖动Edit...

    IT大飞说
  • 从FBNetv1到FBNetV3:一文看懂Facebook在NAS领域的轻量级网络探索

    FBNet系列是完全基于NAS方法的轻量级网络系列,分析当前搜索方法的缺点,逐步增加创新性改进,FBNet结合了DNAS和资源约束,FBNetV2加入了chan...

    Amusi

扫码关注云+社区

领取腾讯云代金券