diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 937cacb8dd..a458f38611 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ -If you meet any problem or request a new feature, you're welcome to [create an issue](https://github.com/brpc/brpc/issues/new/choose). +If you meet any problem or request a new feature, you're welcome to [create an issue](https://github.com/apache/brpc/issues/new/choose). -If you can solve any of [the issues](https://github.com/brpc/brpc/issues), you're welcome to send the PR to us. +If you can solve any of [the issues](https://github.com/apache/brpc/issues), you're welcome to send the PR to us. Before the PR: @@ -14,9 +14,9 @@ After the PR: # Chinese version -如果你遇到问题或需要新功能,欢迎[创建issue](https://github.com/brpc/brpc/issues/new/choose)。 +如果你遇到问题或需要新功能,欢迎[创建issue](https://github.com/apache/brpc/issues/new/choose)。 -如果你可以解决某个[issue](https://github.com/brpc/brpc/issues), 欢迎发送PR。 +如果你可以解决某个[issue](https://github.com/apache/brpc/issues), 欢迎发送PR。 发送PR前请确认: diff --git a/README.md b/README.md index b748a0c1e3..8e28c8500b 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ You can use it to: * Build a server that can talk in multiple protocols (**on same port**), or access all sorts of services * restful http/https, [h2](https://http2.github.io/http2-spec)/[gRPC](https://grpc.io). using http/h2 in brpc is much more friendly than [libcurl](https://curl.haxx.se/libcurl/). Access protobuf-based protocols with HTTP/h2+json, probably from another language. * [redis](docs/en/redis_client.md) and [memcached](docs/en/memcache_client.md), thread-safe, more friendly and performant than the official clients. - * [rtmp](https://github.com/brpc/brpc/blob/master/src/brpc/rtmp.h)/[flv](https://en.wikipedia.org/wiki/Flash_Video)/[hls](https://en.wikipedia.org/wiki/HTTP_Live_Streaming), for building [streaming services](https://github.com/brpc/media-server). + * [rtmp](https://github.com/apache/brpc/blob/master/src/brpc/rtmp.h)/[flv](https://en.wikipedia.org/wiki/Flash_Video)/[hls](https://en.wikipedia.org/wiki/HTTP_Live_Streaming), for building [streaming services](https://github.com/brpc/media-server). * hadoop_rpc (may be opensourced) * [rdma](https://en.wikipedia.org/wiki/Remote_direct_memory_access) support (will be opensourced) * [thrift](docs/en/thrift.md) support, thread-safe, more friendly and performant than the official clients. @@ -28,7 +28,7 @@ You can use it to: # Try it! * Read [overview](docs/en/overview.md) to know where brpc can be used and its advantages. -* Read [getting started](docs/cn/getting_started.md) for building steps and play with [examples](https://github.com/brpc/brpc/tree/master/example/). +* Read [getting started](docs/cn/getting_started.md) for building steps and play with [examples](https://github.com/apache/brpc/tree/master/example/). * Docs: * [Performance benchmark](docs/cn/benchmark.md) * [bvar](docs/en/bvar.md) diff --git a/README_cn.md b/README_cn.md index 43b932119e..850123c22d 100644 --- a/README_cn.md +++ b/README_cn.md @@ -13,7 +13,7 @@ brpc是用c++语言编写的工业级RPC框架,常用于搜索、存储、机 * 搭建能在**一个端口**支持多协议的服务, 或访问各种服务 * restful http/https, [h2](https://http2.github.io/http2-spec)/[gRPC](https://grpc.io)。使用brpc的http实现比[libcurl](https://curl.haxx.se/libcurl/)方便多了。从其他语言通过HTTP/h2+json访问基于protobuf的协议. * [redis](docs/cn/redis_client.md)和[memcached](docs/cn/memcache_client.md), 线程安全,比官方client更方便。 - * [rtmp](https://github.com/brpc/brpc/blob/master/src/brpc/rtmp.h)/[flv](https://en.wikipedia.org/wiki/Flash_Video)/[hls](https://en.wikipedia.org/wiki/HTTP_Live_Streaming), 可用于搭建[流媒体服务](https://github.com/brpc/media-server). + * [rtmp](https://github.com/apache/brpc/blob/master/src/brpc/rtmp.h)/[flv](https://en.wikipedia.org/wiki/Flash_Video)/[hls](https://en.wikipedia.org/wiki/HTTP_Live_Streaming), 可用于搭建[流媒体服务](https://github.com/brpc/media-server). * hadoop_rpc(可能开源) * 支持[rdma](https://en.wikipedia.org/wiki/Remote_direct_memory_access)(即将开源) * 支持[thrift](docs/cn/thrift.md) , 线程安全,比官方client更方便 @@ -28,7 +28,7 @@ brpc是用c++语言编写的工业级RPC框架,常用于搜索、存储、机 # 试一下! * 通过[概述](docs/cn/overview.md)了解哪里可以用brpc及其优势。 -* 阅读[编译步骤](docs/cn/getting_started.md)了解如何开始使用, 之后可以运行一下[示例程序](https://github.com/brpc/brpc/tree/master/example/). +* 阅读[编译步骤](docs/cn/getting_started.md)了解如何开始使用, 之后可以运行一下[示例程序](https://github.com/apache/brpc/tree/master/example/). * 文档: * [性能测试](docs/cn/benchmark.md) * [bvar](docs/cn/bvar.md) diff --git a/docs/cn/auto_concurrency_limiter.md b/docs/cn/auto_concurrency_limiter.md index cd36522c43..17ef5d7ec3 100644 --- a/docs/cn/auto_concurrency_limiter.md +++ b/docs/cn/auto_concurrency_limiter.md @@ -4,7 +4,7 @@ 如果服务持续过载,会导致越来越多的请求积压,最终所有的请求都必须等待较长时间才能被处理,从而使整个服务处于瘫痪状态。 -与之相对的,如果直接拒绝掉一部分请求,反而能够让服务能够"及时"处理更多的请求。对应的方法就是[设置最大并发](https://github.com/brpc/brpc/blob/master/docs/cn/server.md#%E9%99%90%E5%88%B6%E6%9C%80%E5%A4%A7%E5%B9%B6%E5%8F%91)。 +与之相对的,如果直接拒绝掉一部分请求,反而能够让服务能够"及时"处理更多的请求。对应的方法就是[设置最大并发](https://github.com/apache/brpc/blob/master/docs/cn/server.md#%E9%99%90%E5%88%B6%E6%9C%80%E5%A4%A7%E5%B9%B6%E5%8F%91)。 自适应限流能动态调整服务的最大并发,在保证服务不过载的前提下,让服务尽可能多的处理请求。 diff --git a/docs/cn/backup_request.md b/docs/cn/backup_request.md index fa7b236eee..6674fbf429 100644 --- a/docs/cn/backup_request.md +++ b/docs/cn/backup_request.md @@ -4,7 +4,7 @@ Channel开启backup request。这个Channel会先向其中一个server发送请求,如果在ChannelOptions.backup_request_ms后还没回来,再向另一个server发送。之后哪个先回来就取哪个。在设置了合理的backup_request_ms后,大部分时候只会发一个请求,对后端服务只有一倍压力。 -示例代码见[example/backup_request_c++](https://github.com/brpc/brpc/blob/master/example/backup_request_c++)。这个例子中,client设定了在2ms后发送backup request,server在碰到偶数位的请求后会故意睡眠20ms以触发backup request。 +示例代码见[example/backup_request_c++](https://github.com/apache/brpc/blob/master/example/backup_request_c++)。这个例子中,client设定了在2ms后发送backup request,server在碰到偶数位的请求后会故意睡眠20ms以触发backup request。 运行后,client端和server端的日志分别如下,“index”是请求的编号。可以看到server端在收到第一个请求后会故意sleep 20ms,client端之后发送另一个同样index的请求,最终的延时并没有受到故意sleep的影响。 @@ -41,6 +41,6 @@ my_func_latency << tm.u_elapsed(); // u代表微秒,还有s_elapsed(), m_elap # 当后端server不能挂在一个命名服务内时 -【推荐】建立一个开启backup request的SelectiveChannel,其中包含两个sub channel。访问这个SelectiveChannel和上面的情况类似,会先访问一个sub channel,如果在ChannelOptions.backup_request_ms后没返回,再访问另一个sub channel。如果一个sub channel对应一个集群,这个方法就是在两个集群间做互备。SelectiveChannel的例子见[example/selective_echo_c++](https://github.com/brpc/brpc/tree/master/example/selective_echo_c++),具体做法请参考上面的过程。 +【推荐】建立一个开启backup request的SelectiveChannel,其中包含两个sub channel。访问这个SelectiveChannel和上面的情况类似,会先访问一个sub channel,如果在ChannelOptions.backup_request_ms后没返回,再访问另一个sub channel。如果一个sub channel对应一个集群,这个方法就是在两个集群间做互备。SelectiveChannel的例子见[example/selective_echo_c++](https://github.com/apache/brpc/tree/master/example/selective_echo_c++),具体做法请参考上面的过程。 -【不推荐】发起两个异步RPC后Join它们,它们的done内是相互取消的逻辑。示例代码见[example/cancel_c++](https://github.com/brpc/brpc/tree/master/example/cancel_c++)。这种方法的问题是总会发两个请求,对后端服务有两倍压力,这个方法怎么算都是不经济的,你应该尽量避免用这个方法。 +【不推荐】发起两个异步RPC后Join它们,它们的done内是相互取消的逻辑。示例代码见[example/cancel_c++](https://github.com/apache/brpc/tree/master/example/cancel_c++)。这种方法的问题是总会发两个请求,对后端服务有两倍压力,这个方法怎么算都是不经济的,你应该尽量避免用这个方法。 diff --git a/docs/cn/bthread.md b/docs/cn/bthread.md index 3837ca8ab0..f0de58bcd7 100644 --- a/docs/cn/bthread.md +++ b/docs/cn/bthread.md @@ -1,4 +1,4 @@ -[bthread](https://github.com/brpc/brpc/tree/master/src/bthread)是brpc使用的M:N线程库,目的是在提高程序的并发度的同时,降低编码难度,并在核数日益增多的CPU上提供更好的scalability和cache locality。”M:N“是指M个bthread会映射至N个pthread,一般M远大于N。由于linux当下的pthread实现([NPTL](http://en.wikipedia.org/wiki/Native_POSIX_Thread_Library))是1:1的,M个bthread也相当于映射至N个[LWP](http://en.wikipedia.org/wiki/Light-weight_process)。bthread的前身是Distributed Process(DP)中的fiber,一个N:1的合作式线程库,等价于event-loop库,但写的是同步代码。 +[bthread](https://github.com/apache/brpc/tree/master/src/bthread)是brpc使用的M:N线程库,目的是在提高程序的并发度的同时,降低编码难度,并在核数日益增多的CPU上提供更好的scalability和cache locality。”M:N“是指M个bthread会映射至N个pthread,一般M远大于N。由于linux当下的pthread实现([NPTL](http://en.wikipedia.org/wiki/Native_POSIX_Thread_Library))是1:1的,M个bthread也相当于映射至N个[LWP](http://en.wikipedia.org/wiki/Light-weight_process)。bthread的前身是Distributed Process(DP)中的fiber,一个N:1的合作式线程库,等价于event-loop库,但写的是同步代码。 # Goals diff --git a/docs/cn/bvar.md b/docs/cn/bvar.md index 64e7475aa4..84ec443fa5 100644 --- a/docs/cn/bvar.md +++ b/docs/cn/bvar.md @@ -2,7 +2,7 @@ # 什么是bvar? -[bvar](https://github.com/brpc/brpc/tree/master/src/bvar/)是多线程环境下的计数器类库,支持[单维度bvar](bvar_c++.md)和[多维度mbvar](mbvar_c++.md),方便记录和查看用户程序中的各类数值,它利用了thread local存储减少了cache bouncing,相比UbMonitor(百度内的老计数器库)几乎不会给程序增加性能开销,也快于竞争频繁的原子操作。brpc集成了bvar,[/vars](vars.md)可查看所有曝光的bvar,[/vars/VARNAME](vars.md)可查阅某个bvar,在brpc中的使用方法请查看[vars](vars.md)。brpc大量使用了bvar提供统计数值,当你需要在多线程环境中计数并展现时,应该第一时间想到bvar。但bvar不能代替所有的计数器,它的本质是把写时的竞争转移到了读:读得合并所有写过的线程中的数据,而不可避免地变慢了。当你读写都很频繁或得基于最新值做一些逻辑判断时,你不应该用bvar。 +[bvar](https://github.com/apache/brpc/tree/master/src/bvar/)是多线程环境下的计数器类库,支持[单维度bvar](bvar_c++.md)和[多维度mbvar](mbvar_c++.md),方便记录和查看用户程序中的各类数值,它利用了thread local存储减少了cache bouncing,相比UbMonitor(百度内的老计数器库)几乎不会给程序增加性能开销,也快于竞争频繁的原子操作。brpc集成了bvar,[/vars](vars.md)可查看所有曝光的bvar,[/vars/VARNAME](vars.md)可查阅某个bvar,在brpc中的使用方法请查看[vars](vars.md)。brpc大量使用了bvar提供统计数值,当你需要在多线程环境中计数并展现时,应该第一时间想到bvar。但bvar不能代替所有的计数器,它的本质是把写时的竞争转移到了读:读得合并所有写过的线程中的数据,而不可避免地变慢了。当你读写都很频繁或得基于最新值做一些逻辑判断时,你不应该用bvar。 为了理解bvar的原理,你得先阅读[Cacheline这节](atomic_instructions.md#cacheline),其中提到的计数器例子便是bvar。当很多线程都在累加一个计数器时,每个线程只累加私有的变量而不参与全局竞争,在读取时累加所有线程的私有变量。虽然读比之前慢多了,但由于这类计数器的读多为低频的记录和展现,慢点无所谓。而写就快多了,极小的开销使得用户可以无顾虑地使用bvar监控系统,这便是我们设计bvar的目的。 diff --git a/docs/cn/client.md b/docs/cn/client.md index 076549fb75..3d03e73ccd 100755 --- a/docs/cn/client.md +++ b/docs/cn/client.md @@ -2,7 +2,7 @@ # 示例程序 -Echo的[client端代码](https://github.com/brpc/brpc/blob/master/example/echo_c++/client.cpp)。 +Echo的[client端代码](https://github.com/apache/brpc/blob/master/example/echo_c++/client.cpp)。 # 事实速查 @@ -13,7 +13,7 @@ Echo的[client端代码](https://github.com/brpc/brpc/blob/master/example/echo_c - 没有brpc::Client这个类。 # Channel -Client指发起请求的一端,在brpc中没有对应的实体,取而代之的是[brpc::Channel](https://github.com/brpc/brpc/blob/master/src/brpc/channel.h),它代表和一台或一组服务器的交互通道,Client和Channel在角色上的差别在实践中并不重要,你可以把Channel视作Client。 +Client指发起请求的一端,在brpc中没有对应的实体,取而代之的是[brpc::Channel](https://github.com/apache/brpc/blob/master/src/brpc/channel.h),它代表和一台或一组服务器的交互通道,Client和Channel在角色上的差别在实践中并不重要,你可以把Channel视作Client。 Channel可以**被所有线程共用**,你不需要为每个线程创建独立的Channel,也不需要用锁互斥。不过Channel的创建和Init并不是线程安全的,请确保在Init成功后再被多线程访问,在没有线程访问后再析构。 @@ -168,7 +168,7 @@ NacosNamingService只支持整形的权重值。 ### 更多命名服务 -用户可以通过实现brpc::NamingService来对接更多命名服务,具体见[这里](https://github.com/brpc/brpc/blob/master/docs/cn/load_balancing.md#%E5%91%BD%E5%90%8D%E6%9C%8D%E5%8A%A1) +用户可以通过实现brpc::NamingService来对接更多命名服务,具体见[这里](https://github.com/apache/brpc/blob/master/docs/cn/load_balancing.md#%E5%91%BD%E5%90%8D%E6%9C%8D%E5%8A%A1) ### 命名服务中的tag 每个地址可以附带一个tag,在常见的命名服务中,如果地址后有空格,则空格之后的内容均为tag。 @@ -266,7 +266,7 @@ locality-aware,优先选择延时低的下游,直到其延时高于其他机 发起RPC前需要设置Controller.set_request_code(),否则RPC会失败。request_code一般是请求中主键部分的32位哈希值,**不需要和负载均衡使用的哈希算法一致**。比如用c_murmurhash算法也可以用md5计算哈希值。 -[src/brpc/policy/hasher.h](https://github.com/brpc/brpc/blob/master/src/brpc/policy/hasher.h)中包含了常用的hash函数。如果用std::string key代表请求的主键,controller.set_request_code(brpc::policy::MurmurHash32(key.data(), key.size()))就正确地设置了request_code。 +[src/brpc/policy/hasher.h](https://github.com/apache/brpc/blob/master/src/brpc/policy/hasher.h)中包含了常用的hash函数。如果用std::string key代表请求的主键,controller.set_request_code(brpc::policy::MurmurHash32(key.data(), key.size()))就正确地设置了request_code。 注意甄别请求中的“主键”部分和“属性”部分,不要为了偷懒或通用,就把请求的所有内容一股脑儿计算出哈希值,属性的变化会使请求的目的地发生剧烈的变化。另外也要注意padding问题,比如struct Foo { int32_t a; int64_t b; }在64位机器上a和b之间有4个字节的空隙,内容未定义,如果像hash(&foo, sizeof(foo))这样计算哈希值,结果就是未定义的,得把内容紧密排列或序列化后再算。 @@ -370,7 +370,7 @@ request.set_foo(...); cntl->set_timeout_ms(...); stub.some_method(cntl, &request, response, brpc::NewCallback(OnRPCDone, response, cntl)); ``` -由于protobuf 3把NewCallback设置为私有,r32035后brpc把NewCallback独立于[src/brpc/callback.h](https://github.com/brpc/brpc/blob/master/src/brpc/callback.h)(并增加了一些重载)。如果你的程序出现NewCallback相关的编译错误,把google::protobuf::NewCallback替换为brpc::NewCallback就行了。 +由于protobuf 3把NewCallback设置为私有,r32035后brpc把NewCallback独立于[src/brpc/callback.h](https://github.com/apache/brpc/blob/master/src/brpc/callback.h)(并增加了一些重载)。如果你的程序出现NewCallback相关的编译错误,把google::protobuf::NewCallback替换为brpc::NewCallback就行了。 ### 继承google::protobuf::Closure @@ -491,7 +491,7 @@ brpc::StartCancel(call_id)可取消对应的RPC,call_id必须**在发起RPC前 ## 获取Server的地址和端口 -remote_side()方法可知道request被送向了哪个server,返回值类型是[butil::EndPoint](https://github.com/brpc/brpc/blob/master/src/butil/endpoint.h),包含一个ip4地址和端口。在RPC结束前调用这个方法都是没有意义的。 +remote_side()方法可知道request被送向了哪个server,返回值类型是[butil::EndPoint](https://github.com/apache/brpc/blob/master/src/butil/endpoint.h),包含一个ip4地址和端口。在RPC结束前调用这个方法都是没有意义的。 打印方式: ```c++ @@ -534,8 +534,8 @@ for (int i = 0; i < n; ++i) { Client端的设置主要由三部分组成: -- brpc::ChannelOptions: 定义在[src/brpc/channel.h](https://github.com/brpc/brpc/blob/master/src/brpc/channel.h)中,用于初始化Channel,一旦初始化成功无法修改。 -- brpc::Controller: 定义在[src/brpc/controller.h](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h)中,用于在某次RPC中覆盖ChannelOptions中的选项,可根据上下文每次均不同。 +- brpc::ChannelOptions: 定义在[src/brpc/channel.h](https://github.com/apache/brpc/blob/master/src/brpc/channel.h)中,用于初始化Channel,一旦初始化成功无法修改。 +- brpc::Controller: 定义在[src/brpc/controller.h](https://github.com/apache/brpc/blob/master/src/brpc/controller.h)中,用于在某次RPC中覆盖ChannelOptions中的选项,可根据上下文每次均不同。 - 全局gflags:常用于调节一些底层代码的行为,一般不用修改。请自行阅读服务[/flags页面](flags.md)中的说明。 Controller包含了request中没有的数据和选项。server端和client端的Controller结构体是一样的,但使用的字段可能是不同的,你需要仔细阅读Controller中的注释,明确哪些字段可以在server端使用,哪些可以在client端使用。 @@ -600,7 +600,7 @@ Controller.set_max_retry(0)或ChannelOptions.max_retry=0关闭重试。 一些错误重试是没有意义的,就不会重试,比如请求有错时(EREQUEST)不会重试,因为server总不会接受,没有意义。 -用户可以通过继承[brpc::RetryPolicy](https://github.com/brpc/brpc/blob/master/src/brpc/retry_policy.h)自定义重试条件。比如brpc默认不重试http/h2相关的错误,而你的程序中希望在碰到HTTP_STATUS_FORBIDDEN (403)时重试,可以这么做: +用户可以通过继承[brpc::RetryPolicy](https://github.com/apache/brpc/blob/master/src/brpc/retry_policy.h)自定义重试条件。比如brpc默认不重试http/h2相关的错误,而你的程序中希望在碰到HTTP_STATUS_FORBIDDEN (403)时重试,可以这么做: ```c++ #include @@ -745,7 +745,7 @@ baidu_std和hulu_pbrpc协议支持附件,这段数据由用户自定义,不 ## 开启SSL 要开启SSL,首先确保代码依赖了最新的openssl库。如果openssl版本很旧,会有严重的安全漏洞,支持的加密算法也少,违背了开启SSL的初衷。 -然后设置`ChannelOptions.mutable_ssl_options()`,具体选项见[ssl_options.h](https://github.com/brpc/brpc/blob/master/src/brpc/ssl_options.h)。ChannelOptions.has_ssl_options()可查询是否设置过ssl_options, ChannelOptions.ssl_options()可访问到设置过的只读ssl_options。 +然后设置`ChannelOptions.mutable_ssl_options()`,具体选项见[ssl_options.h](https://github.com/apache/brpc/blob/master/src/brpc/ssl_options.h)。ChannelOptions.has_ssl_options()可查询是否设置过ssl_options, ChannelOptions.ssl_options()可访问到设置过的只读ssl_options。 ```c++ // 开启客户端SSL并使用默认值。 @@ -903,11 +903,11 @@ FATAL 04-07 20:00:03 7778 src/brpc/channel.cpp:123] Invalid address=`bns://group 主要步骤: -1. 创建一个[bthread_id](https://github.com/brpc/brpc/blob/master/src/bthread/id.h)作为本次RPC的correlation_id。 -2. 根据Channel的创建方式,从进程级的[SocketMap](https://github.com/brpc/brpc/blob/master/src/brpc/socket_map.h)中或从[LoadBalancer](https://github.com/brpc/brpc/blob/master/src/brpc/load_balancer.h)中选择一台下游server作为本次RPC发送的目的地。 -3. 根据连接方式(单连接、连接池、短连接),选择一个[Socket](https://github.com/brpc/brpc/blob/master/src/brpc/socket.h)。 +1. 创建一个[bthread_id](https://github.com/apache/brpc/blob/master/src/bthread/id.h)作为本次RPC的correlation_id。 +2. 根据Channel的创建方式,从进程级的[SocketMap](https://github.com/apache/brpc/blob/master/src/brpc/socket_map.h)中或从[LoadBalancer](https://github.com/apache/brpc/blob/master/src/brpc/load_balancer.h)中选择一台下游server作为本次RPC发送的目的地。 +3. 根据连接方式(单连接、连接池、短连接),选择一个[Socket](https://github.com/apache/brpc/blob/master/src/brpc/socket.h)。 4. 如果开启验证且当前Socket没有被验证过时,第一个请求进入验证分支,其余请求会阻塞直到第一个包含认证信息的请求写入Socket。server端只对第一个请求进行验证。 -5. 根据Channel的协议,选择对应的序列化函数把request序列化至[IOBuf](https://github.com/brpc/brpc/blob/master/src/butil/iobuf.h)。 +5. 根据Channel的协议,选择对应的序列化函数把request序列化至[IOBuf](https://github.com/apache/brpc/blob/master/src/butil/iobuf.h)。 6. 如果配置了超时,设置定时器。从这个点开始要避免使用Controller对象,因为在设定定时器后随时可能触发超时->调用到用户的超时回调->用户在回调中析构Controller。 7. 发送准备阶段结束,若上述任何步骤出错,会调用Channel::HandleSendFailed。 8. 将之前序列化好的IOBuf写出到Socket上,同时传入回调Channel::HandleSocketFailed,当连接断开、写失败等错误发生时会调用此回调。 diff --git a/docs/cn/combo_channel.md b/docs/cn/combo_channel.md index 370b5e0865..76c0b23c98 100644 --- a/docs/cn/combo_channel.md +++ b/docs/cn/combo_channel.md @@ -17,7 +17,7 @@ ParallelChannel (有时被称为“pchan”)同时访问其包含的sub channel - 可以取消。 - 支持超时。 -示例代码见[example/parallel_echo_c++](https://github.com/brpc/brpc/tree/master/example/parallel_echo_c++/)。 +示例代码见[example/parallel_echo_c++](https://github.com/apache/brpc/tree/master/example/parallel_echo_c++/)。 任何brpc::ChannelBase的子类都可以加入ParallelChannel,包括ParallelChannel和其他组合Channel。用户可以设置ParallelChannelOptions.fail_limit来控制访问的最大失败次数,当失败的访问达到这个数目时,RPC会立刻结束而不等待超时。 @@ -155,14 +155,14 @@ const Controller* sub(int index) const; # SelectiveChannel -[SelectiveChannel](https://github.com/brpc/brpc/blob/master/src/brpc/selective_channel.h) (有时被称为“schan”)按负载均衡算法访问其包含的Channel,相比普通Channel它更加高层:把流量分给sub channel,而不是具体的Server。SelectiveChannel主要用来支持机器组之间的负载均衡,它具备Channel的主要属性: +[SelectiveChannel](https://github.com/apache/brpc/blob/master/src/brpc/selective_channel.h) (有时被称为“schan”)按负载均衡算法访问其包含的Channel,相比普通Channel它更加高层:把流量分给sub channel,而不是具体的Server。SelectiveChannel主要用来支持机器组之间的负载均衡,它具备Channel的主要属性: - 支持同步和异步访问。 - 发起异步操作后可以立刻删除。 - 可以取消。 - 支持超时。 -示例代码见[example/selective_echo_c++](https://github.com/brpc/brpc/tree/master/example/selective_echo_c++/)。 +示例代码见[example/selective_echo_c++](https://github.com/apache/brpc/tree/master/example/selective_echo_c++/)。 任何brpc::ChannelBase的子类都可加入SelectiveChannel,包括SelectiveChannel和其他组合Channel。 @@ -246,9 +246,9 @@ stub.FooMethod(&cntl, &request, &response, NULL); # PartitionChannel -[PartitionChannel](https://github.com/brpc/brpc/blob/master/src/brpc/partition_channel.h)是特殊的ParallelChannel,它会根据命名服务中的tag自动建立对应分库的sub channel。这样用户就可以把所有的分库机器挂在一个命名服务内,通过tag来指定哪台机器对应哪个分库。示例代码见[example/partition_echo_c++](https://github.com/brpc/brpc/tree/master/example/partition_echo_c++/)。 +[PartitionChannel](https://github.com/apache/brpc/blob/master/src/brpc/partition_channel.h)是特殊的ParallelChannel,它会根据命名服务中的tag自动建立对应分库的sub channel。这样用户就可以把所有的分库机器挂在一个命名服务内,通过tag来指定哪台机器对应哪个分库。示例代码见[example/partition_echo_c++](https://github.com/apache/brpc/tree/master/example/partition_echo_c++/)。 -ParititonChannel只能处理一种分库方法,当用户需要多种分库方法共存,或从一个分库方法平滑地切换为另一种分库方法时,可以使用DynamicPartitionChannel,它会根据不同的分库方式动态地建立对应的sub PartitionChannel,并根据容量把请求分配给不同的分库。示例代码见[example/dynamic_partition_echo_c++](https://github.com/brpc/brpc/tree/master/example/dynamic_partition_echo_c++/)。 +ParititonChannel只能处理一种分库方法,当用户需要多种分库方法共存,或从一个分库方法平滑地切换为另一种分库方法时,可以使用DynamicPartitionChannel,它会根据不同的分库方式动态地建立对应的sub PartitionChannel,并根据容量把请求分配给不同的分库。示例代码见[example/dynamic_partition_echo_c++](https://github.com/apache/brpc/tree/master/example/dynamic_partition_echo_c++/)。 如果分库在不同的命名服务内,那么用户得自行用ParallelChannel组装,即每个sub channel对应一个分库(使用不同的命名服务)。ParellelChannel的使用方法见[上面](#ParallelChannel)。 diff --git a/docs/cn/cpu_profiler.md b/docs/cn/cpu_profiler.md index 5dfa396046..15d4e014bc 100644 --- a/docs/cn/cpu_profiler.md +++ b/docs/cn/cpu_profiler.md @@ -53,7 +53,7 @@ cpu profiler的原理是在定期被调用的SIGPROF handler中采样所在线 ![img](../images/echo_cpu_profiling.png) -在Linux下,你也可以使用[pprof](https://github.com/brpc/brpc/blob/master/tools/pprof)或gperftools中的pprof进行profiling。 +在Linux下,你也可以使用[pprof](https://github.com/apache/brpc/blob/master/tools/pprof)或gperftools中的pprof进行profiling。 比如`pprof --text localhost:9002 --seconds=5`的意思是统计运行在本机9002端口的server的cpu情况,时长5秒。一次运行的例子如下: diff --git a/docs/cn/error_code.md b/docs/cn/error_code.md index 5339c232a4..7cd36b72c6 100644 --- a/docs/cn/error_code.md +++ b/docs/cn/error_code.md @@ -1,6 +1,6 @@ [English version](../en/error_code.md) -brpc使用[brpc::Controller](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h)设置和获取一次RPC的参数,`Controller::ErrorCode()`和`Controller::ErrorText()`则分别是该次RPC的错误码和错误描述,RPC结束后才能访问,否则结果未定义。ErrorText()由Controller的基类google::protobuf::RpcController定义,ErrorCode()则是brpc::Controller定义的。Controller还有个Failed()方法告知该次RPC是否失败,这三者的关系是: +brpc使用[brpc::Controller](https://github.com/apache/brpc/blob/master/src/brpc/controller.h)设置和获取一次RPC的参数,`Controller::ErrorCode()`和`Controller::ErrorText()`则分别是该次RPC的错误码和错误描述,RPC结束后才能访问,否则结果未定义。ErrorText()由Controller的基类google::protobuf::RpcController定义,ErrorCode()则是brpc::Controller定义的。Controller还有个Failed()方法告知该次RPC是否失败,这三者的关系是: - 当Failed()为true时,ErrorCode()一定为非0,ErrorText()则为非空。 - 当Failed()为false时,ErrorCode()一定为0,ErrorText()未定义(目前在brpc中会为空,但你最好不要依赖这个事实) @@ -15,9 +15,9 @@ server端Controller的SetFailed()常由用户在服务回调中调用。当处 # brpc的错误码 -brpc使用的所有ErrorCode都定义在[errno.proto](https://github.com/brpc/brpc/blob/master/src/brpc/errno.proto)中,*SYS_*开头的来自linux系统,与/usr/include/errno.h中定义的精确一致,定义在proto中是为了跨语言。其余的是brpc自有的。 +brpc使用的所有ErrorCode都定义在[errno.proto](https://github.com/apache/brpc/blob/master/src/brpc/errno.proto)中,*SYS_*开头的来自linux系统,与/usr/include/errno.h中定义的精确一致,定义在proto中是为了跨语言。其余的是brpc自有的。 -[berror(error_code)](https://github.com/brpc/brpc/blob/master/src/butil/errno.h)可获得error_code的描述,berror()可获得当前[system errno](http://www.cplusplus.com/reference/cerrno/errno/)的描述。**ErrorText() != berror(ErrorCode())**,ErrorText()会包含更具体的错误信息。brpc默认包含berror,你可以直接使用。 +[berror(error_code)](https://github.com/apache/brpc/blob/master/src/butil/errno.h)可获得error_code的描述,berror()可获得当前[system errno](http://www.cplusplus.com/reference/cerrno/errno/)的描述。**ErrorText() != berror(ErrorCode())**,ErrorText()会包含更具体的错误信息。brpc默认包含berror,你可以直接使用。 brpc中常见错误的打印内容列表如下: diff --git a/docs/cn/execution_queue.md b/docs/cn/execution_queue.md index 17dcbcfa82..08d3694007 100644 --- a/docs/cn/execution_queue.md +++ b/docs/cn/execution_queue.md @@ -1,6 +1,6 @@ # 概述 -类似于kylin的ExecMan, [ExecutionQueue](https://github.com/brpc/brpc/blob/master/src/bthread/execution_queue.h)提供了异步串行执行的功能。ExecutionQueue的相关技术最早使用在RPC中实现[多线程向同一个fd写数据](io.md#发消息). 在r31345之后加入到bthread。 ExecutionQueue 提供了如下基本功能: +类似于kylin的ExecMan, [ExecutionQueue](https://github.com/apache/brpc/blob/master/src/bthread/execution_queue.h)提供了异步串行执行的功能。ExecutionQueue的相关技术最早使用在RPC中实现[多线程向同一个fd写数据](io.md#发消息). 在r31345之后加入到bthread。 ExecutionQueue 提供了如下基本功能: - 异步有序执行: 任务在另外一个单独的线程中执行, 并且执行顺序严格和提交顺序一致. - Multi Producer: 多个线程可以同时向一个ExecutionQueue提交任务 diff --git a/docs/cn/flatmap.md b/docs/cn/flatmap.md index c37ba31d9d..814558ac59 100644 --- a/docs/cn/flatmap.md +++ b/docs/cn/flatmap.md @@ -74,7 +74,7 @@ void flatmap_erase_hinted_during_iteration_example() { # DESCRIPTION -[FlatMap](https://github.com/brpc/brpc/blob/master/src/butil/containers/flat_map.h)可能是最快的哈希表,但当value较大时它需要更多的内存,它最适合作为检索过程中需要极快查找的小字典。 +[FlatMap](https://github.com/apache/brpc/blob/master/src/butil/containers/flat_map.h)可能是最快的哈希表,但当value较大时它需要更多的内存,它最适合作为检索过程中需要极快查找的小字典。 原理:把开链桶中第一个节点的内容直接放桶内。由于在实践中,大部分桶没有冲突或冲突较少,所以大部分操作只需要一次内存跳转:通过哈希值访问对应的桶。桶内两个及以上元素仍存放在链表中,由于桶之间彼此独立,一个桶的冲突不会影响其他桶,性能很稳定。在很多时候,FlatMap的查找性能和原生数组接近。 diff --git a/docs/cn/getting_started.md b/docs/cn/getting_started.md index 942fe4bdfa..9db37688d9 100644 --- a/docs/cn/getting_started.md +++ b/docs/cn/getting_started.md @@ -334,7 +334,7 @@ GCC7中over-aligned的问题暂时被禁止。 同一个文件兼容pb 3.x版本和pb 2.x版本: 不要使用proto3新增的类型,并且在proto文件的起始位置添加`syntax=proto2;`声明。 -[tools/add_syntax_equal_proto2_to_all.sh](https://github.com/brpc/brpc/blob/master/tools/add_syntax_equal_proto2_to_all.sh)这个脚本可以给所有没有这行声明的proto文件添加`syntax="proto2"`声明。 +[tools/add_syntax_equal_proto2_to_all.sh](https://github.com/apache/brpc/blob/master/tools/add_syntax_equal_proto2_to_all.sh)这个脚本可以给所有没有这行声明的proto文件添加`syntax="proto2"`声明。 pb 3.x中的Arena至今没被支持。 @@ -378,4 +378,4 @@ brpc会自动检测valgrind(然后注册bthread的栈)。不支持老版本 # 实例追踪 -我们提供了一个程序去帮助你追踪和监控所有brpc实例。 只需要在某处运行 [trackme_server](https://github.com/brpc/brpc/tree/master/tools/trackme_server/) 然后再带着 -trackme_server=SERVER参数启动需要被追踪的实例。trackme_server将从实例周期性地收到ping消息然后打印日志。您可以从日志中聚合实例地址,并调用实例的内置服务以获取更多信息。 +我们提供了一个程序去帮助你追踪和监控所有brpc实例。 只需要在某处运行 [trackme_server](https://github.com/apache/brpc/tree/master/tools/trackme_server/) 然后再带着 -trackme_server=SERVER参数启动需要被追踪的实例。trackme_server将从实例周期性地收到ping消息然后打印日志。您可以从日志中聚合实例地址,并调用实例的内置服务以获取更多信息。 diff --git a/docs/cn/http_client.md b/docs/cn/http_client.md index a6bfb1bb08..b34b0618ca 100644 --- a/docs/cn/http_client.md +++ b/docs/cn/http_client.md @@ -2,7 +2,7 @@ # 示例 -[example/http_c++](https://github.com/brpc/brpc/blob/master/example/http_c++/http_client.cpp) +[example/http_c++](https://github.com/apache/brpc/blob/master/example/http_c++/http_client.cpp) # 关于h2 @@ -41,7 +41,7 @@ HTTP/h2和protobuf关系不大,所以除了Controller和done,CallMethod的 # POST -默认的HTTP Method为GET,可设置为POST或[更多http method](https://github.com/brpc/brpc/blob/master/src/brpc/http_method.h)。待POST的数据应置入request_attachment(),它([butil::IOBuf](https://github.com/brpc/brpc/blob/master/src/butil/iobuf.h))可以直接append std::string或char*。 +默认的HTTP Method为GET,可设置为POST或[更多http method](https://github.com/apache/brpc/blob/master/src/brpc/http_method.h)。待POST的数据应置入request_attachment(),它([butil::IOBuf](https://github.com/apache/brpc/blob/master/src/butil/iobuf.h))可以直接append std::string或char*。 ```c++ brpc::Controller cntl; diff --git a/docs/cn/http_service.md b/docs/cn/http_service.md index c8945eb170..7ecd6d353e 100644 --- a/docs/cn/http_service.md +++ b/docs/cn/http_service.md @@ -5,7 +5,7 @@ 虽然用不到pb消息,但brpc中的http/h2服务接口也得定义在proto文件中,只是request和response都是空的结构体。这确保了所有的服务声明集中在proto文件中,而不是散列在proto文件、程序、配置等多个地方。 #示例 -[http_server.cpp](https://github.com/brpc/brpc/blob/master/example/http_c++/http_server.cpp)。 +[http_server.cpp](https://github.com/apache/brpc/blob/master/example/http_c++/http_server.cpp)。 # 关于h2 @@ -244,7 +244,7 @@ cntl->http_response().set_content_type("text/html"); ## Status Code -status code是http response特有的字段,标记http请求的完成情况。可能的值定义在[http_status_code.h](https://github.com/brpc/brpc/blob/master/src/brpc/http_status_code.h)中。 +status code是http response特有的字段,标记http请求的完成情况。可能的值定义在[http_status_code.h](https://github.com/apache/brpc/blob/master/src/brpc/http_status_code.h)中。 ```c++ // Get Status Code @@ -268,7 +268,7 @@ cntl->http_response().SetHeader("Location", "http://bj.bs.bae.baidu.com/family/i ## Query String -如上面的[HTTP headers](#http-headers)中提到的那样,我们按约定成俗的方式来理解query string,即key1=value1&key2=value2&...。只有key而没有value也是可以的,仍然会被GetQuery查询到,只是值为空字符串,这常被用做bool型的开关。接口定义在[uri.h](https://github.com/brpc/brpc/blob/master/src/brpc/uri.h)。 +如上面的[HTTP headers](#http-headers)中提到的那样,我们按约定成俗的方式来理解query string,即key1=value1&key2=value2&...。只有key而没有value也是可以的,仍然会被GetQuery查询到,只是值为空字符串,这常被用做bool型的开关。接口定义在[uri.h](https://github.com/apache/brpc/blob/master/src/brpc/uri.h)。 ```c++ const std::string* time_value = cntl->http_request().uri().GetQuery("time"); @@ -324,7 +324,7 @@ https是http over SSL的简称,SSL并不是http特有的,而是对所有协 没有极端性能要求的产品都有使用HTTP协议的倾向,特别是移动产品,所以我们很重视HTTP的实现质量,具体来说: -- 使用了node.js的[http parser](https://github.com/brpc/brpc/blob/master/src/brpc/details/http_parser.h)解析http消息,这是一个轻量、优秀、被广泛使用的实现。 +- 使用了node.js的[http parser](https://github.com/apache/brpc/blob/master/src/brpc/details/http_parser.h)解析http消息,这是一个轻量、优秀、被广泛使用的实现。 - 使用[rapidjson](https://github.com/miloyip/rapidjson)解析json,这是一个主打性能的json库。 - 在最差情况下解析http请求的时间复杂度也是O(N),其中N是请求的字节数。反过来说,如果解析代码要求http请求是完整的,那么它可能会花费O(N^2)的时间。HTTP请求普遍较大,这一点意义还是比较大的。 - 来自不同client的http消息是高度并发的,即使相当复杂的http消息也不会影响对其他客户端的响应。其他rpc和[基于单线程reactor](threading_overview.md#单线程reactor)的各类http server往往难以做到这一点。 diff --git a/docs/cn/io.md b/docs/cn/io.md index f2e352fe0a..3fa4b580ac 100644 --- a/docs/cn/io.md +++ b/docs/cn/io.md @@ -10,11 +10,11 @@ linux一般使用non-blocking IO提高IO并发度。当IO并发度很低时,no # 收消息 -“消息”指从连接读入的有边界的二进制串,可能是来自上游client的request或来自下游server的response。brpc使用一个或多个[EventDispatcher](https://github.com/brpc/brpc/blob/master/src/brpc/event_dispatcher.h)(简称为EDISP)等待任一fd发生事件。和常见的“IO线程”不同,EDISP不负责读取。IO线程的问题在于一个线程同时只能读一个fd,当多个繁忙的fd聚集在一个IO线程中时,一些读取就被延迟了。多租户、复杂分流算法,[Streaming RPC](streaming_rpc.md)等功能会加重这个问题。高负载下常见的某次读取卡顿会拖慢一个IO线程中所有fd的读取,对可用性的影响幅度较大。 +“消息”指从连接读入的有边界的二进制串,可能是来自上游client的request或来自下游server的response。brpc使用一个或多个[EventDispatcher](https://github.com/apache/brpc/blob/master/src/brpc/event_dispatcher.h)(简称为EDISP)等待任一fd发生事件。和常见的“IO线程”不同,EDISP不负责读取。IO线程的问题在于一个线程同时只能读一个fd,当多个繁忙的fd聚集在一个IO线程中时,一些读取就被延迟了。多租户、复杂分流算法,[Streaming RPC](streaming_rpc.md)等功能会加重这个问题。高负载下常见的某次读取卡顿会拖慢一个IO线程中所有fd的读取,对可用性的影响幅度较大。 -由于epoll的[一个bug](https://patchwork.kernel.org/patch/1970231/)(开发brpc时仍有)及epoll_ctl较大的开销,EDISP使用Edge triggered模式。当收到事件时,EDISP给一个原子变量加1,只有当加1前的值是0时启动一个bthread处理对应fd上的数据。在背后,EDISP把所在的pthread让给了新建的bthread,使其有更好的cache locality,可以尽快地读取fd上的数据。而EDISP所在的bthread会被偷到另外一个pthread继续执行,这个过程即是bthread的work stealing调度。要准确理解那个原子变量的工作方式可以先阅读[atomic instructions](atomic_instructions.md),再看[Socket::StartInputEvent](https://github.com/brpc/brpc/blob/master/src/brpc/socket.cpp)。这些方法使得brpc读取同一个fd时产生的竞争是[wait-free](http://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom)的。 +由于epoll的[一个bug](https://patchwork.kernel.org/patch/1970231/)(开发brpc时仍有)及epoll_ctl较大的开销,EDISP使用Edge triggered模式。当收到事件时,EDISP给一个原子变量加1,只有当加1前的值是0时启动一个bthread处理对应fd上的数据。在背后,EDISP把所在的pthread让给了新建的bthread,使其有更好的cache locality,可以尽快地读取fd上的数据。而EDISP所在的bthread会被偷到另外一个pthread继续执行,这个过程即是bthread的work stealing调度。要准确理解那个原子变量的工作方式可以先阅读[atomic instructions](atomic_instructions.md),再看[Socket::StartInputEvent](https://github.com/apache/brpc/blob/master/src/brpc/socket.cpp)。这些方法使得brpc读取同一个fd时产生的竞争是[wait-free](http://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom)的。 -[InputMessenger](https://github.com/brpc/brpc/blob/master/src/brpc/input_messenger.h)负责从fd上切割和处理消息,它通过用户回调函数理解不同的格式。Parse一般是把消息从二进制流上切割下来,运行时间较固定;Process则是进一步解析消息(比如反序列化为protobuf)后调用用户回调,时间不确定。若一次从某个fd读取出n个消息(n > 1),InputMessenger会启动n-1个bthread分别处理前n-1个消息,最后一个消息则会在原地被Process。InputMessenger会逐一尝试多种协议,由于一个连接上往往只有一种消息格式,InputMessenger会记录下上次的选择,而避免每次都重复尝试。 +[InputMessenger](https://github.com/apache/brpc/blob/master/src/brpc/input_messenger.h)负责从fd上切割和处理消息,它通过用户回调函数理解不同的格式。Parse一般是把消息从二进制流上切割下来,运行时间较固定;Process则是进一步解析消息(比如反序列化为protobuf)后调用用户回调,时间不确定。若一次从某个fd读取出n个消息(n > 1),InputMessenger会启动n-1个bthread分别处理前n-1个消息,最后一个消息则会在原地被Process。InputMessenger会逐一尝试多种协议,由于一个连接上往往只有一种消息格式,InputMessenger会记录下上次的选择,而避免每次都重复尝试。 可以看到,fd间和fd内的消息都会在brpc中获得并发,这使brpc非常擅长大消息的读取,在高负载时仍能及时处理不同来源的消息,减少长尾的存在。 @@ -22,7 +22,7 @@ linux一般使用non-blocking IO提高IO并发度。当IO并发度很低时,no "消息”指向连接写出的有边界的二进制串,可能是发向上游client的response或下游server的request。多个线程可能会同时向一个fd发送消息,而写fd又是非原子的,所以如何高效率地排队不同线程写出的数据包是这里的关键。brpc使用一种wait-free MPSC链表来实现这个功能。所有待写出的数据都放在一个单链表节点中,next指针初始化为一个特殊值(Socket::WriteRequest::UNCONNECTED)。当一个线程想写出数据前,它先尝试和对应的链表头(Socket::_write_head)做原子交换,返回值是交换前的链表头。如果返回值为空,说明它获得了写出的权利,它会在原地写一次数据。否则说明有另一个线程在写,它把next指针指向返回的头以让链表连通。正在写的线程之后会看到新的头并写出这块数据。 -这套方法可以让写竞争是wait-free的,而获得写权利的线程虽然在原理上不是wait-free也不是lock-free,可能会被一个值仍为UNCONNECTED的节点锁定(这需要发起写的线程正好在原子交换后,在设置next指针前,仅仅一条指令的时间内被OS换出),但在实践中很少出现。在当前的实现中,如果获得写权利的线程一下子无法写出所有的数据,会启动一个KeepWrite线程继续写,直到所有的数据都被写出。这套逻辑非常复杂,大致原理如下图,细节请阅读[socket.cpp](https://github.com/brpc/brpc/blob/master/src/brpc/socket.cpp)。 +这套方法可以让写竞争是wait-free的,而获得写权利的线程虽然在原理上不是wait-free也不是lock-free,可能会被一个值仍为UNCONNECTED的节点锁定(这需要发起写的线程正好在原子交换后,在设置next指针前,仅仅一条指令的时间内被OS换出),但在实践中很少出现。在当前的实现中,如果获得写权利的线程一下子无法写出所有的数据,会启动一个KeepWrite线程继续写,直到所有的数据都被写出。这套逻辑非常复杂,大致原理如下图,细节请阅读[socket.cpp](https://github.com/apache/brpc/blob/master/src/brpc/socket.cpp)。 ![img](../images/write.png) @@ -30,7 +30,7 @@ linux一般使用non-blocking IO提高IO并发度。当IO并发度很低时,no # Socket -和fd相关的数据均在[Socket](https://github.com/brpc/brpc/blob/master/src/brpc/socket.h)中,是rpc最复杂的结构之一,这个结构的独特之处在于用64位的SocketId指代Socket对象以方便在多线程环境下使用fd。常用的三个方法: +和fd相关的数据均在[Socket](https://github.com/apache/brpc/blob/master/src/brpc/socket.h)中,是rpc最复杂的结构之一,这个结构的独特之处在于用64位的SocketId指代Socket对象以方便在多线程环境下使用fd。常用的三个方法: - Create:创建Socket,并返回其SocketId。 - Address:取得id对应的Socket,包装在一个会自动释放的unique_ptr中(SocketUniquePtr),当Socket被SetFailed后,返回指针为空。只要Address返回了非空指针,其内容保证不会变化,直到指针自动析构。这个函数是wait-free的。 diff --git a/docs/cn/iobuf.md b/docs/cn/iobuf.md index bd6d9e93b9..75c7ffcaca 100644 --- a/docs/cn/iobuf.md +++ b/docs/cn/iobuf.md @@ -1,6 +1,6 @@ [English version](../en/iobuf.md) -brpc使用[butil::IOBuf](https://github.com/brpc/brpc/blob/master/src/butil/iobuf.h)作为一些协议中的附件或http body的数据结构,它是一种非连续零拷贝缓冲,在其他项目中得到了验证并有出色的性能。IOBuf的接口和std::string类似,但不相同。 +brpc使用[butil::IOBuf](https://github.com/apache/brpc/blob/master/src/butil/iobuf.h)作为一些协议中的附件或http body的数据结构,它是一种非连续零拷贝缓冲,在其他项目中得到了验证并有出色的性能。IOBuf的接口和std::string类似,但不相同。 如果你之前使用Kylin中的BufHandle,你将更能感受到IOBuf的便利性:前者几乎没有实现完整,直接暴露了内部结构,用户得小心翼翼地处理引用计数,极易出错。 diff --git a/docs/cn/json2pb.md b/docs/cn/json2pb.md index fc41073f61..4442b120c2 100644 --- a/docs/cn/json2pb.md +++ b/docs/cn/json2pb.md @@ -1,4 +1,4 @@ -brpc支持json和protobuf间的**双向**转化,实现于[json2pb](https://github.com/brpc/brpc/tree/master/src/json2pb/),json解析使用[rapidjson](https://github.com/miloyip/rapidjson)。此功能对pb2.x和3.x均有效。pb3内置了[转换json](https://developers.google.com/protocol-buffers/docs/proto3#json)的功能。 +brpc支持json和protobuf间的**双向**转化,实现于[json2pb](https://github.com/apache/brpc/tree/master/src/json2pb/),json解析使用[rapidjson](https://github.com/miloyip/rapidjson)。此功能对pb2.x和3.x均有效。pb3内置了[转换json](https://developers.google.com/protocol-buffers/docs/proto3#json)的功能。 by design, 通过HTTP + json访问protobuf服务是对外服务的常见方式,故转化必须精准,转化规则列举如下。 diff --git a/docs/cn/lalb.md b/docs/cn/lalb.md index 58d054243a..d2951394fd 100644 --- a/docs/cn/lalb.md +++ b/docs/cn/lalb.md @@ -101,7 +101,7 @@ LoadBalancer是一个读远多于写的数据结构:大部分时候,所有 - 不同的读之间没有竞争,高度并发。 - 如果没有写,读总是能无竞争地获取和释放thread-local锁,一般小于25ns,对延时基本无影响。如果有写,由于其临界区极小(拿到立刻释放),读在大部分时候仍能快速地获得锁,少数时候释放锁时可能有唤醒写线程的代价。由于写本身就是少数情况,读整体上几乎不会碰到竞争锁。 -完成这些功能的数据结构是[DoublyBufferedData<>](https://github.com/brpc/brpc/blob/master/src/butil/containers/doubly_buffered_data.h),我们常简称为DBD。brpc中的所有load balancer都使用了这个数据结构,使不同线程在分流时几乎不会互斥。而其他rpc实现往往使用了全局锁,这使得它们无法写出复杂的分流算法:否则分流代码将会成为竞争热点。 +完成这些功能的数据结构是[DoublyBufferedData<>](https://github.com/apache/brpc/blob/master/src/butil/containers/doubly_buffered_data.h),我们常简称为DBD。brpc中的所有load balancer都使用了这个数据结构,使不同线程在分流时几乎不会互斥。而其他rpc实现往往使用了全局锁,这使得它们无法写出复杂的分流算法:否则分流代码将会成为竞争热点。 这个结构有广泛的应用场景: diff --git a/docs/cn/load_balancing.md b/docs/cn/load_balancing.md index 4990634996..27bad7d3c2 100644 --- a/docs/cn/load_balancing.md +++ b/docs/cn/load_balancing.md @@ -2,10 +2,10 @@ # 命名服务 -在brpc中,[NamingService](https://github.com/brpc/brpc/blob/master/src/brpc/naming_service.h)用于获得服务名对应的所有节点。一个直观的做法是定期调用一个函数以获取最新的节点列表。但这会带来一定的延时(定期调用的周期一般在若干秒左右),作为通用接口不太合适。特别当命名服务提供事件通知时(比如zk),这个特性没有被利用。所以我们反转了控制权:不是我们调用用户函数,而是用户在获得列表后调用我们的接口,对应[NamingServiceActions](https://github.com/brpc/brpc/blob/master/src/brpc/naming_service.h)。当然我们还是得启动进行这一过程的函数,对应NamingService::RunNamingService。下面以三个实现解释这套方式: +在brpc中,[NamingService](https://github.com/apache/brpc/blob/master/src/brpc/naming_service.h)用于获得服务名对应的所有节点。一个直观的做法是定期调用一个函数以获取最新的节点列表。但这会带来一定的延时(定期调用的周期一般在若干秒左右),作为通用接口不太合适。特别当命名服务提供事件通知时(比如zk),这个特性没有被利用。所以我们反转了控制权:不是我们调用用户函数,而是用户在获得列表后调用我们的接口,对应[NamingServiceActions](https://github.com/apache/brpc/blob/master/src/brpc/naming_service.h)。当然我们还是得启动进行这一过程的函数,对应NamingService::RunNamingService。下面以三个实现解释这套方式: -- bns:没有事件通知,所以我们只能定期去获得最新列表,默认间隔是[5秒](http://brpc.baidu.com:8765/flags/ns_access_interval)。为了简化这类定期获取的逻辑,brpc提供了[PeriodicNamingService](https://github.com/brpc/brpc/blob/master/src/brpc/periodic_naming_service.h) 供用户继承,用户只需要实现单次如何获取(GetServers)。获取后调用NamingServiceActions::ResetServers告诉框架。框架会对列表去重,和之前的列表比较,通知对列表有兴趣的观察者(NamingServiceWatcher)。这套逻辑会运行在独立的bthread中,即NamingServiceThread。一个NamingServiceThread可能被多个Channel共享,通过intrusive_ptr管理ownership。 -- file:列表即文件。合理的方式是在文件更新后重新读取。[该实现](https://github.com/brpc/brpc/blob/master/src/brpc/policy/file_naming_service.cpp)使用[FileWatcher](https://github.com/brpc/brpc/blob/master/src/butil/files/file_watcher.h)关注文件的修改时间,当文件修改后,读取并调用NamingServiceActions::ResetServers告诉框架。 +- bns:没有事件通知,所以我们只能定期去获得最新列表,默认间隔是[5秒](http://brpc.baidu.com:8765/flags/ns_access_interval)。为了简化这类定期获取的逻辑,brpc提供了[PeriodicNamingService](https://github.com/apache/brpc/blob/master/src/brpc/periodic_naming_service.h) 供用户继承,用户只需要实现单次如何获取(GetServers)。获取后调用NamingServiceActions::ResetServers告诉框架。框架会对列表去重,和之前的列表比较,通知对列表有兴趣的观察者(NamingServiceWatcher)。这套逻辑会运行在独立的bthread中,即NamingServiceThread。一个NamingServiceThread可能被多个Channel共享,通过intrusive_ptr管理ownership。 +- file:列表即文件。合理的方式是在文件更新后重新读取。[该实现](https://github.com/apache/brpc/blob/master/src/brpc/policy/file_naming_service.cpp)使用[FileWatcher](https://github.com/apache/brpc/blob/master/src/butil/files/file_watcher.h)关注文件的修改时间,当文件修改后,读取并调用NamingServiceActions::ResetServers告诉框架。 - list:列表就在服务名里(逗号分隔)。在读取完一次并调用NamingServiceActions::ResetServers后就退出了,因为列表再不会改变了。 如果用户需要建立这些对象仍然是不够方便的,因为总是需要一些工厂代码根据配置项建立不同的对象,鉴于此,我们把工厂类做进了框架,并且是非常方便的形式: @@ -20,7 +20,7 @@ list://addr1,addr2,... # use the addresses separated by comma http:// # Domain Naming Service, aka DNS. ``` -这套方式是可扩展的,实现了新的NamingService后在[global.cpp](https://github.com/brpc/brpc/blob/master/src/brpc/global.cpp)中依葫芦画瓢注册下就行了,如下图所示: +这套方式是可扩展的,实现了新的NamingService后在[global.cpp](https://github.com/apache/brpc/blob/master/src/brpc/global.cpp)中依葫芦画瓢注册下就行了,如下图所示: ![img](../images/register_ns.png) @@ -28,7 +28,7 @@ http:// # Domain Naming Service, aka DNS. # 负载均衡 -brpc中[LoadBalancer](https://github.com/brpc/brpc/blob/master/src/brpc/load_balancer.h)从多个服务节点中选择一个节点,目前的实现见[负载均衡](client.md#负载均衡)。 +brpc中[LoadBalancer](https://github.com/apache/brpc/blob/master/src/brpc/load_balancer.h)从多个服务节点中选择一个节点,目前的实现见[负载均衡](client.md#负载均衡)。 Load balancer最重要的是如何让不同线程中的负载均衡不互斥,解决这个问题的技术是[DoublyBufferedData](lalb.md#doublybuffereddata)。 diff --git a/docs/cn/memcache_client.md b/docs/cn/memcache_client.md index 11780b2ec6..2e7a8f6240 100644 --- a/docs/cn/memcache_client.md +++ b/docs/cn/memcache_client.md @@ -1,6 +1,6 @@ [English version](../en/memcache_client.md) -[memcached](http://memcached.org/)是常用的缓存服务,为了使用户更快捷地访问memcached并充分利用bthread的并发能力,brpc直接支持memcache协议。示例程序:[example/memcache_c++](https://github.com/brpc/brpc/tree/master/example/memcache_c++/) +[memcached](http://memcached.org/)是常用的缓存服务,为了使用户更快捷地访问memcached并充分利用bthread的并发能力,brpc直接支持memcache协议。示例程序:[example/memcache_c++](https://github.com/apache/brpc/tree/master/example/memcache_c++/) **注意**:brpc只支持memcache的二进制协议。memcached在1.3前只有文本协议,但在当前看来支持的意义甚微。如果你的memcached早于1.3,升级版本。 diff --git a/docs/cn/memory_management.md b/docs/cn/memory_management.md index 8ddee199f7..6e9afcabef 100644 --- a/docs/cn/memory_management.md +++ b/docs/cn/memory_management.md @@ -29,7 +29,7 @@ # 生成bthread_t -用户期望通过创建bthread获得更高的并发度,所以创建bthread必须很快。 在目前的实现中创建一个bthread的平均耗时小于200ns。如果每次都要从头创建,是不可能这么快的。创建过程更像是从一个bthread池子中取一个实例,我们又同时需要一个id来指代一个bthread,所以这儿正是ResourcePool的用武之地。bthread在代码中被称作Task,其结构被称为TaskMeta,定义在[task_meta.h](https://github.com/brpc/brpc/blob/master/src/bthread/task_meta.h)中,所有的TaskMeta由ResourcePool分配。 +用户期望通过创建bthread获得更高的并发度,所以创建bthread必须很快。 在目前的实现中创建一个bthread的平均耗时小于200ns。如果每次都要从头创建,是不可能这么快的。创建过程更像是从一个bthread池子中取一个实例,我们又同时需要一个id来指代一个bthread,所以这儿正是ResourcePool的用武之地。bthread在代码中被称作Task,其结构被称为TaskMeta,定义在[task_meta.h](https://github.com/apache/brpc/blob/master/src/bthread/task_meta.h)中,所有的TaskMeta由ResourcePool分配。 bthread的大部分函数都需要在O(1)时间内通过bthread_t访问到TaskMeta,并且当bthread_t失效后,访问应返回NULL以让函数做出返回错误。解决方法是:bthread_t由32位的版本和32位的偏移量组成。版本解决[ABA问题](http://en.wikipedia.org/wiki/ABA_problem),偏移量由ResourcePool分配。查找时先通过偏移量获得TaskMeta,再检查版本,如果版本不匹配,说明bthread失效了。注意:这只是大概的说法,在多线程环境下,即使版本相等,bthread仍可能随时失效,在不同的bthread函数中处理方法都是不同的,有些函数会加锁,有些则能忍受版本不相等。 diff --git a/docs/cn/new_protocol.md b/docs/cn/new_protocol.md index 47ded203d3..7d89f68d1d 100644 --- a/docs/cn/new_protocol.md +++ b/docs/cn/new_protocol.md @@ -20,7 +20,7 @@ brpc就是设计为可随时扩展新协议的,步骤如下: ## 增加ProtocolType -在[options.proto](https://github.com/brpc/brpc/blob/master/src/brpc/options.proto)的ProtocolType中增加新协议类型,如果你需要的话可以联系我们增加,以确保不会和其他人的需求重合。 +在[options.proto](https://github.com/apache/brpc/blob/master/src/brpc/options.proto)的ProtocolType中增加新协议类型,如果你需要的话可以联系我们增加,以确保不会和其他人的需求重合。 目前的ProtocolType(18年中): ```c++ @@ -56,7 +56,7 @@ enum ProtocolType { ``` ## 实现回调 -均定义在struct Protocol中,该结构定义在[protocol.h](https://github.com/brpc/brpc/blob/master/src/brpc/protocol.h)。其中的parse必须实现,除此之外server端至少要实现process_request,client端至少要实现serialize_request,pack_request,process_response。 +均定义在struct Protocol中,该结构定义在[protocol.h](https://github.com/apache/brpc/blob/master/src/brpc/protocol.h)。其中的parse必须实现,除此之外server端至少要实现process_request,client端至少要实现serialize_request,pack_request,process_response。 实现协议回调还是比较困难的,这块的代码不会像供普通用户使用的那样,有较好的提示和保护,你得先靠自己搞清楚其他协议中的类似代码,然后再动手,最后发给我们做code review。 @@ -141,7 +141,7 @@ typedef const std::string& (*GetMethodName)(const google::protobuf::MethodDescri ## 注册到全局 -实现好的协议要调用RegisterProtocol[注册到全局](https://github.com/brpc/brpc/blob/master/src/brpc/global.cpp),以便brpc发现。就像这样: +实现好的协议要调用RegisterProtocol[注册到全局](https://github.com/apache/brpc/blob/master/src/brpc/global.cpp),以便brpc发现。就像这样: ```c++ Protocol http_protocol = { ParseHttpMessage, SerializeHttpRequest, PackHttpRequest, diff --git a/docs/cn/nshead_service.md b/docs/cn/nshead_service.md index db18bed962..baad1e8790 100644 --- a/docs/cn/nshead_service.md +++ b/docs/cn/nshead_service.md @@ -10,7 +10,7 @@ ubrpc协议的基本形式是nshead+compack或mcpack2,但compack或mcpack2中 ## 把idl文件转化为proto文件 -使用脚本[idl2proto](https://github.com/brpc/brpc/blob/master/tools/idl2proto)把idl文件自动转化为proto文件,下面是转化后的proto文件。 +使用脚本[idl2proto](https://github.com/apache/brpc/blob/master/tools/idl2proto)把idl文件自动转化为proto文件,下面是转化后的proto文件。 ```protobuf // Converted from echo.idl by brpc/tools/idl2proto @@ -119,11 +119,11 @@ brpc::ServerOptions option; option.nshead_service = new brpc::policy::UbrpcCompackAdaptor; // mcpack2用UbrpcMcpack2Adaptor ``` -例子见[example/echo_c++_ubrpc_compack](https://github.com/brpc/brpc/blob/master/example/echo_c++_ubrpc_compack/)。 +例子见[example/echo_c++_ubrpc_compack](https://github.com/apache/brpc/blob/master/example/echo_c++_ubrpc_compack/)。 # 使用nshead+blob的服务 -[NsheadService](https://github.com/brpc/brpc/blob/master/src/brpc/nshead_service.h)是brpc中所有处理nshead打头协议的基类,实现好的NsheadService实例得赋值给ServerOptions.nshead_service才能发挥作用。不赋值的话,默认是NULL,代表不支持任何nshead开头的协议,这个server被nshead开头的数据包访问时会报错。明显地,**一个Server只能处理一种以nshead开头的协议。** +[NsheadService](https://github.com/apache/brpc/blob/master/src/brpc/nshead_service.h)是brpc中所有处理nshead打头协议的基类,实现好的NsheadService实例得赋值给ServerOptions.nshead_service才能发挥作用。不赋值的话,默认是NULL,代表不支持任何nshead开头的协议,这个server被nshead开头的数据包访问时会报错。明显地,**一个Server只能处理一种以nshead开头的协议。** NsheadService的接口如下,基本上用户只需要实现`ProcessNsheadRequest`这个函数。 @@ -159,11 +159,11 @@ public: }; ``` -完整的example在[example/nshead_extension_c++](https://github.com/brpc/brpc/tree/master/example/nshead_extension_c++/)。 +完整的example在[example/nshead_extension_c++](https://github.com/apache/brpc/tree/master/example/nshead_extension_c++/)。 # 使用nshead+mcpack/compack/idl的服务 -idl是mcpack/compack的前端,用户只要在idl文件中描述schema,就可以生成一些C++结构体,这些结构体可以打包为mcpack/compack。如果你的服务仍在大量地使用idl生成的结构体,且短期内难以修改,同时想要使用brpc提升性能和开发效率的话,可以实现[NsheadService](https://github.com/brpc/brpc/blob/master/src/brpc/nshead_service.h),其接口接受nshead + 二进制包为request,用户填写自己的处理逻辑,最后的response也是nshead+二进制包。流程与protobuf方法保持一致,但过程中不涉及任何protobuf的序列化和反序列化,用户可以自由地理解nshead后的二进制包,包括用idl加载mcpack/compack数据包。 +idl是mcpack/compack的前端,用户只要在idl文件中描述schema,就可以生成一些C++结构体,这些结构体可以打包为mcpack/compack。如果你的服务仍在大量地使用idl生成的结构体,且短期内难以修改,同时想要使用brpc提升性能和开发效率的话,可以实现[NsheadService](https://github.com/apache/brpc/blob/master/src/brpc/nshead_service.h),其接口接受nshead + 二进制包为request,用户填写自己的处理逻辑,最后的response也是nshead+二进制包。流程与protobuf方法保持一致,但过程中不涉及任何protobuf的序列化和反序列化,用户可以自由地理解nshead后的二进制包,包括用idl加载mcpack/compack数据包。 不过,你应当充分意识到这么改造的坏处: @@ -173,7 +173,7 @@ idl是mcpack/compack的前端,用户只要在idl文件中描述schema,就可 # 使用nshead+protobuf的服务 -如果你的协议已经使用了nshead + protobuf,或者你想把你的协议适配为protobuf格式,那可以使用另一种模式:实现[NsheadPbServiceAdaptor](https://github.com/brpc/brpc/blob/master/src/brpc/nshead_pb_service_adaptor.h)(NsheadService的子类)。 +如果你的协议已经使用了nshead + protobuf,或者你想把你的协议适配为protobuf格式,那可以使用另一种模式:实现[NsheadPbServiceAdaptor](https://github.com/apache/brpc/blob/master/src/brpc/nshead_pb_service_adaptor.h)(NsheadService的子类)。 工作步骤: @@ -181,7 +181,7 @@ idl是mcpack/compack的前端,用户只要在idl文件中描述schema,就可 - Call ParseRequestFromIOBuf() to convert the body after nshead header to pb request, then call the pb method. - When user calls server's done to end the RPC, SerializeResponseToIOBuf() is called to convert pb response to binary data that will be appended after nshead header and sent back to client. -这样做的好处是,这个服务还可以被其他使用protobuf的协议访问,比如baidu_std,hulu_pbrpc,sofa_pbrpc协议等等。NsheadPbServiceAdaptor的主要接口如下。完整的example在[这里](https://github.com/brpc/brpc/tree/master/example/nshead_pb_extension_c++/)。 +这样做的好处是,这个服务还可以被其他使用protobuf的协议访问,比如baidu_std,hulu_pbrpc,sofa_pbrpc协议等等。NsheadPbServiceAdaptor的主要接口如下。完整的example在[这里](https://github.com/apache/brpc/tree/master/example/nshead_pb_extension_c++/)。 ```c++ class NsheadPbServiceAdaptor : public NsheadService { diff --git a/docs/cn/overview.md b/docs/cn/overview.md index a5a06288a6..3595998ec9 100644 --- a/docs/cn/overview.md +++ b/docs/cn/overview.md @@ -44,7 +44,7 @@ RPC不是万能的抽象,否则我们也不需要TCP/IP这一层了。但是 * 搭建能在**一个端口**支持多协议的服务, 或访问各种服务 * restful http/https, [h2](https://http2.github.io/http2-spec)/[gRPC](https://grpc.io)。使用brpc的http实现比[libcurl](https://curl.haxx.se/libcurl/)方便多了。从其他语言通过HTTP/h2+json访问基于protobuf的协议. * [redis](redis_client.md)和[memcached](memcache_client.md), 线程安全,比官方client更方便。 - * [rtmp](https://github.com/brpc/brpc/blob/master/src/brpc/rtmp.h)/[flv](https://en.wikipedia.org/wiki/Flash_Video)/[hls](https://en.wikipedia.org/wiki/HTTP_Live_Streaming), 可用于搭建[流媒体服务](https://github.com/brpc/media-server). + * [rtmp](https://github.com/apache/brpc/blob/master/src/brpc/rtmp.h)/[flv](https://en.wikipedia.org/wiki/Flash_Video)/[hls](https://en.wikipedia.org/wiki/HTTP_Live_Streaming), 可用于搭建[流媒体服务](https://github.com/brpc/media-server). * hadoop_rpc(可能开源) * 支持[rdma](https://en.wikipedia.org/wiki/Remote_direct_memory_access)(即将开源) * 支持[thrift](thrift.md) , 线程安全,比官方client更方便 @@ -60,11 +60,11 @@ RPC不是万能的抽象,否则我们也不需要TCP/IP这一层了。但是 ### 更友好的接口 -只有三个(主要的)用户类: [Server](https://github.com/brpc/brpc/blob/master/src/brpc/server.h), [Channel](https://github.com/brpc/brpc/blob/master/src/brpc/channel.h), [Controller](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h), 分别对应server端,client端,参数集合. 你不必推敲诸如"如何初始化XXXManager", "如何组合各种组件", "XXXController的XXXContext间的关系是什么"。要做的很简单: +只有三个(主要的)用户类: [Server](https://github.com/apache/brpc/blob/master/src/brpc/server.h), [Channel](https://github.com/apache/brpc/blob/master/src/brpc/channel.h), [Controller](https://github.com/apache/brpc/blob/master/src/brpc/controller.h), 分别对应server端,client端,参数集合. 你不必推敲诸如"如何初始化XXXManager", "如何组合各种组件", "XXXController的XXXContext间的关系是什么"。要做的很简单: -* 建服务? 包含[brpc/server.h](https://github.com/brpc/brpc/blob/master/src/brpc/server.h)并参考注释或[示例](https://github.com/brpc/brpc/blob/master/example/echo_c++/server.cpp). -* 访问服务? 包含[brpc/channel.h](https://github.com/brpc/brpc/blob/master/src/brpc/channel.h)并参考注释或[示例](https://github.com/brpc/brpc/blob/master/example/echo_c++/client.cpp). -* 调整参数? 看看[brpc/controller.h](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h). 注意这个类是Server和Channel共用的,分成了三段,分别标记为Client-side, Server-side和Both-side methods。 +* 建服务? 包含[brpc/server.h](https://github.com/apache/brpc/blob/master/src/brpc/server.h)并参考注释或[示例](https://github.com/apache/brpc/blob/master/example/echo_c++/server.cpp). +* 访问服务? 包含[brpc/channel.h](https://github.com/apache/brpc/blob/master/src/brpc/channel.h)并参考注释或[示例](https://github.com/apache/brpc/blob/master/example/echo_c++/client.cpp). +* 调整参数? 看看[brpc/controller.h](https://github.com/apache/brpc/blob/master/src/brpc/controller.h). 注意这个类是Server和Channel共用的,分成了三段,分别标记为Client-side, Server-side和Both-side methods。 我们尝试让事情变得更加简单,以命名服务为例,在其他RPC实现中,你也许需要复制一长段晦涩的代码才可使用,而在brpc中访问BNS可以这么写`"bns://node-name"`,DNS是`"http://domain-name"`,本地文件列表是`"file:///home/work/server.list"`,相信不用解释,你也能明白这些代表什么。 diff --git a/docs/cn/redis_client.md b/docs/cn/redis_client.md index c0abbe62a7..52409706b2 100644 --- a/docs/cn/redis_client.md +++ b/docs/cn/redis_client.md @@ -1,6 +1,6 @@ [English version](../en/redis_client.md) -[redis](http://redis.io/)是最近几年比较火的缓存服务,相比memcached在server端提供了更多的数据结构和操作方法,简化了用户的开发工作。为了使用户更快捷地访问redis并充分利用bthread的并发能力,brpc直接支持redis协议。示例程序:[example/redis_c++](https://github.com/brpc/brpc/tree/master/example/redis_c++/) +[redis](http://redis.io/)是最近几年比较火的缓存服务,相比memcached在server端提供了更多的数据结构和操作方法,简化了用户的开发工作。为了使用户更快捷地访问redis并充分利用bthread的并发能力,brpc直接支持redis协议。示例程序:[example/redis_c++](https://github.com/apache/brpc/tree/master/example/redis_c++/) 相比使用[hiredis](https://github.com/redis/hiredis)(官方client)的优势有: @@ -116,7 +116,7 @@ options.auth = auth; # RedisRequest -一个[RedisRequest](https://github.com/brpc/brpc/blob/master/src/brpc/redis.h)可包含多个Command,调用AddCommand*增加命令,成功返回true,失败返回false**并会打印调用处的栈**。 +一个[RedisRequest](https://github.com/apache/brpc/blob/master/src/brpc/redis.h)可包含多个Command,调用AddCommand*增加命令,成功返回true,失败返回false**并会打印调用处的栈**。 ```c++ bool AddCommand(const char* fmt, ...); @@ -136,7 +136,7 @@ command_size()可获得(成功)加入的命令个数。 # RedisResponse -[RedisResponse](https://github.com/brpc/brpc/blob/master/src/brpc/redis.h)可能包含一个或多个[RedisReply](https://github.com/brpc/brpc/blob/master/src/brpc/redis_reply.h),reply_size()可获得reply的个数,reply(i)可获得第i个reply的引用(从0计数)。注意在hiredis中,如果请求包含了N个command,获取结果也要调用N次redisGetReply。但在brpc中这是不必要的,RedisResponse已经包含了N个reply,通过reply(i)获取就行了。只要RPC成功,response.reply_size()应与request.command_size()相等,除非redis-server有bug,redis-server工作的基本前提就是reply和command按序一一对应。 +[RedisResponse](https://github.com/apache/brpc/blob/master/src/brpc/redis.h)可能包含一个或多个[RedisReply](https://github.com/apache/brpc/blob/master/src/brpc/redis_reply.h),reply_size()可获得reply的个数,reply(i)可获得第i个reply的引用(从0计数)。注意在hiredis中,如果请求包含了N个command,获取结果也要调用N次redisGetReply。但在brpc中这是不必要的,RedisResponse已经包含了N个reply,通过reply(i)获取就行了。只要RPC成功,response.reply_size()应与request.command_size()相等,除非redis-server有bug,redis-server工作的基本前提就是reply和command按序一一对应。 每个reply可能是: @@ -238,7 +238,7 @@ TRACE: 02-13 18:07:42: * 0 client.cpp:180] Accessing redis server at qps=75238 # Command Line Interface -[example/redis_c++/redis_cli](https://github.com/brpc/brpc/blob/master/example/redis_c%2B%2B/redis_cli.cpp)是一个类似于官方CLI的命令行工具,以展示brpc对redis协议的处理能力。当使用brpc访问redis-server出现不符合预期的行为时,也可以使用这个CLI进行交互式的调试。 +[example/redis_c++/redis_cli](https://github.com/apache/brpc/blob/master/example/redis_c%2B%2B/redis_cli.cpp)是一个类似于官方CLI的命令行工具,以展示brpc对redis协议的处理能力。当使用brpc访问redis-server出现不符合预期的行为时,也可以使用这个CLI进行交互式的调试。 和官方CLI类似,`redis_cli `也可以直接运行命令,-server参数可以指定redis-server的地址。 diff --git a/docs/cn/rpc_replay.md b/docs/cn/rpc_replay.md index 973ca21064..d1b23af8ea 100644 --- a/docs/cn/rpc_replay.md +++ b/docs/cn/rpc_replay.md @@ -21,7 +21,7 @@ brpc通过如下flags打开和控制如何保存请求,包含(R)后缀的flag - -rpc_dump_max_files: 设置目录下的最大文件数,当超过限制时,老文件会被删除以腾出空间。 - -rpc_dump_max_requests_in_one_file:一个文件内的最大请求数,超过后写新文件。 -brpc通过一个[bvar::Collector](https://github.com/brpc/brpc/blob/master/src/bvar/collector.h)来汇总来自不同线程的被采样请求,不同线程之间没有竞争,开销很小。 +brpc通过一个[bvar::Collector](https://github.com/apache/brpc/blob/master/src/bvar/collector.h)来汇总来自不同线程的被采样请求,不同线程之间没有竞争,开销很小。 写出的内容依次存放在rpc_dump_dir目录下的多个文件内,这个目录默认在./rpc_dump_,其中是程序名。不同程序在同一个目录下同时采样时会写入不同的目录。如果程序启动时rpc_dump_dir已经存在了,目录将被清空。目录中的每个文件以requests.yyyymmdd_hhmmss_uuuuus命名,以保证按时间有序方便查找,比如: @@ -43,7 +43,7 @@ serialized request (body_size - meta_size bytes, including attachment) > 一个文件可能包含多种协议的请求,如果server被多种协议访问的话。回放时被请求的server也将收到不同协议的请求。 -brpc提供了[SampleIterator](https://github.com/brpc/brpc/blob/master/src/brpc/rpc_dump.h)从一个采样目录下的所有文件中依次读取所有的被采样请求,用户可根据需求把serialized request反序列化为protobuf请求,做一些二次开发。 +brpc提供了[SampleIterator](https://github.com/apache/brpc/blob/master/src/brpc/rpc_dump.h)从一个采样目录下的所有文件中依次读取所有的被采样请求,用户可根据需求把serialized request反序列化为protobuf请求,做一些二次开发。 ```c++ #include @@ -59,7 +59,7 @@ for (brpc::SampledRequest* req = it->Next(); req != NULL; req = it->Next()) { # 回放 -brpc在[tools/rpc_replay](https://github.com/brpc/brpc/tree/master/tools/rpc_replay/)提供了默认的回放工具。运行方式如下: +brpc在[tools/rpc_replay](https://github.com/apache/brpc/tree/master/tools/rpc_replay/)提供了默认的回放工具。运行方式如下: ![img](../images/rpc_replay_4.png) diff --git a/docs/cn/rpcz.md b/docs/cn/rpcz.md index e84158da3c..b2808da268 100644 --- a/docs/cn/rpcz.md +++ b/docs/cn/rpcz.md @@ -48,7 +48,7 @@ ## Annotation -只要你使用了brpc,就可以使用[TRACEPRINTF](https://github.com/brpc/brpc/blob/master/src/brpc/traceprintf.h)打印内容到事件流中,比如: +只要你使用了brpc,就可以使用[TRACEPRINTF](https://github.com/apache/brpc/blob/master/src/brpc/traceprintf.h)打印内容到事件流中,比如: ```c++ TRACEPRINTF("Hello rpcz %d", 123); diff --git a/docs/cn/server.md b/docs/cn/server.md index bec63baba4..5fa88f4f83 100644 --- a/docs/cn/server.md +++ b/docs/cn/server.md @@ -2,7 +2,7 @@ # 示例程序 -Echo的[server端代码](https://github.com/brpc/brpc/blob/master/example/echo_c++/server.cpp)。 +Echo的[server端代码](https://github.com/apache/brpc/blob/master/example/echo_c++/server.cpp)。 # 填写proto文件 @@ -50,13 +50,13 @@ public: }; ``` -Service在插入[brpc.Server](https://github.com/brpc/brpc/blob/master/src/brpc/server.h)后才可能提供服务。 +Service在插入[brpc.Server](https://github.com/apache/brpc/blob/master/src/brpc/server.h)后才可能提供服务。 当客户端发来请求时,Echo()会被调用。参数的含义分别是: **controller** -在brpc中可以静态转为brpc::Controller(前提是代码运行brpc.Server中),包含了所有request和response之外的参数集合,具体接口查阅[controller.h](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h) +在brpc中可以静态转为brpc::Controller(前提是代码运行brpc.Server中),包含了所有request和response之外的参数集合,具体接口查阅[controller.h](https://github.com/apache/brpc/blob/master/src/brpc/controller.h) **request** @@ -135,7 +135,7 @@ public: 调用Controller.SetFailed()可以把当前调用设置为失败,当发送过程出现错误时,框架也会调用这个函数。用户一般是在服务的CallMethod里调用这个函数,比如某个处理环节出错,SetFailed()后确认done->Run()被调用了就可以跳出函数了(若使用了ClosureGuard,跳出函数时会自动调用done,不用手动)。Server端的done的逻辑主要是发送response回client,当其发现用户调用了SetFailed()后,会把错误信息送回client。client收到后,它的Controller::Failed()会为true(成功时为false),Controller::ErrorCode()和Controller::ErrorText()则分别是错误码和错误信息。 -用户可以为http访问设置[status-code](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html),在server端一般是调用`controller.http_response().set_status_code()`,标准的status-code定义在[http_status_code.h](https://github.com/brpc/brpc/blob/master/src/brpc/http_status_code.h)中。Controller.SetFailed也会设置status-code,值是与错误码含义最接近的status-code,没有相关的则填500错误(brpc::HTTP_STATUS_INTERNAL_SERVER_ERROR)。如果你要覆盖status_code,设置代码一定要放在SetFailed()后,而不是之前。 +用户可以为http访问设置[status-code](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html),在server端一般是调用`controller.http_response().set_status_code()`,标准的status-code定义在[http_status_code.h](https://github.com/apache/brpc/blob/master/src/brpc/http_status_code.h)中。Controller.SetFailed也会设置status-code,值是与错误码含义最接近的status-code,没有相关的则填500错误(brpc::HTTP_STATUS_INTERNAL_SERVER_ERROR)。如果你要覆盖status_code,设置代码一定要放在SetFailed()后,而不是之前。 ## 获取Client的地址 @@ -165,7 +165,7 @@ printf("local_side=%s\n", butil::endpoint2str(cntl->local_side()).c_str()); 有些server以等待后端服务返回结果为主,且处理时间特别长,为了及时地释放出线程资源,更好的办法是把done注册到被等待事件的回调中,等到事件发生后再调用done->Run()。 -异步service的最后一行一般是done_guard.release()以确保正常退出CallMethod时不会调用done->Run()。例子请看[example/session_data_and_thread_local](https://github.com/brpc/brpc/tree/master/example/session_data_and_thread_local/)。 +异步service的最后一行一般是done_guard.release()以确保正常退出CallMethod时不会调用done->Run()。例子请看[example/session_data_and_thread_local](https://github.com/apache/brpc/tree/master/example/session_data_and_thread_local/)。 Service和Channel都可以使用done来表达后续的操作,但它们是**完全不同**的,请勿混淆: @@ -201,7 +201,7 @@ Server启动后你无法再修改其中的Service。 # 启动 -调用以下[Server](https://github.com/brpc/brpc/blob/master/src/brpc/server.h)的接口启动服务。 +调用以下[Server](https://github.com/apache/brpc/blob/master/src/brpc/server.h)的接口启动服务。 ```c++ int Start(const char* ip_and_port_str, const ServerOptions* opt); @@ -263,7 +263,7 @@ Join()完成后可以修改其中的Service,并重新Start。 使用Protobuf的服务通常可以通过http/h2+json访问,存于body的json串可与对应protobuf消息相互自动转化。 -以[echo server](https://github.com/brpc/brpc/blob/master/example/echo_c%2B%2B/server.cpp)为例,你可以用[curl](https://curl.haxx.se/)访问这个服务。 +以[echo server](https://github.com/apache/brpc/blob/master/example/echo_c%2B%2B/server.cpp)为例,你可以用[curl](https://curl.haxx.se/)访问这个服务。 ```shell # -H 'Content-Type: application/json' is optional @@ -384,13 +384,13 @@ Server.set_version(...)可以为server设置一个名称+版本,可通过/vers ## 在每条日志后打印hostname -此功能只对[butil/logging.h](https://github.com/brpc/brpc/blob/master/src/butil/logging.h)中的日志宏有效。 +此功能只对[butil/logging.h](https://github.com/apache/brpc/blob/master/src/butil/logging.h)中的日志宏有效。 打开[-log_hostname](http://brpc.baidu.com:8765/flags/log_hostname)后每条日志后都会带本机名称,如果所有的日志需要汇总到一起进行分析,这个功能可以帮助你了解某条日志来自哪台机器。 ## 打印FATAL日志后退出程序 -此功能只对[butil/logging.h](https://github.com/brpc/brpc/blob/master/src/butil/logging.h)中的日志宏有效,glog默认在FATAL日志时crash。 +此功能只对[butil/logging.h](https://github.com/apache/brpc/blob/master/src/butil/logging.h)中的日志宏有效,glog默认在FATAL日志时crash。 打开[-crash_on_fatal_log](http://brpc.baidu.com:8765/flags/crash_on_fatal_log)后如果程序使用LOG(FATAL)打印了异常日志或违反了CHECK宏中的断言,那么程序会在打印日志后abort,这一般也会产生coredump文件,默认不打开。这个开关可在对程序的压力测试中打开,以确认程序没有进入过严重错误的分支。 @@ -398,7 +398,7 @@ Server.set_version(...)可以为server设置一个名称+版本,可通过/vers ## 最低日志级别 -此功能由[butil/logging.h](https://github.com/brpc/brpc/blob/master/src/butil/logging.h)和glog各自实现,为同名选项。 +此功能由[butil/logging.h](https://github.com/apache/brpc/blob/master/src/butil/logging.h)和glog各自实现,为同名选项。 只有**不低于**-minloglevel指定的日志级别的日志才会被打印。这个选项可以动态修改。设置值和日志级别的对应关系:0=INFO 1=NOTICE 2=WARNING 3=ERROR 4=FATAL,默认为0。 @@ -480,7 +480,7 @@ baidu_std和hulu_pbrpc协议支持传递附件,这段数据由用户自定义 ## 开启SSL -要开启SSL,首先确保代码依赖了最新的openssl库。如果openssl版本很旧,会有严重的安全漏洞,支持的加密算法也少,违背了开启SSL的初衷。然后设置`ServerOptions.ssl_options`,具体见[ssl_options.h](https://github.com/brpc/brpc/blob/master/src/brpc/ssl_options.h)。 +要开启SSL,首先确保代码依赖了最新的openssl库。如果openssl版本很旧,会有严重的安全漏洞,支持的加密算法也少,违背了开启SSL的初衷。然后设置`ServerOptions.ssl_options`,具体见[ssl_options.h](https://github.com/apache/brpc/blob/master/src/brpc/ssl_options.h)。 ```c++ // Certificate structure @@ -709,7 +709,7 @@ curl -s -m 1 :/flags/enable_dir_service,enable_threads_service | ## 定制/health页面 -/health页面默认返回"OK",若需定制/health页面的内容:先继承[HealthReporter](https://github.com/brpc/brpc/blob/master/src/brpc/health_reporter.h),在其中实现生成页面的逻辑(就像实现其他http service那样),然后把实例赋给ServerOptions.health_reporter,这个实例不被server拥有,必须保证在server运行期间有效。用户在定制逻辑中可以根据业务的运行状态返回更多样的状态信息。 +/health页面默认返回"OK",若需定制/health页面的内容:先继承[HealthReporter](https://github.com/apache/brpc/blob/master/src/brpc/health_reporter.h),在其中实现生成页面的逻辑(就像实现其他http service那样),然后把实例赋给ServerOptions.health_reporter,这个实例不被server拥有,必须保证在server运行期间有效。用户在定制逻辑中可以根据业务的运行状态返回更多样的状态信息。 ## 线程私有变量 @@ -770,7 +770,7 @@ struct ServerOptions { }; ``` -session_local_data_factory的类型为[DataFactory](https://github.com/brpc/brpc/blob/master/src/brpc/data_factory.h),你需要实现其中的CreateData和DestroyData。 +session_local_data_factory的类型为[DataFactory](https://github.com/apache/brpc/blob/master/src/brpc/data_factory.h),你需要实现其中的CreateData和DestroyData。 注意:CreateData和DestroyData会被多个线程同时调用,必须线程安全。 @@ -861,7 +861,7 @@ struct ServerOptions { }; ``` -thread_local_data_factory的类型为[DataFactory](https://github.com/brpc/brpc/blob/master/src/brpc/data_factory.h),你需要实现其中的CreateData和DestroyData。 +thread_local_data_factory的类型为[DataFactory](https://github.com/apache/brpc/blob/master/src/brpc/data_factory.h),你需要实现其中的CreateData和DestroyData。 注意:CreateData和DestroyData会被多个线程同时调用,必须线程安全。 diff --git a/docs/cn/status.md b/docs/cn/status.md index 8f4b916cf3..a9acdb01f3 100644 --- a/docs/cn/status.md +++ b/docs/cn/status.md @@ -20,7 +20,7 @@ - **processing**: (新版改名为concurrency)正在处理的请求个数。在压力归0后若此指标仍持续不为0,server则很有可能bug,比如忘记调用done了或卡在某个处理步骤上了。 -用户可通过让对应Service实现[brpc::Describable](https://github.com/brpc/brpc/blob/master/src/brpc/describable.h)自定义在/status页面上的描述. +用户可通过让对应Service实现[brpc::Describable](https://github.com/apache/brpc/blob/master/src/brpc/describable.h)自定义在/status页面上的描述. ```c++ class MyService : public XXXService, public brpc::Describable { diff --git a/docs/cn/streaming_rpc.md b/docs/cn/streaming_rpc.md index 14a44c22c8..01c7241dff 100644 --- a/docs/cn/streaming_rpc.md +++ b/docs/cn/streaming_rpc.md @@ -19,7 +19,7 @@ Streaming RPC保证: 目前的实现还没有自动切割过大的消息,同一个tcp连接上的多个Stream之间可能有[Head-of-line blocking](https://en.wikipedia.org/wiki/Head-of-line_blocking)问题,请尽量避免过大的单个消息,实现自动切割后我们会告知并更新文档。 -例子见[example/streaming_echo_c++](https://github.com/brpc/brpc/tree/master/example/streaming_echo_c++/)。 +例子见[example/streaming_echo_c++](https://github.com/apache/brpc/tree/master/example/streaming_echo_c++/)。 # 建立Stream diff --git a/docs/cn/thrift.md b/docs/cn/thrift.md index 957cea5453..45275ea7d9 100755 --- a/docs/cn/thrift.md +++ b/docs/cn/thrift.md @@ -2,7 +2,7 @@ [thrift](https://thrift.apache.org/)是应用较广的RPC框架,最初由Facebook发布,后交由Apache维护。为了和thrift服务互通,同时解决thrift原生方案在多线程安全、易用性、并发能力等方面的一系列问题,brpc实现并支持thrift在NonBlocking模式下的协议(FramedProtocol), 下文均直接称为thrift协议。 -示例程序:[example/thrift_extension_c++](https://github.com/brpc/brpc/tree/master/example/thrift_extension_c++/) +示例程序:[example/thrift_extension_c++](https://github.com/apache/brpc/tree/master/example/thrift_extension_c++/) 相比使用原生方案的优势有: - 线程安全。用户不需要为每个线程建立独立的client. diff --git a/docs/cn/timeout_concurrency_limiter.md b/docs/cn/timeout_concurrency_limiter.md index 7da715a92b..c9b00fbabe 100644 --- a/docs/cn/timeout_concurrency_limiter.md +++ b/docs/cn/timeout_concurrency_limiter.md @@ -4,7 +4,7 @@ 如果服务持续过载,会导致越来越多的请求积压,最终所有的请求都必须等待较长时间才能被处理,从而使整个服务处于瘫痪状态。 -与之相对的,如果直接拒绝掉一部分请求,反而能够让服务能够"及时"处理更多的请求。对应的方法就是[设置最大并发](https://github.com/brpc/brpc/blob/master/docs/cn/server.md#%E9%99%90%E5%88%B6%E6%9C%80%E5%A4%A7%E5%B9%B6%E5%8F%91)。 +与之相对的,如果直接拒绝掉一部分请求,反而能够让服务能够"及时"处理更多的请求。对应的方法就是[设置最大并发](https://github.com/apache/brpc/blob/master/docs/cn/server.md#%E9%99%90%E5%88%B6%E6%9C%80%E5%A4%A7%E5%B9%B6%E5%8F%91)。 ## 算法描述 diff --git a/docs/cn/timer_keeping.md b/docs/cn/timer_keeping.md index 4ca4df460e..31f82e82ff 100644 --- a/docs/cn/timer_keeping.md +++ b/docs/cn/timer_keeping.md @@ -34,7 +34,7 @@ - 删除时通过id直接定位到timer内存结构,修改一个标志,timer结构总是由TimerThread释放。 - TimerThread被唤醒后首先把全局nearest_run_time设置为几乎无限大(max of int64),然后取出所有Bucket内的链表,并把Bucket的nearest_run_time设置为几乎无限大(max of int64)。TimerThread把未删除的timer插入小顶堆中维护,这个堆就它一个线程用。在每次运行回调或准备睡眠前都会检查全局nearest_run_time, 如果全局更早,说明有更早的时间加入了,重复这个过程。 -这里勾勒了TimerThread的大致工作原理,工程实现中还有不少细节问题,具体请阅读[timer_thread.h](https://github.com/brpc/brpc/blob/master/src/bthread/timer_thread.h)和[timer_thread.cpp](https://github.com/brpc/brpc/blob/master/src/bthread/timer_thread.cpp)。 +这里勾勒了TimerThread的大致工作原理,工程实现中还有不少细节问题,具体请阅读[timer_thread.h](https://github.com/apache/brpc/blob/master/src/bthread/timer_thread.h)和[timer_thread.cpp](https://github.com/apache/brpc/blob/master/src/bthread/timer_thread.cpp)。 这个方法之所以有效: diff --git a/docs/cn/ub_client.md b/docs/cn/ub_client.md index cbfe9f95a2..f020b39195 100644 --- a/docs/cn/ub_client.md +++ b/docs/cn/ub_client.md @@ -6,7 +6,7 @@ r31687后,brpc支持通过protobuf访问ubrpc,不需要baidu-rpc-ub,也不 **步骤:** -1. 用[idl2proto](https://github.com/brpc/brpc/blob/master/tools/idl2proto)把idl文件转化为proto文件,老版本idl2proto不会转化idl中的service,需要手动转化。 +1. 用[idl2proto](https://github.com/apache/brpc/blob/master/tools/idl2proto)把idl文件转化为proto文件,老版本idl2proto不会转化idl中的service,需要手动转化。 ```protobuf // Converted from echo.idl by brpc/tools/idl2proto @@ -141,7 +141,7 @@ r31687后,brpc支持通过protobuf访问ubrpc,不需要baidu-rpc-ub,也不 // cntl.idl_result(); ``` - 例子详见[example/echo_c++_ubrpc_compack](https://github.com/brpc/brpc/blob/master/example/echo_c++_ubrpc_compack/)。 + 例子详见[example/echo_c++_ubrpc_compack](https://github.com/apache/brpc/blob/master/example/echo_c++_ubrpc_compack/)。 # ubrpc (by baidu-rpc-ub) @@ -214,7 +214,7 @@ server端由public/ubrpc搭建,request/response使用idl文件描述字段, ... ``` - 具体example代码可以参考[echo_c++_compack_ubrpc](https://github.com/brpc/brpc/tree/master/example/echo_c++_compack_ubrpc/),类似的还有[echo_c++_mcpack_ubrpc](https://github.com/brpc/brpc/tree/master/example/echo_c++_mcpack_ubrpc/)。 + 具体example代码可以参考[echo_c++_compack_ubrpc](https://github.com/apache/brpc/tree/master/example/echo_c++_compack_ubrpc/),类似的还有[echo_c++_mcpack_ubrpc](https://github.com/apache/brpc/tree/master/example/echo_c++_mcpack_ubrpc/)。 # nshead+idl @@ -253,7 +253,7 @@ channel.CallMethod(NULL, &cntl, &request, &response, NULL); // 假设channel response.message(); ``` -具体example代码可以参考[echo_c++_mcpack_ub](https://github.com/brpc/brpc/blob/master/example/echo_c++_mcpack_ub/),compack情况类似,不再赘述 +具体example代码可以参考[echo_c++_mcpack_ub](https://github.com/apache/brpc/blob/master/example/echo_c++_mcpack_ub/),compack情况类似,不再赘述 # nshead+mcpack(非idl产生的) @@ -300,11 +300,11 @@ const mc_pack_t* res_pack = response.McpackHandle(); mc_pack_get_str(res_pack, "mystr"); ``` -具体example代码可以参考[echo_c++_raw_mcpack](https://github.com/brpc/brpc/blob/master/example/echo_c++_raw_mcpack/)。 +具体example代码可以参考[echo_c++_raw_mcpack](https://github.com/apache/brpc/blob/master/example/echo_c++_raw_mcpack/)。 # nshead+blob -r32897后brpc直接支持用nshead+blob访问老server(而不用依赖baidu-rpc-ub)。example代码可以参考[nshead_extension_c++](https://github.com/brpc/brpc/blob/master/example/nshead_extension_c++/client.cpp)。 +r32897后brpc直接支持用nshead+blob访问老server(而不用依赖baidu-rpc-ub)。example代码可以参考[nshead_extension_c++](https://github.com/apache/brpc/blob/master/example/nshead_extension_c++/client.cpp)。 ```c++ #include @@ -337,7 +337,7 @@ if (cntl.Failed()) { // response.head and response.body contains nshead_t and blob respectively. ``` -或者用户也可以使用baidu-rpc-ub中的UBRawBufferRequest和UBRawBufferResponse来访问。example代码可以参考[echo_c++_raw_buffer](https://github.com/brpc/brpc/blob/master/example/echo_c++_raw_buffer/)。 +或者用户也可以使用baidu-rpc-ub中的UBRawBufferRequest和UBRawBufferResponse来访问。example代码可以参考[echo_c++_raw_buffer](https://github.com/apache/brpc/blob/master/example/echo_c++_raw_buffer/)。 ```c++ brpc::Channel channel; diff --git a/docs/en/backup_request.md b/docs/en/backup_request.md index 1cdb9dbb4d..8e1a337c41 100644 --- a/docs/en/backup_request.md +++ b/docs/en/backup_request.md @@ -4,7 +4,7 @@ Sometimes in order to ensure availability, we need to visit two services at the Channel opens backup request. Channel sends the request to one of the servers and when the response is not returned after ChannelOptions.backup_request_ms ms, it sends to another server, taking the response that coming back first. After backup_request_ms is set up properly, in most of times only one request should be sent, causing no extra pressure to back-end services. -Read [example/backup_request_c++](https://github.com/brpc/brpc/blob/master/example/backup_request_c++) as example code. In this example, client sends backup request after 2ms and server sleeps for 20ms on purpose when the number of requests is even to trigger backup request. +Read [example/backup_request_c++](https://github.com/apache/brpc/blob/master/example/backup_request_c++) as example code. In this example, client sends backup request after 2ms and server sleeps for 20ms on purpose when the number of requests is even to trigger backup request. After running, the log in client and server is as following. "Index" is the number of request. After the server receives the first request, it will sleep for 20ms on purpose. Then the client sends the request with the same index. The final delay is not affected by the intentional sleep. @@ -41,6 +41,6 @@ my_func_latency << tm.u_elapsed(); // u represents for microsecond, and s_elaps # When backend servers cannot be hung in a naming service -[Recommended] Define a SelectiveChannel that sets backup request, in which contains two sub channel. The visiting process of this SelectiveChannel is similar to the above situation. It will visit one sub channel first. If the response is not returned after channelOptions.backup_request_ms ms, then another sub channel is visited. If a sub channel corresponds to a cluster, this method does backups between two clusters. An example of SelectiveChannel can be found in [example/selective_echo_c++](https://github.com/brpc/brpc/tree/master/example/selective_echo_c++). More details please refer to the above program. +[Recommended] Define a SelectiveChannel that sets backup request, in which contains two sub channel. The visiting process of this SelectiveChannel is similar to the above situation. It will visit one sub channel first. If the response is not returned after channelOptions.backup_request_ms ms, then another sub channel is visited. If a sub channel corresponds to a cluster, this method does backups between two clusters. An example of SelectiveChannel can be found in [example/selective_echo_c++](https://github.com/apache/brpc/tree/master/example/selective_echo_c++). More details please refer to the above program. -[Not Recommended] Issue two asynchronous RPC calls and join them. They cancel each other in their done callback. An example is in [example/cancel_c++](https://github.com/brpc/brpc/tree/master/example/cancel_c++). The problem of this method is that the program always sends two requests, doubling the pressure to back-end services. It is uneconomical in any sense and should be avoided as much as possible. +[Not Recommended] Issue two asynchronous RPC calls and join them. They cancel each other in their done callback. An example is in [example/cancel_c++](https://github.com/apache/brpc/tree/master/example/cancel_c++). The problem of this method is that the program always sends two requests, doubling the pressure to back-end services. It is uneconomical in any sense and should be avoided as much as possible. diff --git a/docs/en/bvar.md b/docs/en/bvar.md index 2719cdded0..c2496a253a 100644 --- a/docs/en/bvar.md +++ b/docs/en/bvar.md @@ -2,7 +2,7 @@ # What is bvar? -[bvar](https://github.com/brpc/brpc/tree/master/src/bvar/) is a set of counters to record and view miscellaneous statistics conveniently in multi-threaded applications. The implementation reduces cache bouncing by storing data in thread local storage(TLS), being much faster than UbMonitor(a legacy counting library inside Baidu) and even atomic operations in highly contended scenarios. brpc integrates bvar by default, namely all exposed bvars in a server are accessible through [/vars](http://brpc.baidu.com:8765/vars), and a single bvar is addressable by [/vars/VARNAME](http://brpc.baidu.com:8765/vars/rpc_socket_count). Read [vars](vars.md) to know how to query them in brpc servers. brpc extensively use bvar to expose internal status. If you are looking for an utility to collect and display metrics of your application, consider bvar in the first place. bvar definitely can't replace all counters, essentially it moves contentions occurred during write to read: which needs to combine all data written by all threads and becomes much slower than an ordinary read. If read and write on the counter are both frequent or decisions need to be made based on latest values, you should not use bvar. +[bvar](https://github.com/apache/brpc/tree/master/src/bvar/) is a set of counters to record and view miscellaneous statistics conveniently in multi-threaded applications. The implementation reduces cache bouncing by storing data in thread local storage(TLS), being much faster than UbMonitor(a legacy counting library inside Baidu) and even atomic operations in highly contended scenarios. brpc integrates bvar by default, namely all exposed bvars in a server are accessible through [/vars](http://brpc.baidu.com:8765/vars), and a single bvar is addressable by [/vars/VARNAME](http://brpc.baidu.com:8765/vars/rpc_socket_count). Read [vars](vars.md) to know how to query them in brpc servers. brpc extensively use bvar to expose internal status. If you are looking for an utility to collect and display metrics of your application, consider bvar in the first place. bvar definitely can't replace all counters, essentially it moves contentions occurred during write to read: which needs to combine all data written by all threads and becomes much slower than an ordinary read. If read and write on the counter are both frequent or decisions need to be made based on latest values, you should not use bvar. To understand how bvar works, read [explaining cacheline](atomic_instructions.md#cacheline) first, in which the mentioned counter example is just bvar. When many threads are modifying a counter, each thread writes into its own area without joining the global contention and all private data are combined at read, which is much slower than an ordinary one, but OK for low-frequency logging or display. The much faster and very-little-overhead write enables users to monitor systems from all aspects without worrying about hurting performance. This is the purpose that we designed bvar. diff --git a/docs/en/client.md b/docs/en/client.md index 75cb504b03..358bf2f247 100644 --- a/docs/en/client.md +++ b/docs/en/client.md @@ -2,7 +2,7 @@ # Example -[client-side code](https://github.com/brpc/brpc/blob/master/example/echo_c++/client.cpp) of echo. +[client-side code](https://github.com/apache/brpc/blob/master/example/echo_c++/client.cpp) of echo. # Quick facts @@ -13,7 +13,7 @@ - No class named brpc::Client. # Channel -Client-side of RPC sends requests. It's called [Channel](https://github.com/brpc/brpc/blob/master/src/brpc/channel.h) rather than "Client" in brpc. A channel represents a communication line to one server or multiple servers, which can be used for calling services. +Client-side of RPC sends requests. It's called [Channel](https://github.com/apache/brpc/blob/master/src/brpc/channel.h) rather than "Client" in brpc. A channel represents a communication line to one server or multiple servers, which can be used for calling services. A Channel can be **shared by all threads** in the process. Yon don't need to create separate Channels for each thread, and you don't need to synchronize Channel.CallMethod with lock. However creation and destroying of Channel is **not** thread-safe, make sure the channel is initialized and destroyed only by one thread. @@ -166,7 +166,7 @@ NOTE: The value of server weight must be an integer. ### More naming services -User can extend to more naming services by implementing brpc::NamingService, check [this link](https://github.com/brpc/brpc/blob/master/docs/cn/load_balancing.md#%E5%91%BD%E5%90%8D%E6%9C%8D%E5%8A%A1) for details. +User can extend to more naming services by implementing brpc::NamingService, check [this link](https://github.com/apache/brpc/blob/master/docs/cn/load_balancing.md#%E5%91%BD%E5%90%8D%E6%9C%8D%E5%8A%A1) for details. ### The tag in naming service Every address can be attached with a tag. The common implementation is that if there're spaces after the address, the content after the spaces is the tag. @@ -264,7 +264,7 @@ which is consistent hashing. Adding or removing servers does not make destinatio Need to set Controller.set_request_code() before RPC otherwise the RPC will fail. request_code is often a 32-bit hash code of "key part" of the request, and the hashing algorithm does not need to be same with the one used by load balancer. Say `c_murmurhash` can use md5 to compute request_code of the request as well. -[src/brpc/policy/hasher.h](https://github.com/brpc/brpc/blob/master/src/brpc/policy/hasher.h) includes common hash functions. If `std::string key` stands for key part of the request, controller.set_request_code(brpc::policy::MurmurHash32(key.data(), key.size())) sets request_code correctly. +[src/brpc/policy/hasher.h](https://github.com/apache/brpc/blob/master/src/brpc/policy/hasher.h) includes common hash functions. If `std::string key` stands for key part of the request, controller.set_request_code(brpc::policy::MurmurHash32(key.data(), key.size())) sets request_code correctly. Do distinguish "key" and "attributes" of the request. Don't compute request_code by full content of the request just for quick. Minor change in attributes may result in totally different hash code and change destination dramatically. Another cause is padding, for example: `struct Foo { int32_t a; int64_t b; }` has a 4-byte undefined gap between `a` and `b` on 64-bit machines, result of `hash(&foo, sizeof(foo))` is undefined. Fields need to be packed or serialized before hashing. @@ -368,7 +368,7 @@ request.set_foo(...); cntl->set_timeout_ms(...); stub.some_method(cntl, &request, response, brpc::NewCallback(OnRPCDone, response, cntl)); ``` -Since protobuf 3 changes NewCallback to private, brpc puts NewCallback in [src/brpc/callback.h](https://github.com/brpc/brpc/blob/master/src/brpc/callback.h) after r32035 (and adds more overloads). If your program has compilation issues with NewCallback, replace google::protobuf::NewCallback with brpc::NewCallback. +Since protobuf 3 changes NewCallback to private, brpc puts NewCallback in [src/brpc/callback.h](https://github.com/apache/brpc/blob/master/src/brpc/callback.h) after r32035 (and adds more overloads). If your program has compilation issues with NewCallback, replace google::protobuf::NewCallback with brpc::NewCallback. ### Inherit google::protobuf::Closure @@ -489,7 +489,7 @@ Facts about StartCancel: ## Get server-side address and port -remote_side() tells where request was sent to, the return type is [butil::EndPoint](https://github.com/brpc/brpc/blob/master/src/butil/endpoint.h), which includes an ipv4 address and port. Calling this method before completion of RPC is undefined. +remote_side() tells where request was sent to, the return type is [butil::EndPoint](https://github.com/apache/brpc/blob/master/src/butil/endpoint.h), which includes an ipv4 address and port. Calling this method before completion of RPC is undefined. How to print: ```c++ @@ -534,8 +534,8 @@ If the Controller in snippet1 is new-ed on heap, snippet1 has extra cost of "hea Client-side settings has 3 parts: -- brpc::ChannelOptions: defined in [src/brpc/channel.h](https://github.com/brpc/brpc/blob/master/src/brpc/channel.h), for initializing Channel, becoming immutable once the initialization is done. -- brpc::Controller: defined in [src/brpc/controller.h](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h), for overriding fields in brpc::ChannelOptions for some RPC according to contexts. +- brpc::ChannelOptions: defined in [src/brpc/channel.h](https://github.com/apache/brpc/blob/master/src/brpc/channel.h), for initializing Channel, becoming immutable once the initialization is done. +- brpc::Controller: defined in [src/brpc/controller.h](https://github.com/apache/brpc/blob/master/src/brpc/controller.h), for overriding fields in brpc::ChannelOptions for some RPC according to contexts. - global gflags: for tuning global behaviors, being unchanged generally. Read comments in [/flags](flags.md) before setting. Controller contains data and options that request may not have. server and client share the same Controller class, but they may set different fields. Read comments in Controller carefully before using. @@ -599,7 +599,7 @@ Controller.set_max_retry(0) or ChannelOptions.max_retry = 0 disables retries. If the RPC fails due to request(EREQUEST), no retry will be done because server is very likely to reject the request again, retrying makes no sense here. -Users can inherit [brpc::RetryPolicy](https://github.com/brpc/brpc/blob/master/src/brpc/retry_policy.h) to customize conditions of retrying. For example brpc does not retry for http/h2 related errors by default. If you want to retry for HTTP_STATUS_FORBIDDEN(403) in your app, you can do as follows: +Users can inherit [brpc::RetryPolicy](https://github.com/apache/brpc/blob/master/src/brpc/retry_policy.h) to customize conditions of retrying. For example brpc does not retry for http/h2 related errors by default. If you want to retry for HTTP_STATUS_FORBIDDEN(403) in your app, you can do as follows: ```c++ #include @@ -746,7 +746,7 @@ In http/h2, attachment corresponds to [message body](http://www.w3.org/Protocols ## Turn on SSL Update openssl to the latest version before turning on SSL, since older versions of openssl may have severe security problems and support less encryption algorithms, which is against with the purpose of using SSL. -Set ChannelOptions.mutable_ssl_options() to enable SSL. Refer to [ssl_options.h](https://github.com/brpc/brpc/blob/master/src/brpc/ssl_options.h) for the detailed options. ChannelOptions.has_ssl_options() checks if ssl_options was set; ChannelOptions.ssl_options() returns const reference to the ssl_options. +Set ChannelOptions.mutable_ssl_options() to enable SSL. Refer to [ssl_options.h](https://github.com/apache/brpc/blob/master/src/brpc/ssl_options.h) for the detailed options. ChannelOptions.has_ssl_options() checks if ssl_options was set; ChannelOptions.ssl_options() returns const reference to the ssl_options. ```c++ // Enable client-side SSL and use default values. @@ -905,11 +905,11 @@ Check if the C++ version turns on compression (Controller::set_compress_type), C Steps: -1. Create a [bthread_id](https://github.com/brpc/brpc/blob/master/src/bthread/id.h) as correlation_id of current RPC. -2. According to how the Channel is initialized, choose a server from global [SocketMap](https://github.com/brpc/brpc/blob/master/src/brpc/socket_map.h) or [LoadBalancer](https://github.com/brpc/brpc/blob/master/src/brpc/load_balancer.h) as destination of the request. -3. Choose a [Socket](https://github.com/brpc/brpc/blob/master/src/brpc/socket.h) according to connection type (single, pooled, short) +1. Create a [bthread_id](https://github.com/apache/brpc/blob/master/src/bthread/id.h) as correlation_id of current RPC. +2. According to how the Channel is initialized, choose a server from global [SocketMap](https://github.com/apache/brpc/blob/master/src/brpc/socket_map.h) or [LoadBalancer](https://github.com/apache/brpc/blob/master/src/brpc/load_balancer.h) as destination of the request. +3. Choose a [Socket](https://github.com/apache/brpc/blob/master/src/brpc/socket.h) according to connection type (single, pooled, short) 4. If authentication is turned on and the Socket is not authenticated yet, first request enters authenticating branch, other requests block until the branch writes authenticating information into the Socket. Server-side only verifies the first request. -5. According to protocol of the Channel, choose corresponding serialization callback to serialize request into [IOBuf](https://github.com/brpc/brpc/blob/master/src/butil/iobuf.h). +5. According to protocol of the Channel, choose corresponding serialization callback to serialize request into [IOBuf](https://github.com/apache/brpc/blob/master/src/butil/iobuf.h). 6. If timeout is set, setup timer. From this point on, avoid using Controller, since the timer may be triggered at anytime and calls user's callback for timeout, which may delete Controller. 7. Sending phase is completed. If error occurs at any step, Channel::HandleSendFailed is called. 8. Write IOBuf with serialized data into the Socket and add Channel::HandleSocketFailed into id_wait_list of the Socket. The callback will be called when the write is failed or connection is broken before completion of RPC. diff --git a/docs/en/combo_channel.md b/docs/en/combo_channel.md index 581f388946..c87dc5ca7a 100644 --- a/docs/en/combo_channel.md +++ b/docs/en/combo_channel.md @@ -17,7 +17,7 @@ We need a better abstraction. If several channels are combined into a larger one - Support cancellation. - Support timeout. -Check [example/parallel_echo_c++](https://github.com/brpc/brpc/tree/master/example/parallel_echo_c++/) for an example. +Check [example/parallel_echo_c++](https://github.com/apache/brpc/tree/master/example/parallel_echo_c++/) for an example. Any subclasses of `brpc::ChannelBase` can be added into `ParallelChannel`, including `ParallelChannel` and other combo channels. Set `ParallelChannelOptions.fail_limit` to control maximum number of failures. When number of failed responses reaches the limit, the RPC is ended immediately rather than waiting for timeout. @@ -162,14 +162,14 @@ const Controller* sub(int index) const; # SelectiveChannel -[SelectiveChannel](https://github.com/brpc/brpc/blob/master/src/brpc/selective_channel.h) (referred to as "schan" sometimes) accesses one of the internal sub channels with a load balancing algorithm. It's more high-level compared to ordinary channels: The requests are sent to sub channels instead of servers directly. `SelectiveChannel` is mainly for load balancing between groups of machines and shares basic properties of `Channel`: +[SelectiveChannel](https://github.com/apache/brpc/blob/master/src/brpc/selective_channel.h) (referred to as "schan" sometimes) accesses one of the internal sub channels with a load balancing algorithm. It's more high-level compared to ordinary channels: The requests are sent to sub channels instead of servers directly. `SelectiveChannel` is mainly for load balancing between groups of machines and shares basic properties of `Channel`: - Support synchronous and asynchronous accesses. - Can be destroyed immediately after initiating an asynchronous operation. - Support cancellation. - Support timeout. -Check [example/selective_echo_c++](https://github.com/brpc/brpc/tree/master/example/selective_echo_c++/) for an example. +Check [example/selective_echo_c++](https://github.com/apache/brpc/tree/master/example/selective_echo_c++/) for an example. Any subclasses of `brpc::ChannelBase` can be added into `SelectiveChannel`, including `SelectiveChannel` and other combo channels. @@ -255,9 +255,9 @@ stub.FooMethod(&cntl, &request, &response, NULL); # PartitionChannel -[PartitionChannel](https://github.com/brpc/brpc/blob/master/src/brpc/partition_channel.h) is a specialized `ParallelChannel` to add sub channels automatically based on tags defined in the naming service. As a result, users can list all machines in one naming service and partition them by tags. Check [example/partition_echo_c++](https://github.com/brpc/brpc/tree/master/example/partition_echo_c++/) for an example. +[PartitionChannel](https://github.com/apache/brpc/blob/master/src/brpc/partition_channel.h) is a specialized `ParallelChannel` to add sub channels automatically based on tags defined in the naming service. As a result, users can list all machines in one naming service and partition them by tags. Check [example/partition_echo_c++](https://github.com/apache/brpc/tree/master/example/partition_echo_c++/) for an example. -`ParititonChannel` only supports one kind to partitioning method. When multiple methods need to coexist, or one method needs to be changed to another smoothly, try `DynamicPartitionChannel`, which creates corresponding sub `PartitionChannel` for different partitioning methods, and divide traffic to partitions according to capacities of servers. Check [example/dynamic_partition_echo_c++](https://github.com/brpc/brpc/tree/master/example/dynamic_partition_echo_c++/) for an example. +`ParititonChannel` only supports one kind to partitioning method. When multiple methods need to coexist, or one method needs to be changed to another smoothly, try `DynamicPartitionChannel`, which creates corresponding sub `PartitionChannel` for different partitioning methods, and divide traffic to partitions according to capacities of servers. Check [example/dynamic_partition_echo_c++](https://github.com/apache/brpc/tree/master/example/dynamic_partition_echo_c++/) for an example. If partitions are listed in different naming services, users have to implement the partitioning by `ParallelChannel` and include sub channels to corresponding naming services respectively. Refer to [the previous section](#ParallelChannel) for usages of `ParellelChannel`. diff --git a/docs/en/error_code.md b/docs/en/error_code.md index baefbc28fa..db9260965d 100644 --- a/docs/en/error_code.md +++ b/docs/en/error_code.md @@ -1,6 +1,6 @@ [中文版](../cn/error_code.md) -brpc use [brpc::Controller](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h) to set and get parameters for one RPC. `Controller::ErrorCode()` and `Controller::ErrorText()` return error code and description of the RPC respectively, only accessible after completion of the RPC, otherwise the result is undefined. `ErrorText()` is defined by the base class of the Controller: `google::protobuf::RpcController`, while `ErrorCode()` is defined by `brpc::Controller`. Controller also has a method `Failed()` to tell whether RPC fails or not. Relations between the three methods: +brpc use [brpc::Controller](https://github.com/apache/brpc/blob/master/src/brpc/controller.h) to set and get parameters for one RPC. `Controller::ErrorCode()` and `Controller::ErrorText()` return error code and description of the RPC respectively, only accessible after completion of the RPC, otherwise the result is undefined. `ErrorText()` is defined by the base class of the Controller: `google::protobuf::RpcController`, while `ErrorCode()` is defined by `brpc::Controller`. Controller also has a method `Failed()` to tell whether RPC fails or not. Relations between the three methods: - When `Failed()` is true, `ErrorCode()` must be non-zero and `ErrorText()` be non-empty. - When `Failed()` is false, `ErrorCode()` is 0 and `ErrorText()` is undefined (it's empty in brpc currently, but you'd better not rely on this) @@ -15,9 +15,9 @@ Both client and server in brpc have `Controller`, which can be set with `setFail # Error Code in brpc -All error codes in brpc are defined in [errno.proto](https://github.com/brpc/brpc/blob/master/src/brpc/errno.proto), in which those begin with *SYS_* are defined by linux system and exactly same with the ones defined in `/usr/include/errno.h`. The reason that we put it in .proto is to cross language. The rest of the error codes are defined by brpc. +All error codes in brpc are defined in [errno.proto](https://github.com/apache/brpc/blob/master/src/brpc/errno.proto), in which those begin with *SYS_* are defined by linux system and exactly same with the ones defined in `/usr/include/errno.h`. The reason that we put it in .proto is to cross language. The rest of the error codes are defined by brpc. -[berror(error_code)](https://github.com/brpc/brpc/blob/master/src/butil/errno.h) gets description for the error code, and `berror()` gets description for current [system errno](http://www.cplusplus.com/reference/cerrno/errno/). Note that **ErrorText() != berror(ErorCode())** since `ErrorText()` contains more specific information. brpc includes berror by default so that you can use it in your project directly. +[berror(error_code)](https://github.com/apache/brpc/blob/master/src/butil/errno.h) gets description for the error code, and `berror()` gets description for current [system errno](http://www.cplusplus.com/reference/cerrno/errno/). Note that **ErrorText() != berror(ErorCode())** since `ErrorText()` contains more specific information. brpc includes berror by default so that you can use it in your project directly. Following table shows common error codes and their descriptions: diff --git a/docs/en/getting_started.md b/docs/en/getting_started.md index 547a010427..8c44c6e82f 100644 --- a/docs/en/getting_started.md +++ b/docs/en/getting_started.md @@ -341,7 +341,7 @@ no known issues. Be compatible with pb 3.x and pb 2.x with the same file: Don't use new types in proto3 and start the proto file with `syntax="proto2";` -[tools/add_syntax_equal_proto2_to_all.sh](https://github.com/brpc/brpc/blob/master/tools/add_syntax_equal_proto2_to_all.sh)can add `syntax="proto2"` to all proto files without it. +[tools/add_syntax_equal_proto2_to_all.sh](https://github.com/apache/brpc/blob/master/tools/add_syntax_equal_proto2_to_all.sh)can add `syntax="proto2"` to all proto files without it. Arena in pb 3.x is not supported yet. @@ -385,4 +385,4 @@ no known issues. # Track instances -We provide a program to help you to track and monitor all brpc instances. Just run [trackme_server](https://github.com/brpc/brpc/tree/master/tools/trackme_server/) somewhere and launch need-to-be-tracked instances with -trackme_server=SERVER. The trackme_server will receive pings from instances periodically and print logs when it does. You can aggregate instance addresses from the log and call builtin services of the instances for further information. +We provide a program to help you to track and monitor all brpc instances. Just run [trackme_server](https://github.com/apache/brpc/tree/master/tools/trackme_server/) somewhere and launch need-to-be-tracked instances with -trackme_server=SERVER. The trackme_server will receive pings from instances periodically and print logs when it does. You can aggregate instance addresses from the log and call builtin services of the instances for further information. diff --git a/docs/en/http_client.md b/docs/en/http_client.md index f83478d558..a7cf520599 100644 --- a/docs/en/http_client.md +++ b/docs/en/http_client.md @@ -2,7 +2,7 @@ # Example -[example/http_c++](https://github.com/brpc/brpc/blob/master/example/http_c++/http_client.cpp) +[example/http_c++](https://github.com/apache/brpc/blob/master/example/http_c++/http_client.cpp) # About h2 @@ -41,7 +41,7 @@ http/h2 does not relate to protobuf much, thus all parameters of `CallMethod` ar # POST -The default HTTP Method is GET, which can be changed to POST or [other http methods](https://github.com/brpc/brpc/blob/master/src/brpc/http_method.h). The data to POST should be put into `request_attachment()`, which is typed [butil::IOBuf](https://github.com/brpc/brpc/blob/master/src/butil/iobuf.h) and able to append `std :: string` or `char *` directly. +The default HTTP Method is GET, which can be changed to POST or [other http methods](https://github.com/apache/brpc/blob/master/src/brpc/http_method.h). The data to POST should be put into `request_attachment()`, which is typed [butil::IOBuf](https://github.com/apache/brpc/blob/master/src/butil/iobuf.h) and able to append `std :: string` or `char *` directly. ```c++ brpc::Controller cntl; diff --git a/docs/en/http_service.md b/docs/en/http_service.md index cf1ea9af3a..0e57b3a78b 100644 --- a/docs/en/http_service.md +++ b/docs/en/http_service.md @@ -5,7 +5,7 @@ http/h2 services in brpc have to declare interfaces with empty request and respo # Example -[http_server.cpp](https://github.com/brpc/brpc/blob/master/example/http_c++/http_server.cpp) +[http_server.cpp](https://github.com/apache/brpc/blob/master/example/http_c++/http_server.cpp) # About h2 @@ -245,7 +245,7 @@ If the RPC fails (`Controller` has been `SetFailed`), the framework overwrites ` ## Status Code -Status code is a special field in HTTP response to store processing result of the http request. Possible values are defined in [http_status_code.h](https://github.com/brpc/brpc/blob/master/src/brpc/http_status_code.h). +Status code is a special field in HTTP response to store processing result of the http request. Possible values are defined in [http_status_code.h](https://github.com/apache/brpc/blob/master/src/brpc/http_status_code.h). ```c++ // Get Status Code @@ -269,7 +269,7 @@ cntl->http_response().SetHeader("Location", "http://bj.bs.bae.baidu.com/family/i ## Query String -As mentioned in above [HTTP headers](#http-headers), query strings are interpreted in common convention, whose form is `key1=value1&key2=value2&…`. Keys without values are acceptable as well and accessible by `GetQuery` which returns an empty string. Such keys are often used as boolean flags. Full API are defined in [uri.h](https://github.com/brpc/brpc/blob/master/src/brpc/uri.h). +As mentioned in above [HTTP headers](#http-headers), query strings are interpreted in common convention, whose form is `key1=value1&key2=value2&…`. Keys without values are acceptable as well and accessible by `GetQuery` which returns an empty string. Such keys are often used as boolean flags. Full API are defined in [uri.h](https://github.com/apache/brpc/blob/master/src/brpc/uri.h). ```c++ const std::string* time_value = cntl->http_request().uri().GetQuery("time"); @@ -325,7 +325,7 @@ https is short for "http over SSL", SSL is not exclusive for http, but effective Productions without extreme performance requirements tend to use HTTP protocol, especially mobile products. Thus we put great emphasis on implementation qualities of HTTP. To be more specific: -- Use [http parser](https://github.com/brpc/brpc/blob/master/src/brpc/details/http_parser.h) of node.js to parse http messages, which is a lightweight, well-written, and extensively used implementation. +- Use [http parser](https://github.com/apache/brpc/blob/master/src/brpc/details/http_parser.h) of node.js to parse http messages, which is a lightweight, well-written, and extensively used implementation. - Use [rapidjson](https://github.com/miloyip/rapidjson) to parse json, which is a json library focuses on performance. - In the worst case, the time complexity of parsing http requests is still O(N), where N is byte size of the request. As a contrast, parsing code that requires the http request to be complete, may cost O(N^2) time in the worst case. This feature is very helpful since many HTTP requests are large. - Processing HTTP messages from different clients is highly concurrent, even a pretty complicated http message does not block responding other clients. It's difficult to achieve this for other RPC implementations and http servers often based on [single-threaded reactor](threading_overview.md#single-threaded-reactor). diff --git a/docs/en/io.md b/docs/en/io.md index c69bff286b..6bb8288274 100644 --- a/docs/en/io.md +++ b/docs/en/io.md @@ -10,11 +10,11 @@ Non-blocking IO is usually used for increasing IO concurrency in Linux. When the # Receiving messages -A message is a bounded binary data read from a connection, which may be a request from upstream clients or a response from downstream servers. brpc uses one or several [EventDispatcher](https://github.com/brpc/brpc/blob/master/src/brpc/event_dispatcher.cpp)(referred to as EDISP) to wait for events from file descriptors. Unlike the common "IO threads", EDISP is not responsible for reading or writing. The problem of IO threads is that one thread can only read one fd at a given time, other reads may be delayed when many fds in one IO thread are busy. Multi-tenancy, complicated load balancing and [Streaming RPC](streaming_rpc.md) worsen the problem. Under high workloads, regular long delays on one fd may slow down all fds in the IO thread, causing more long tails. +A message is a bounded binary data read from a connection, which may be a request from upstream clients or a response from downstream servers. brpc uses one or several [EventDispatcher](https://github.com/apache/brpc/blob/master/src/brpc/event_dispatcher.cpp)(referred to as EDISP) to wait for events from file descriptors. Unlike the common "IO threads", EDISP is not responsible for reading or writing. The problem of IO threads is that one thread can only read one fd at a given time, other reads may be delayed when many fds in one IO thread are busy. Multi-tenancy, complicated load balancing and [Streaming RPC](streaming_rpc.md) worsen the problem. Under high workloads, regular long delays on one fd may slow down all fds in the IO thread, causing more long tails. -Because of a [bug](https://patchwork.kernel.org/patch/1970231/) of epoll (at the time of developing brpc) and overhead of epoll_ctl, edge triggered mode is used in EDISP. After receiving an event, an atomic variable associated with the fd is added by one atomically. If the variable is zero before addition, a bthread is started to handle the data from the fd. The pthread worker in which EDISP runs is yielded to the newly created bthread to make it start reading ASAP and have a better cache locality. The bthread in which EDISP runs will be stolen to another pthread and keep running, this mechanism is work stealing used in bthreads. To understand exactly how that atomic variable works, you can read [atomic instructions](atomic_instructions.md) first, then check [Socket::StartInputEvent](https://github.com/brpc/brpc/blob/master/src/brpc/socket.cpp). These methods make contentions on dispatching events of one fd [wait-free](http://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom). +Because of a [bug](https://patchwork.kernel.org/patch/1970231/) of epoll (at the time of developing brpc) and overhead of epoll_ctl, edge triggered mode is used in EDISP. After receiving an event, an atomic variable associated with the fd is added by one atomically. If the variable is zero before addition, a bthread is started to handle the data from the fd. The pthread worker in which EDISP runs is yielded to the newly created bthread to make it start reading ASAP and have a better cache locality. The bthread in which EDISP runs will be stolen to another pthread and keep running, this mechanism is work stealing used in bthreads. To understand exactly how that atomic variable works, you can read [atomic instructions](atomic_instructions.md) first, then check [Socket::StartInputEvent](https://github.com/apache/brpc/blob/master/src/brpc/socket.cpp). These methods make contentions on dispatching events of one fd [wait-free](http://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom). -[InputMessenger](https://github.com/brpc/brpc/blob/master/src/brpc/input_messenger.h) cuts messages and uses customizable callbacks to handle different format of data. `Parse` callback cuts messages from binary data and has relatively stable running time; `Process` parses messages further(such as parsing by protobuf) and calls users' callbacks, which vary in running time. If n(n > 1) messages are read from the fd, InputMessenger launches n-1 bthreads to handle first n-1 messages respectively, and processes the last message in-place. InputMessenger tries protocols one by one. Since one connections often has only one type of messages, InputMessenger remembers current protocol to avoid trying for protocols next time. +[InputMessenger](https://github.com/apache/brpc/blob/master/src/brpc/input_messenger.h) cuts messages and uses customizable callbacks to handle different format of data. `Parse` callback cuts messages from binary data and has relatively stable running time; `Process` parses messages further(such as parsing by protobuf) and calls users' callbacks, which vary in running time. If n(n > 1) messages are read from the fd, InputMessenger launches n-1 bthreads to handle first n-1 messages respectively, and processes the last message in-place. InputMessenger tries protocols one by one. Since one connections often has only one type of messages, InputMessenger remembers current protocol to avoid trying for protocols next time. It can be seen that messages from different fds or even same fd are processed concurrently in brpc, which makes brpc good at handling large messages and reducing long tails on processing messages from different sources under high workloads. @@ -22,7 +22,7 @@ It can be seen that messages from different fds or even same fd are processed co A message is a bounded binary data written to a connection, which may be a response to upstream clients or a request to downstream servers. Multiple threads may send messages to a fd at the same time, however writing to a fd is non-atomic, so how to queue writes from different thread efficiently is a key technique. brpc uses a special wait-free MPSC list to solve the issue. All data ready to write is put into a node of a singly-linked list, whose next pointer points to a special value(`Socket::WriteRequest::UNCONNECTED`). When a thread wants to write out some data, it tries to atomically exchange the node with the list head(Socket::_write_head) first. If the head before exchange is empty, the caller gets the right to write and writes out the data in-place once. Otherwise there must be another thread writing. The caller points the next pointer to the head returned to make the linked list connected. The thread that is writing will see the new head later and write new data. -This method makes the writing contentions wait-free. Although the thread that gets the right to write is not wait-free nor lock-free in principle and may be blocked by a node that is still UNCONNECTED(the thread issuing write is swapped out by OS just after atomic exchange and before setting the next pointer, within execution time of just one instruction), the blocking rarely happens in practice. In current implementations, if the data cannot be written fully in one call, a KeepWrite bthread is created to write the remaining data. This mechanism is pretty complicated and the principle is depicted below. Read [socket.cpp](https://github.com/brpc/brpc/blob/master/src/brpc/socket.cpp) for more details. +This method makes the writing contentions wait-free. Although the thread that gets the right to write is not wait-free nor lock-free in principle and may be blocked by a node that is still UNCONNECTED(the thread issuing write is swapped out by OS just after atomic exchange and before setting the next pointer, within execution time of just one instruction), the blocking rarely happens in practice. In current implementations, if the data cannot be written fully in one call, a KeepWrite bthread is created to write the remaining data. This mechanism is pretty complicated and the principle is depicted below. Read [socket.cpp](https://github.com/apache/brpc/blob/master/src/brpc/socket.cpp) for more details. ![img](../images/write.png) @@ -30,7 +30,7 @@ Since writes in brpc always complete within short time, the calling thread can h # Socket -[Socket](https://github.com/brpc/brpc/blob/master/src/brpc/socket.h) contains data structures related to fd and is one of the most complex structure in brpc. The unique feature of this structure is that it uses 64-bit SocketId to refer to a Socket object to facilitate usages of fd in multi-threaded environments. Commonly used methods: +[Socket](https://github.com/apache/brpc/blob/master/src/brpc/socket.h) contains data structures related to fd and is one of the most complex structure in brpc. The unique feature of this structure is that it uses 64-bit SocketId to refer to a Socket object to facilitate usages of fd in multi-threaded environments. Commonly used methods: - Create: create a Socket and return its SocketId. - Address: retrieve Socket from an id, and wrap it into a unique_ptr(SocketUniquePtr) that will be automatically released. When Socket is set failed, the pointer returned is empty. As long as Address returns a non-null pointer, the contents are guaranteed to not change until the pointer is destructed. This function is wait-free. @@ -38,7 +38,7 @@ Since writes in brpc always complete within short time, the calling thread can h We can see that, Socket is similar to [shared_ptr](http://en.cppreference.com/w/cpp/memory/shared_ptr) in the sense of referential counting and SocketId is similar to [weak_ptr](http://en.cppreference.com/w/cpp/memory/weak_ptr). The unique `SetFailed` prevents Socket from being addressed so that the reference count can hit zero finally. Simply using shared_ptr/weak_ptr cannot guarantee this. For example, when a server needs to quit when requests are still coming in frequently, the reference count of Socket may not hit zero and the server is unable to stop quickly. What' more, weak_ptr cannot be directly put into epoll data, but SocketId can. These factors lead to design of Socket which is stable and rarely changed since 2014. -Using SocketUniquePtr or SocketId depends on if a strong reference is needed. For example, Controller is used thoroughly inside RPC and has a lot of interactions with Socket, it uses SocketUniquePtr. Epoll notifies events on fds and events of a recycled socket can be ignored, so epoll uses SocketId. +Using SocketUniquePtr or SocketId depends on if a strong reference is needed. For example, Controller is used thoroughly inside RPC and has a lot of interactions with Socket, it uses SocketUniquePtr. Epoll notifies events on fds and events of a recycled socket can be ignored, so epoll uses SocketId. As long as SocketUniquePtr is valid, the Socket enclosed will not be changed so that users have no need to care about race conditions and ABA problems, being safer to operate the shared socket. This method also circumvents implicit referential counting and makes ownership of memory more clear, producing better-quality programs. brpc uses SocketUniquePtr and SocketId a lot to simplify related issues. diff --git a/docs/en/iobuf.md b/docs/en/iobuf.md index 4d9b708c35..8da47ccb90 100644 --- a/docs/en/iobuf.md +++ b/docs/en/iobuf.md @@ -1,6 +1,6 @@ [中文版](../cn/iobuf.md) -brpc uses [butil::IOBuf](https://github.com/brpc/brpc/blob/master/src/butil/iobuf.h) as data structure for attachment in some protocols and HTTP body. It's a non-contiguous zero-copied buffer, proved in previous projects, and good at performance. The interface of `IOBuf` is similar to `std::string`, but not the same. +brpc uses [butil::IOBuf](https://github.com/apache/brpc/blob/master/src/butil/iobuf.h) as data structure for attachment in some protocols and HTTP body. It's a non-contiguous zero-copied buffer, proved in previous projects, and good at performance. The interface of `IOBuf` is similar to `std::string`, but not the same. If you've used the `BufHandle` in Kylin before, you should notice the convenience of `IOBuf`: the former one is badly encapsulated, leaving the internal structure directly in front of users, who must carefully handle the referential countings, very error prone and leading to bugs. diff --git a/docs/en/memcache_client.md b/docs/en/memcache_client.md index 4f9a4918c1..c65114cf03 100644 --- a/docs/en/memcache_client.md +++ b/docs/en/memcache_client.md @@ -1,6 +1,6 @@ [中文版](../cn/memcache_client.md) -[memcached](http://memcached.org/) is a common caching service. In order to access memcached more conveniently and make full use of bthread's capability of concurrency, brpc directly supports the memcached protocol. Check [example/memcache_c++](https://github.com/brpc/brpc/tree/master/example/memcache_c++/) for an example. +[memcached](http://memcached.org/) is a common caching service. In order to access memcached more conveniently and make full use of bthread's capability of concurrency, brpc directly supports the memcached protocol. Check [example/memcache_c++](https://github.com/apache/brpc/tree/master/example/memcache_c++/) for an example. **NOTE**: brpc only supports the binary protocol of memcache. There's little benefit to support the textual protocol which is replaced since memcached 1.3. If your memcached is older than 1.3, upgrade to a newer version. diff --git a/docs/en/new_protocol.md b/docs/en/new_protocol.md index b5d05d54a0..4f6d358aa6 100644 --- a/docs/en/new_protocol.md +++ b/docs/en/new_protocol.md @@ -20,7 +20,7 @@ brpc is designed to add new protocols at any time, just proceed as follows: ## add ProtocolType -Add new protocol type in ProtocolType in [options.proto](https://github.com/brpc/brpc/blob/master/src/brpc/options.proto). If you need to add new protocol, please contact us to add it for you to make sure there is no conflict with protocols of others. +Add new protocol type in ProtocolType in [options.proto](https://github.com/apache/brpc/blob/master/src/brpc/options.proto). If you need to add new protocol, please contact us to add it for you to make sure there is no conflict with protocols of others. Currently we support in ProtocolType(at the middle of 2018): ```c++ @@ -56,7 +56,7 @@ enum ProtocolType { ``` ## Implement Callbacks -All callbacks are defined in struct Protocol, which is defined in [protocol.h](https://github.com/brpc/brpc/blob/master/src/brpc/protocol.h). Among all these callbacks, `parse` is a callback that must be implemented. Besides, `process_request` must be implemented in the server side and `serialize_request`, `pack_request`, `process_response` must be implemented in the client side. +All callbacks are defined in struct Protocol, which is defined in [protocol.h](https://github.com/apache/brpc/blob/master/src/brpc/protocol.h). Among all these callbacks, `parse` is a callback that must be implemented. Besides, `process_request` must be implemented in the server side and `serialize_request`, `pack_request`, `process_response` must be implemented in the client side. It is difficult to implement callbacks of the protocol. These codes are not like the codes that ordinary users use which has good prompts and protections. You have to figure it out how to handle similar code in other protocols and implement your own protocol, then send it to us to do code review. @@ -137,7 +137,7 @@ The name of the protocol, which appears in the various configurations and displa ## Register to global -RegisterProtocol should be called to [register implemented protocol](https://github.com/brpc/brpc/blob/master/src/brpc/global.cpp) to brpc, just like: +RegisterProtocol should be called to [register implemented protocol](https://github.com/apache/brpc/blob/master/src/brpc/global.cpp) to brpc, just like: ```c++ Protocol http_protocol = { ParseHttpMessage, diff --git a/docs/en/overview.md b/docs/en/overview.md index 32185e0bf8..0a704ddc6b 100644 --- a/docs/en/overview.md +++ b/docs/en/overview.md @@ -40,7 +40,7 @@ You can use it to: * Build a server that can talk in multiple protocols (**on same port**), or access all sorts of services * restful http/https, [h2](https://http2.github.io/http2-spec)/[gRPC](https://grpc.io). using http/h2 in brpc is much more friendly than [libcurl](https://curl.haxx.se/libcurl/). Access protobuf-based protocols with HTTP/h2+json, probably from another language. * [redis](redis_client.md) and [memcached](memcache_client.md), thread-safe, more friendly and performant than the official clients - * [rtmp](https://github.com/brpc/brpc/blob/master/src/brpc/rtmp.h)/[flv](https://en.wikipedia.org/wiki/Flash_Video)/[hls](https://en.wikipedia.org/wiki/HTTP_Live_Streaming), for building [streaming services](https://github.com/brpc/media-server). + * [rtmp](https://github.com/apache/brpc/blob/master/src/brpc/rtmp.h)/[flv](https://en.wikipedia.org/wiki/Flash_Video)/[hls](https://en.wikipedia.org/wiki/HTTP_Live_Streaming), for building [streaming services](https://github.com/brpc/media-server). * hadoop_rpc (may be opensourced) * [rdma](https://en.wikipedia.org/wiki/Remote_direct_memory_access) support (will be opensourced) * [thrift](thrift.md) support, thread-safe, more friendly and performant than the official clients. @@ -56,13 +56,13 @@ You can use it to: ### More friendly API -Only 3 (major) user headers: [Server](https://github.com/brpc/brpc/blob/master/src/brpc/server.h), [Channel](https://github.com/brpc/brpc/blob/master/src/brpc/channel.h), [Controller](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h), corresponding to server-side, client-side and parameter-set respectively. You don't have to worry about "How to initialize XXXManager", "How to layer all these components together", "What's the relationship between XXXController and XXXContext". All you need to do is simple: +Only 3 (major) user headers: [Server](https://github.com/apache/brpc/blob/master/src/brpc/server.h), [Channel](https://github.com/apache/brpc/blob/master/src/brpc/channel.h), [Controller](https://github.com/apache/brpc/blob/master/src/brpc/controller.h), corresponding to server-side, client-side and parameter-set respectively. You don't have to worry about "How to initialize XXXManager", "How to layer all these components together", "What's the relationship between XXXController and XXXContext". All you need to do is simple: -* Build service? include [brpc/server.h](https://github.com/brpc/brpc/blob/master/src/brpc/server.h) and follow the comments or [examples](https://github.com/brpc/brpc/blob/master/example/echo_c++/server.cpp). +* Build service? include [brpc/server.h](https://github.com/apache/brpc/blob/master/src/brpc/server.h) and follow the comments or [examples](https://github.com/apache/brpc/blob/master/example/echo_c++/server.cpp). -* Access service? include [brpc/channel.h](https://github.com/brpc/brpc/blob/master/src/brpc/channel.h) and follow the comments or [examples](https://github.com/brpc/brpc/blob/master/example/echo_c++/client.cpp). +* Access service? include [brpc/channel.h](https://github.com/apache/brpc/blob/master/src/brpc/channel.h) and follow the comments or [examples](https://github.com/apache/brpc/blob/master/example/echo_c++/client.cpp). -* Tweak parameters? Checkout [brpc/controller.h](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h). Note that the class is shared by server and channel. Methods are separated into 3 parts: client-side, server-side and both-side. +* Tweak parameters? Checkout [brpc/controller.h](https://github.com/apache/brpc/blob/master/src/brpc/controller.h). Note that the class is shared by server and channel. Methods are separated into 3 parts: client-side, server-side and both-side. We tried to make simple things simple. Take naming service as an example. In older RPC implementations you may need to copy a pile of obscure code to make it work, however, in brpc accessing BNS is expressed as `Init("bns://node-name", ...)`, DNS is `Init("http://domain-name", ...)` and local machine list is `Init("file:///home/work/server.list", ...)`. Without any explanation, you know what it means. diff --git a/docs/en/redis_client.md b/docs/en/redis_client.md index 00c19c5b6a..0ab1694d6d 100644 --- a/docs/en/redis_client.md +++ b/docs/en/redis_client.md @@ -1,6 +1,6 @@ [中文版](../cn/redis_client.md) -[redis](http://redis.io/) is one of the most popular caching service in recent years. Compared to memcached it provides users with more data structures and operations, speeding up developments. In order to access redis servers more conveniently and make full use of bthread's capability of concurrency, brpc directly supports the redis protocol. Check [example/redis_c++](https://github.com/brpc/brpc/tree/master/example/redis_c++/) for an example. +[redis](http://redis.io/) is one of the most popular caching service in recent years. Compared to memcached it provides users with more data structures and operations, speeding up developments. In order to access redis servers more conveniently and make full use of bthread's capability of concurrency, brpc directly supports the redis protocol. Check [example/redis_c++](https://github.com/apache/brpc/tree/master/example/redis_c++/) for an example. Advantages compared to [hiredis](https://github.com/redis/hiredis) (the official redis client): @@ -117,7 +117,7 @@ options.auth = auth; # RedisRequest -A [RedisRequest](https://github.com/brpc/brpc/blob/master/src/brpc/redis.h) may contain multiple commands by calling `AddCommand*`, which returns true on success and false otherwise. **The callsite backtrace is also printed on error**. +A [RedisRequest](https://github.com/apache/brpc/blob/master/src/brpc/redis.h) may contain multiple commands by calling `AddCommand*`, which returns true on success and false otherwise. **The callsite backtrace is also printed on error**. ```c++ bool AddCommand(const char* fmt, ...); @@ -137,7 +137,7 @@ Call `Clear()` before re-using the `RedisRequest` object. # RedisResponse -A [RedisResponse](https://github.com/brpc/brpc/blob/master/src/brpc/redis.h) may contain one or multiple [RedisReply](https://github.com/brpc/brpc/blob/master/src/brpc/redis_reply.h)s. Use `reply_size()` for total number of replies and `reply(i)` for reference to the i-th reply (counting from 0). Note that in hiredis, if the request contains N commands, you have to call `redisGetReply` N times to get replies, while it's unnecessary in brpc as the `RedisResponse` already includes the N replies which are accessible by reply(i). As long as RPC is successful, `response.reply_size()` should be equal to `request.command_size()`, unless the redis-server is buggy. The precondition that redis works correctly is that replies correspond to commands one by one in the same sequence (positional correspondence). +A [RedisResponse](https://github.com/apache/brpc/blob/master/src/brpc/redis.h) may contain one or multiple [RedisReply](https://github.com/apache/brpc/blob/master/src/brpc/redis_reply.h)s. Use `reply_size()` for total number of replies and `reply(i)` for reference to the i-th reply (counting from 0). Note that in hiredis, if the request contains N commands, you have to call `redisGetReply` N times to get replies, while it's unnecessary in brpc as the `RedisResponse` already includes the N replies which are accessible by reply(i). As long as RPC is successful, `response.reply_size()` should be equal to `request.command_size()`, unless the redis-server is buggy. The precondition that redis works correctly is that replies correspond to commands one by one in the same sequence (positional correspondence). Each `RedisReply` may be: @@ -239,7 +239,7 @@ We can see a tremendous drop of QPS compared to the one using single connection # Command Line Interface -[example/redis_c++/redis_cli](https://github.com/brpc/brpc/blob/master/example/redis_c%2B%2B/redis_cli.cpp) is a command line tool similar to the official CLI, demostrating brpc's capability to talk with redis servers. When unexpected results are got from a redis-server using a brpc client, you can debug with this tool interactively as well. +[example/redis_c++/redis_cli](https://github.com/apache/brpc/blob/master/example/redis_c%2B%2B/redis_cli.cpp) is a command line tool similar to the official CLI, demostrating brpc's capability to talk with redis servers. When unexpected results are got from a redis-server using a brpc client, you can debug with this tool interactively as well. Like the official CLI, `redis_cli ` runs the command directly, and `-server` which is address of the redis-server can be specified. diff --git a/docs/en/server.md b/docs/en/server.md index 0702fff662..1a76ebc5a8 100644 --- a/docs/en/server.md +++ b/docs/en/server.md @@ -2,7 +2,7 @@ # Example -[server-side code](https://github.com/brpc/brpc/blob/master/example/echo_c++/server.cpp) of Echo. +[server-side code](https://github.com/apache/brpc/blob/master/example/echo_c++/server.cpp) of Echo. # Fill the .proto @@ -50,15 +50,15 @@ public: }; ``` -Service is not available before insertion into [brpc.Server](https://github.com/brpc/brpc/blob/master/src/brpc/server.h). +Service is not available before insertion into [brpc.Server](https://github.com/apache/brpc/blob/master/src/brpc/server.h). -When client sends request, Echo() is called. +When client sends request, Echo() is called. Explain parameters: **controller** -Statically convertible to brpc::Controller (provided that the code runs in brpc.Server). Contains parameters that can't be included by request and response, check out [src/brpc/controller.h](https://github.com/brpc/brpc/blob/master/src/brpc/controller.h) for details. +Statically convertible to brpc::Controller (provided that the code runs in brpc.Server). Contains parameters that can't be included by request and response, check out [src/brpc/controller.h](https://github.com/apache/brpc/blob/master/src/brpc/controller.h) for details. **request** @@ -137,7 +137,7 @@ public: Call Controller.SetFailed() to set the RPC to be failed. If error occurs during sending response, framework calls the method as well. Users often call the method in services' CallMethod(), For example if a stage of processing fails, user calls SetFailed() and call done->Run(), then quit CallMethod (If ClosureGuard is used, done->Run() is called automatically). The server-side done is created by framework and contains code sending response back to client. If SetFailed() is called, error information is sent to client instead of normal content. When client receives the response, its controller will be SetFailed() as well and Controller::Failed() will be true. In addition, Controller::ErrorCode() and Controller::ErrorText() are error code and error information respectively. -User may set [status-code](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) for http calls by calling `controller.http_response().set_status_code()` at server-side. Standard status-code are defined in [http_status_code.h](https://github.com/brpc/brpc/blob/master/src/brpc/http_status_code.h). Controller.SetFailed() sets status-code as well with the value closest to the error-code in semantics. brpc::HTTP_STATUS_INTERNAL_SERVER_ERROR(500) is chosen when there's no proper value. +User may set [status-code](http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) for http calls by calling `controller.http_response().set_status_code()` at server-side. Standard status-code are defined in [http_status_code.h](https://github.com/apache/brpc/blob/master/src/brpc/http_status_code.h). Controller.SetFailed() sets status-code as well with the value closest to the error-code in semantics. brpc::HTTP_STATUS_INTERNAL_SERVER_ERROR(500) is chosen when there's no proper value. ## Get address of client @@ -167,7 +167,7 @@ In which done->Run() is called after leaving service's CallMethod(). Some server proxies requests to back-end servers and waits for responses that may come back after a long time. To make better use of threads, save done in corresponding event handlers which are triggered after CallMethod() and call done->Run() inside. This kind of service is **asynchronous**. -Last line of asynchronous service is often `done_guard.release()` to prevent done->Run() from being called at successful exit from CallMethod(). Check out [example/session_data_and_thread_local](https://github.com/brpc/brpc/tree/master/example/session_data_and_thread_local/) for a example. +Last line of asynchronous service is often `done_guard.release()` to prevent done->Run() from being called at successful exit from CallMethod(). Check out [example/session_data_and_thread_local](https://github.com/apache/brpc/tree/master/example/session_data_and_thread_local/) for a example. Server-side and client-side both use done to represent the continuation code after leaving CallMethod, but they're **totally different**: @@ -203,7 +203,7 @@ You cannot add or remove services after the server is started. # Start server -Call following methods of [Server](https://github.com/brpc/brpc/blob/master/src/brpc/server.h) to start serving. +Call following methods of [Server](https://github.com/apache/brpc/blob/master/src/brpc/server.h) to start serving. ```c++ int Start(const char* ip_and_port_str, const ServerOptions* opt); @@ -259,7 +259,7 @@ Services can be added or removed after Join() returns and server can be Start() Services using protobuf can be accessed via http/h2+json generally. The json string stored in body is convertible to/from corresponding protobuf message. -[echo server](https://github.com/brpc/brpc/blob/master/example/echo_c%2B%2B/server.cpp) as an example, is accessible from [curl](https://curl.haxx.se/). +[echo server](https://github.com/apache/brpc/blob/master/example/echo_c%2B%2B/server.cpp) as an example, is accessible from [curl](https://curl.haxx.se/). ```shell @@ -381,13 +381,13 @@ If this field is non-empty, Server creates a file named so at start-up, with pid ## Print hostname in each line of log -This feature only affects logging macros in [butil/logging.h](https://github.com/brpc/brpc/blob/master/src/butil/logging.h). +This feature only affects logging macros in [butil/logging.h](https://github.com/apache/brpc/blob/master/src/butil/logging.h). If [-log_hostname](http://brpc.baidu.com:8765/flags/log_hostname) is turned on, each line of log contains the hostname so that users know machines at where each line is generated from aggregated logs. ## Crash after printing FATAL log -This feature only affects logging macros in [butil/logging.h](https://github.com/brpc/brpc/blob/master/src/butil/logging.h), glog crashes for FATAL log by default. +This feature only affects logging macros in [butil/logging.h](https://github.com/apache/brpc/blob/master/src/butil/logging.h), glog crashes for FATAL log by default. If [-crash_on_fatal_log](http://brpc.baidu.com:8765/flags/crash_on_fatal_log) is turned on, program crashes after printing LOG(FATAL) or failed assertions by CHECK*(), and generates coredump (with proper environmental settings). Default value is false. This flag can be turned on in tests to make sure the program never hit critical errors. @@ -395,7 +395,7 @@ If [-crash_on_fatal_log](http://brpc.baidu.com:8765/flags/crash_on_fatal_log) is ## Minimum log level -This feature is implemented by [butil/logging.h](https://github.com/brpc/brpc/blob/master/src/butil/logging.h) and glog separately, as a same-named gflag. +This feature is implemented by [butil/logging.h](https://github.com/apache/brpc/blob/master/src/butil/logging.h) and glog separately, as a same-named gflag. Only logs with levels **not less than** the level specified by -minloglevel are printed. This flag can be modified at run-time. Correspondence between values and log levels: 0=INFO 1=NOTICE 2=WARNING 3=ERROR 4=FATAL, default value is 0. @@ -476,7 +476,7 @@ In http, attachment corresponds to [message body](http://www.w3.org/Protocols/rf ## Turn on SSL -Update openssl to the latest version before turning on SSL, since older versions of openssl may have severe security problems and support less encryption algorithms, which is against with the purpose of using SSL. Setup `ServerOptions.ssl_options` to turn on SSL. Refer to [ssl_options.h](https://github.com/brpc/brpc/blob/master/src/brpc/ssl_options.h) for more details. +Update openssl to the latest version before turning on SSL, since older versions of openssl may have severe security problems and support less encryption algorithms, which is against with the purpose of using SSL. Setup `ServerOptions.ssl_options` to turn on SSL. Refer to [ssl_options.h](https://github.com/apache/brpc/blob/master/src/brpc/ssl_options.h) for more details. ```c++ // Certificate structure @@ -704,7 +704,7 @@ Consider returning signatures of the addresses. For example after setting Server ## Customize /health -/health returns "OK" by default. If the content on /health needs to be customized: inherit [HealthReporter](https://github.com/brpc/brpc/blob/master/src/brpc/health_reporter.h) and implement code to generate the page (like implementing other http services). Assign an instance to ServerOptions.health_reporter, which is not owned by server and must be valid during lifetime of the server. Users may return richer healthy information according to application requirements. +/health returns "OK" by default. If the content on /health needs to be customized: inherit [HealthReporter](https://github.com/apache/brpc/blob/master/src/brpc/health_reporter.h) and implement code to generate the page (like implementing other http services). Assign an instance to ServerOptions.health_reporter, which is not owned by server and must be valid during lifetime of the server. Users may return richer healthy information according to application requirements. ## thread-local variables @@ -765,7 +765,7 @@ struct ServerOptions { }; ``` -session_local_data_factory is typed [DataFactory](https://github.com/brpc/brpc/blob/master/src/brpc/data_factory.h). You have to implement CreateData and DestroyData inside. +session_local_data_factory is typed [DataFactory](https://github.com/apache/brpc/blob/master/src/brpc/data_factory.h). You have to implement CreateData and DestroyData inside. NOTE: CreateData and DestroyData may be called by multiple threads simultaneously. Thread-safety is a must. @@ -856,7 +856,7 @@ struct ServerOptions { }; ``` -thread_local_data_factory is typed [DataFactory](https://github.com/brpc/brpc/blob/master/src/brpc/data_factory.h). You need to implement CreateData and DestroyData inside. +thread_local_data_factory is typed [DataFactory](https://github.com/apache/brpc/blob/master/src/brpc/data_factory.h). You need to implement CreateData and DestroyData inside. NOTE: CreateData and DestroyData may be called by multiple threads simultaneously. Thread-safety is a must. diff --git a/docs/en/status.md b/docs/en/status.md index 1d02c871d2..1af19bb506 100644 --- a/docs/en/status.md +++ b/docs/en/status.md @@ -20,7 +20,7 @@ Meanings of the fields above: - **processing**: (renamed to concurrency in master) Number of requests being processed by the method. If this counter can't hit zero when the traffic to the service becomes zero, the server probably has bugs, such as forgetting to call done->Run() or stuck on some processing steps. -Users may customize descriptions on /status by letting the service implement [brpc::Describable](https://github.com/brpc/brpc/blob/master/src/brpc/describable.h). +Users may customize descriptions on /status by letting the service implement [brpc::Describable](https://github.com/apache/brpc/blob/master/src/brpc/describable.h). ```c++ class MyService : public XXXService, public brpc::Describable { diff --git a/docs/en/streaming_rpc.md b/docs/en/streaming_rpc.md index 58ee7a9637..626481d3f8 100644 --- a/docs/en/streaming_rpc.md +++ b/docs/en/streaming_rpc.md @@ -19,7 +19,7 @@ Streaming RPC ensures/provides: We do not support segment large messages automatically so that multiple Streams on a single TCP connection may lead to [Head-of-line blocking](https://en.wikipedia.org/wiki/Head-of-line_blocking) problem. Please avoid putting huge data into single message until we provide automatic segmentation. -For examples please refer to [example/streaming_echo_c++](https://github.com/brpc/brpc/tree/master/example/streaming_echo_c++/). +For examples please refer to [example/streaming_echo_c++](https://github.com/apache/brpc/tree/master/example/streaming_echo_c++/). # Create a Stream diff --git a/docs/en/thrift.md b/docs/en/thrift.md index 5719a321b5..c1d4dce892 100755 --- a/docs/en/thrift.md +++ b/docs/en/thrift.md @@ -2,7 +2,7 @@ [thrift](https://thrift.apache.org/) is a RPC framework used widely in various environments, which was developed by Facebook and adopted by Apache later. In order to interact with thrift servers and solves issues on thread-safety, usabilities and concurrencies, brpc directly supports the thrift protocol that is used by thrift in NonBlocking mode. -Example: [example/thrift_extension_c++](https://github.com/brpc/brpc/tree/master/example/thrift_extension_c++/). +Example: [example/thrift_extension_c++](https://github.com/apache/brpc/tree/master/example/thrift_extension_c++/). Advantages compared to the official solution: - Thread safety. No need to set up separate clients for each thread. diff --git a/docs/en/vars.md b/docs/en/vars.md index e391408032..49ad78095d 100644 --- a/docs/en/vars.md +++ b/docs/en/vars.md @@ -1,6 +1,6 @@ [中文版](../cn/vars.md) -[bvar](https://github.com/brpc/brpc/tree/master/src/bvar/) is a set of counters to record and view miscellaneous statistics conveniently in multi-threaded applications. The implementation reduces cache bouncing by storing data in thread local storage(TLS), being much faster than UbMonitor(a legacy counting library inside Baidu) and even atomic operations in highly contended scenarios. brpc integrates bvar by default, namely all exposed bvars in a server are accessible through [/vars](http://brpc.baidu.com:8765/vars), and a single bvar is addressable by [/vars/VARNAME](http://brpc.baidu.com:8765/vars/rpc_socket_count). Read [bvar](bvar.md) to know how to add bvars for your program. brpc extensively use bvar to expose internal status. If you are looking for an utility to collect and display metrics of your application, consider bvar in the first place. bvar definitely can't replace all counters, essentially it moves contentions occurred during write to read: which needs to combine all data written by all threads and becomes much slower than an ordinary read. If read and write on the counter are both frequent or decisions need to be made based on latest values, you should not use bvar. +[bvar](https://github.com/apache/brpc/tree/master/src/bvar/) is a set of counters to record and view miscellaneous statistics conveniently in multi-threaded applications. The implementation reduces cache bouncing by storing data in thread local storage(TLS), being much faster than UbMonitor(a legacy counting library inside Baidu) and even atomic operations in highly contended scenarios. brpc integrates bvar by default, namely all exposed bvars in a server are accessible through [/vars](http://brpc.baidu.com:8765/vars), and a single bvar is addressable by [/vars/VARNAME](http://brpc.baidu.com:8765/vars/rpc_socket_count). Read [bvar](bvar.md) to know how to add bvars for your program. brpc extensively use bvar to expose internal status. If you are looking for an utility to collect and display metrics of your application, consider bvar in the first place. bvar definitely can't replace all counters, essentially it moves contentions occurred during write to read: which needs to combine all data written by all threads and becomes much slower than an ordinary read. If read and write on the counter are both frequent or decisions need to be made based on latest values, you should not use bvar. ## Query methods diff --git a/src/brpc/builtin/hotspots_service.cpp b/src/brpc/builtin/hotspots_service.cpp index c757732053..adb38d703a 100644 --- a/src/brpc/builtin/hotspots_service.cpp +++ b/src/brpc/builtin/hotspots_service.cpp @@ -422,7 +422,7 @@ static void DisplayResult(Controller* cntl, if (display_type == DisplayType::kFlameGraph && !flamegraph_tool) { return cntl->SetFailed(EINVAL, "Failed to find environment variable " "FLAMEGRAPH_PL_PATH, please read cpu_profiler doc" - "(https://github.com/brpc/brpc/blob/master/docs/cn/cpu_profiler.md)"); + "(https://github.com/apache/brpc/blob/master/docs/cn/cpu_profiler.md)"); } #endif } @@ -893,7 +893,7 @@ static void StartProfiling(ProfilingType type, if (display_type == DisplayType::kFlameGraph && !flamegraph_tool) { return cntl->SetFailed(EINVAL, "Failed to find environment variable " "FLAMEGRAPH_PL_PATH, please read cpu_profiler doc" - "(https://github.com/brpc/brpc/blob/master/docs/cn/cpu_profiler.md)"); + "(https://github.com/apache/brpc/blob/master/docs/cn/cpu_profiler.md)"); } #endif } @@ -1104,8 +1104,8 @@ static void StartProfiling(ProfilingType type, os << "

Error: " << type_str << " profiler is not enabled." << extra_desc << "

" "

To enable all profilers, link tcmalloc and define macros BRPC_ENABLE_CPU_PROFILER" - "

Or read docs: cpu_profiler" - " and heap_profiler" + "

Or read docs: cpu_profiler" + " and heap_profiler" "

"; os.move_to(cntl->response_attachment()); cntl->http_response().set_status_code(HTTP_STATUS_FORBIDDEN); diff --git a/src/brpc/builtin/index_service.cpp b/src/brpc/builtin/index_service.cpp index d3c97c33b5..fec74e8636 100644 --- a/src/brpc/builtin/index_service.cpp +++ b/src/brpc/builtin/index_service.cpp @@ -87,9 +87,9 @@ void IndexService::default_method(::google::protobuf::RpcController* controller, } os << '\n'; if (use_html) { - os << "github"; + os << "github"; } else { - os << "github : https://github.com/brpc/brpc"; + os << "github : https://github.com/apache/brpc"; } os << NL << NL; if (!as_more) { diff --git a/src/brpc/server.cpp b/src/brpc/server.cpp index a7db319321..380ebb20d4 100644 --- a/src/brpc/server.cpp +++ b/src/brpc/server.cpp @@ -1812,7 +1812,7 @@ void Server::PrintTabsBody(std::ostream& os, current_tab_name); } } - os << "
  • ?
  • \n\n" "
    "; // placeholder }