📄️ 使用krpc
安装krpc基础环境以及编译krpc.
📄️ 服务开发
示例程序
📄️ http服务
这里指我们通常说的http/h2服务,而不是可通过http/h2访问的pb服务。
📄️ Thrift服务
thrift是应用较广的RPC框架,最初由Facebook发布,后交由Apache维护。为了和thrift服务互通,
📄️ CPU使用分析
krpc可以分析程序中的热点函数。
📄️ 堆栈分析
krpc可以分析内存是被哪些函数占据的。heap profiler的原理是每分配满一些内存就采样调用处的栈,“一些”由环境变量TCMALLOCSAMPLEPARAMETER控制,默认524288,即512K字节。根据栈表现出的函数调用关系汇总为我们看到的结果图。在实践中heap profiler对原程序的影响不明显。
📄️ 竞态分析
krpc可以分析花在等待锁上的时间及发生等待的函数。
📄️ server dummy
如果你的程序只使用了krpc的client或根本没有使用krpc,但你也想使用krpc的内置服务,只要在程序中启动一个空的server就行了,这种server我们称为dummy server。
📄️ rpc追踪
用户能通过/rpcz看到最近请求的详细信息,并可以插入注释(annotation),不同于tracing system(如dapper)以全局视角看到整体系统的延时分布,rpcz更多是一个调试工具,虽然角色有所不同,但在krpc中rpcz和tracing的数据来源是一样的。当每秒请求数小于1万时,rpcz会记录所有的请求,超过1万时,rpcz会随机忽略一些请求把采样数控制在1万左右。rpcz可以淘汰时间窗口之前的数据,通过-spankeepingseconds选项设置,默认1小时。一个长期运行的例子。
📄️ thread local
本页说明kthread下使用pthread-local可能会导致的问题。kthread-local的使用方法见这里。
📄️ json和protobuf转换
krpc支持json和protobuf间的双向转化,实现于json2pb,json解析使用rapidjson。此功能对pb2.x和3.x均有效。pb3内置了转换json的功能。
📄️ 常见线程模型
连接独占线程或进程
📄️ atomic使用
我们都知道多核编程常用锁避免多个线程在修改同一个数据时产生race condition。当锁成为性能瓶颈时,我们又总想试着绕开它,而不可避免地接触了原子指令。但在实践中,用原子指令写出正确的代码是一件非常困难的事,琢磨不透的race condition、ABA problem、memory fence很烧脑,这篇文章试图通过介绍SMP架构下的原子指令帮助大家入门。C++11正式引入了原子指令,我们就以其语法描述。
📄️ flags使用
krpc使用gflags管理配置。如果你的程序也使用gflags,那么你应该已经可以修改和krpc相关的flags,你可以浏览flags服务了解每个flag的具体功能。如果你的程序还没有使用gflags,我们建议你使用,原因如下:
📄️ IO详解
一般有三种操作IO的方式:
📄️ 流式rpc
在一些应用场景中, client或server需要向对面发送大量数据,这些数据非常大或者持续地在产生以至于无法放在一个RPC的附件中。比如一个分布式系统的不同节点间传递replica或snapshot。client/server之间虽然可以通过多次RPC把数据切分后传输过去,但存在如下问题:
📄️ EndPoint工具类
UDS及IPV6支持
📄️ kumo标准协议
kumo_std是一种基于TCP协议的二进制RPC通信协议。它以Protobuf作为基本的数据交换格式,并基于Protobuf内置的RPC Service形式,规定了通信双方之间的数据交换协议,以实现完整的RPC调用。
📄️ 客户端服务
事实速查
📄️ 熔断功能
当我们发起一个rpc之后,krpc首先会从命名服务(naming service)拿到一个可用节点列表,之后根据负载均衡策略挑选出一个节点作为实际访问的节点。当某个节点出现故障时,krpc能够自动将它从可用节点列表中剔除,并周期性的对故障节点进行健康检查。
📄️ connections服务
connections服务可以查看所有的连接。一个典型的页面如下:
📄️ lalb调度
LALB全称Locality-aware load balancing,是一个能把请求及时、自动地送到延时最低的下游的负载均衡算法,特别适合混合部署环境。该算法产生自DP系统,现已加入krpc!
📄️ 一致性hash
一些场景希望同样的请求尽量落到一台机器上,比如访问缓存集群时,我们往往希望同一种请求能落到同一个后端上,以充分利用其上已有的缓存,不同的机器承载不同的稳定working set。而不是随机地散落到所有机器上,那样的话会迫使所有机器缓存所有的内容,最终由于存不下形成颠簸而表现糟糕。 我们都知道hash能满足这个要求,比如当有n台服务器时,输入x总是会发送到第hash(x) % n台服务器上。但当服务器变为m台时,hash(x) % n和hash(x) % m很可能都不相等,这会使得几乎所有请求的发送目的地都发生变化,如果目的地是缓存服务,所有缓存将失效,继而对原本被缓存遮挡的数据库或计算服务造成请求风暴,触发雪崩。一致性哈希是一种特殊的哈希算法,在增加服务器时,发向每个老节点的请求中只会有一部分转向新节点,从而实现平滑的迁移。这篇论文中提出了一致性hash的概念。
📄️ http客户端
example/httpc++
📄️ http延展阅读
http/h2协议的基本用法见httpclient和httpservice
📄️ 服务治理
随着服务规模的增大,对下游的访问流程会越来越复杂,其中往往包含多个同时发起的RPC或有复杂的层次结构。但这类代码的多线程陷阱很多,用户可能写出了bug也不自知,复现和调试也比较困难。而且实现要么只能支持同步的情况,要么得为异步重写一套。以"在多个异步RPC完成后运行一些代码"为例,它的同步实现一般是异步地发起多个RPC,然后逐个等待各自完成;它的异步实现一般是用一个带计数器的回调,每当一个RPC完成时计数器减一,直到0时调用回调。可以看到它的缺点:
📄️ memcached客户端
memcached是常用的缓存服务,为了使用户更快捷地访问memcached并充分利用kthread的并发能力,krpc直接支持memcache协议。示例程序:example/memcachec++
📄️ redis支持
redis是最近几年比较火的缓存服务,相比memcached在server端提供了更多的数据结构和操作方法,简化了用户的开发工作。为了使用户更快捷地访问redis并充分利用kthread的并发能力,krpc直接支持redis协议。示例程序:example/redisc++
📄️ 自适应限流
服务的处理能力是有客观上限的。当请求速度超过服务的处理速度时,服务就会过载。
📄️ rpc调试
1.检查工作线程的数量