brpc学习笔记(1)

文章目录

    • 一、简介及各个文档学习
      • 1.1 bvar
      • 1.2 bthread
      • 1.3 client
      • 1.4 server
      • 1.5 内置服务
      • 1.6 工具
    • 参考

一、简介及各个文档学习

brpc是一款RPC框架,基于brpc可以在一个端口上搭建支持多种协议的服务。

编译按照文档编译即可,编译完成后需要将output目录下的拷贝到对应的系统目录:

cp -r bin/* /usr/bin
cp -r include/*  /usr/include
cp -r lib/*  /usr/lib

1.1 bvar

  • bvar是多线程环境下的计数器类库,方便统计和查看用户程序中的各类数值(例如qps、平均延时等等),使用thread_local减少了cache bouncing。brpc集成了该模块,因此需要在多线程环境中计数的场景可以第一时间考虑bvar,但是由于分散了数据,读时整合会速度会慢一些,因此读写很频繁时和需要最新值的场景不适合使用。
  • cache bouncing:由于缓存一致性,某个CPU更改了某个cache中的数值后,会通过缓存一致性协议将消息同步给其他存放了该数据的核,以使得各个核的缓存数据一致,由于缓存一致通常由硬件锁实现,因此存在隐性的全局竞争。因此多线程情况下,变量要尽可能的按访问规律排列,频繁被其他线程修改的变量要放在独立的cacheline中,如果想让一个变量或者结构体按cacheline对齐,可以使用include中的BAIDU_CACHELINE_ALIGNMENT宏。
  • memory fence:保证了可见性的顺序,但并不保证可见性。单个的内存屏障无法保证可见性,只能保证顺序,但多个内存屏障的组合可以保证可见性。
  • volatile:借助memory fence保证了可见性,但不保证原子性。(java的,c++好像没有借助内存屏障,了解不多),等详细学习参考再补充
  • wait-free:不管CPU如何调度,每个线程都始终在做有用的事
  • lock-free:不管CPU如何调度,都至少有一个线程在做有用的事

bvar解决的问题主要是以提高读延迟为代价来提供对性能影响较小的多线程数据统计。

使用方法:
当brpc启动后会绑定一个http端口,可以通过浏览器来访问查看bvar。

  • /vars:列出所有暴露的bvar
  • /vars/NAME:查询名字为NAME的bvar
  • /vars/xxx*xx$r:查询名字与模式匹配的bvar

内置的bvar:

process_context_switches_involuntary_second : 14
process_context_switches_voluntary_second : 15760
process_cpu_usage : 0.428
process_cpu_usage_system : 0.142
process_cpu_usage_user : 0.286
process_disk_read_bytes_second : 0
process_disk_write_bytes_second : 260902
process_faults_major : 256
process_faults_minor_second : 14
process_memory_resident : 392744960
system_core_count : 12
system_loadavg_15m : 0.040
system_loadavg_1m : 0.000
system_loadavg_5m : 0.020

bthread_switch_second : 20422
bthread_timer_scheduled_second : 4
bthread_timer_triggered_second : 4
bthread_timer_usage : 2.64987e-05
bthread_worker_count : 13
bthread_worker_usage : 1.33733
bvar_collector_dump_second : 0
bvar_collector_dump_thread_usage : 0.000307385
bvar_collector_grab_second : 0
bvar_collector_grab_thread_usage : 1.9699e-05
bvar_collector_pending_samples : 0
bvar_dump_interval : 10
bvar_revision : "34975"
bvar_sampler_collector_usage : 0.00106495
iobuf_block_count : 89
iobuf_block_count_hit_tls_threshold : 0
iobuf_block_memory : 729088
iobuf_newbigview_second : 10

1.2 bthread

  • bthread是brpc使用的线程库,目的是提高程序并发度,降低并发程序的编写难度,提供更好的缓存局部性,使用的是M:N模型,即M个bthread会映射到N个pthread,相当于映射到N个LWP(个人理解就是Linux中的线程实现),有些类似go调度模型中的P
  • ExecutionQueue:基于bthread实现的任务队列,提供异步串行执行的功能,提交任务的接口是wait-free的。
  • 最好不要将业务数据定义为线程级别的,因为bthread在执行时,若阻塞会转换pthread,因此转换之后,线程变了,再去访问变量的结果是未定义的。
  • 如果仅仅是为了并发rpc请求,使用bthread效果不如直接使用brpc提供的异步接口,因为会增加创建bthread的开销,同时bthread在等待rpc请求的过程中会阻塞。

1.3 client

  • brpc中使用channel表示一台或一组服务器的交互通道,而没有具体的Client类。Channel的使用是线程安全的,但是需要注意Channel的创建和初始化不是线程安全的。
  • channel的部分全局配置存放在gflags中,其他设置到ChannelOptions中
  • Channel的连接单台机器的 init 需要传入连接的目标ip以及port和ChannelOptions,连接集群的需要传入注册中心的地址(为了获取目标服务器列表)以及负载策略(当为空时相当于连接单机)和ChannelOptions
  • client一共可通过三个渠道来获取配置:全局gflags、ChannelOptions(仅用于初始化Channel)、Controller,Controller用于覆盖Options中的配置,每个Controller仅在一次RPC过程中有效,其是线程不安全的。另外如果异步RPC,本次RPC使用的Controller需要创建在堆上new出来,然后在done回调中delete。
  • 客户端没有专门的线程池,所有的Channel和Server通过bthread共享线程池
  • 客户端可以通过set_log_id()设置一个64位的整型id,该id会随请求送到服务端打印到日志中,因此可以通过一次检索把所有的服务串联起来。

parallelChannel

在同时发起大量RPC的情况下,用户只能选择以同步或者异步其中之一的方式来编写代码,接口无法统一,且往往不容易取消以及不能轻松的扩展。

因此,brpc提供了parallelChannel,其会同时访问其包含的子channel,并合并它们的结果。采用了MapReuce的思想。

SelectiveChannel

该channel的初始化类似与普通的channel,仅仅是不需要注册中心地址。会按照负载均衡算法将流量输送到各个子channel;

例如有几组提供相同功能的服务挂载到不同注册中心中,可以在client建立对应的几组channel,然后将这些channel加入到一个selectiveChannel中,schan会均衡的将这些流量分发到各个组。

partionChannel

parallelChannel的特例。可以根据命名服务的tag服务来区分sub channel,这样提供相同功能的几组服务的元信息可以注册到同一个注册中心中,以tag来区分。

DynamicPartitionChannel

支持动态选择子channel

streamingRpc

某些场景,需要传输的数据量比较大,如果并行,无法保证顺序,如果串行,则每次传递都需要等待一次网络RTT以及处理数据的延迟,因此提供流水线式的RPC

demo:example/streaming_echo_c++

dummy_server

当仅仅使用client端的功能或未使用brpc,如果想使用brpc的内置服务,此时在程序中启动一个空的server即可,这种server即dummy server,例如想使用bvar。

1.4 server

  • brpc是基于protobuf rpc来构建的,因此首先需要在.proto文件中定义service,然后继承Protobuf生成的Service类,重写对应的方法,最后通过AddService加入到Server中对外暴露。

1.5 内置服务

内置服务以多种形式展现服务器内部的状态。

主要服务:

  • /status:显示所有服务的主要状态
  • /vars: 显示各种统计指标
  • /connections: 所有连接的统计信息
  • flags: 所有全局配置 gflags 的状态,可动态修改
  • rpcz:查看所有rpc的细节
  • cpu profiler:分析cpu热点
  • heap profiler:分析内存占用
  • contention profiler:分析锁竞争
  • /version: 查看服务器版本
  • /health: 存活探针,健康检查
  • /protobufs: 查看程序所有的protobuf结构体
  • /vlog: 查看程序当前开启的VLOG
  • /dir:浏览服务器上的所有文件
  • /threads: 查看进程内所有线程的运行情况

1.6 工具

  • rpc_press:压测
  • rpc_replay:用于回放存在特定文件中的一些rpc请求
  • rpc_view: 转发端口被限的server的内置服务
  • benchmark_http
  • parallel_http

参考

Linux下配置Vscode环境
GDB基本使用方式
GDB添加断点方式
c++ volatile关键字深度剖析
常见线程模型

你可能感兴趣的:(#,rpc,rpc)