Unverified Commit 9f4c1920 authored by Ge Jun's avatar Ge Jun Committed by GitHub

Merge pull request #521 from brpc/h2_docs

Add h2/grpc docs
parents ea0a56d7 d1da7627
......@@ -8,14 +8,13 @@ An industrial-grade RPC framework used throughout [Baidu](http://ir.baidu.com/ph
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/h2c (compatible with [grpc](https://github.com/grpc/grpc), will be opensourced). using http in brpc is much more friendly than [libcurl](https://curl.haxx.se/libcurl/).
* 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).
* 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.
* all sorts of protocols used in Baidu: [baidu_std](docs/cn/baidu_std.md), [streaming_rpc](docs/en/streaming_rpc.md), hulu_pbrpc, [sofa_pbrpc](https://github.com/baidu/sofa-pbrpc), nova_pbrpc, public_pbrpc, ubrpc and nshead-based ones.
* Access protobuf-based protocols with HTTP+json, probably from another language.
* Build [HA](https://en.wikipedia.org/wiki/High_availability) distributed services using an industrial-grade implementation of [RAFT consensus algorithm](https://raft.github.io) which is opensourced at [braft](https://github.com/brpc/braft)
* Servers can handle requests [synchronously](docs/en/server.md) or [asynchronously](docs/en/server.md#asynchronous-service).
* Clients can access servers [synchronously](docs/en/client.md#synchronus-call), [asynchronously](docs/en/client.md#asynchronous-call), [semi-synchronously](docs/en/client.md#semi-synchronous-call), or use [combo channels](docs/en/combo_channel.md) to simplify sharded or parallel accesses declaratively.
......@@ -39,7 +38,8 @@ You can use it to:
* [Basics](docs/en/client.md)
* [Error code](docs/en/error_code.md)
* [Combo channels](docs/en/combo_channel.md)
* [Access HTTP](docs/en/http_client.md)
* [Access http/h2](docs/en/http_client.md)
* [Access gRPC](docs/en/http_derivatives.md#h2grpc)
* [Access thrift](docs/en/thrift.md#client-accesses-thrift-server)
* [Access UB](docs/cn/ub_client.md)
* [Streaming RPC](docs/en/streaming_rpc.md)
......@@ -49,7 +49,8 @@ You can use it to:
* [Dummy server](docs/en/dummy_server.md)
* Server
* [Basics](docs/en/server.md)
* [Serve HTTP](docs/en/http_service.md)
* [Serve http/h2](docs/en/http_service.md)
* [Serve gRPC](docs/en/http_derivatives.md#h2grpc)
* [Serve thrift](docs/en/thrift.md#server-processes-thrift-requests)
* [Serve Nshead](docs/cn/nshead_service.md)
* [Debug server issues](docs/cn/server_debugging.md)
......
......@@ -9,14 +9,13 @@
你可以使用它:
* 搭建能在**一个端口**支持多协议的服务, 或访问各种服务
* restful http/https, h2/h2c (与[grpc](https://github.com/grpc/grpc)兼容, 即将开源). 使用brpc的http实现比[libcurl](https://curl.haxx.se/libcurl/)方便多了。
* 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).
* hadoop_rpc(可能开源)
* 支持[rdma](https://en.wikipedia.org/wiki/Remote_direct_memory_access)(即将开源)
* 支持[thrift](docs/cn/thrift.md) , 线程安全,比官方client更方便
* 各种百度内使用的协议: [baidu_std](docs/cn/baidu_std.md), [streaming_rpc](docs/cn/streaming_rpc.md), hulu_pbrpc, [sofa_pbrpc](https://github.com/baidu/sofa-pbrpc), nova_pbrpc, public_pbrpc, ubrpc和使用nshead的各种协议.
* 从其他语言通过HTTP+json访问基于protobuf的协议.
* 基于工业级的[RAFT算法](https://raft.github.io)实现搭建[高可用](https://en.wikipedia.org/wiki/High_availability)分布式系统,已在[braft](https://github.com/brpc/braft)开源。
* Server能[同步](docs/cn/server.md)[异步](docs/cn/server.md#异步service)处理请求。
* Client支持[同步](docs/cn/client.md#同步访问)[异步](docs/cn/client.md#异步访问)[半同步](docs/cn/client.md#半同步),或使用[组合channels](docs/cn/combo_channel.md)简化复杂的分库或并发访问。
......@@ -40,7 +39,8 @@
* [基础功能](docs/cn/client.md)
* [错误码](docs/cn/error_code.md)
* [组合channels](docs/cn/combo_channel.md)
* [访问HTTP](docs/cn/http_client.md)
* [访问http/h2](docs/cn/http_client.md)
* [访问gRPC](docs/cn/http_derivatives.md#h2grpc)
* [访问thrift](docs/cn/thrift.md#client端访问thrift-server)
* [访问UB](docs/cn/ub_client.md)
* [Streaming RPC](docs/cn/streaming_rpc.md)
......@@ -50,7 +50,8 @@
* [Dummy server](docs/cn/dummy_server.md)
* Server
* [基础功能](docs/cn/server.md)
* [搭建HTTP服务](docs/cn/http_service.md)
* [搭建http/h2服务](docs/cn/http_service.md)
* [搭建gRPC服务](docs/cn/http_derivatives.md#h2grpc)
* [搭建thrift服务](docs/cn/thrift.md#server端处理thrift请求)
* [搭建Nshead服务](docs/cn/nshead_service.md)
* [高效率排查server卡顿](docs/cn/server_debugging.md)
......
This diff is collapsed.
......@@ -121,6 +121,10 @@ BNS是百度内常用的命名服务,比如bns://rdev.matrix.all,其中"bns"
缺点: 受限于DNS的格式限制无法传递复杂的meta数据,也无法实现通知机制。
### https://\<url\>
和http前缀类似,只是会自动开启SSL。
### consul://\<service-name\>
通过consul获取服务名称为service-name的服务列表。consul的默认地址是localhost:8500,可通过gflags设置-consul\_agent\_addr来修改。consul的连接超时时间默认是200ms,可通过-consul\_connect\_timeout\_ms来修改。
......@@ -251,7 +255,7 @@ stub.some_method(controller, request, response, done);
```c++
XXX_Stub(&channel).some_method(controller, request, response, done);
```
一个例外是http client。访问http服务和protobuf没什么关系,直接调用CallMethod即可,除了Controller和done均为NULL,详见[访问HTTP服务](http_client.md)
一个例外是http/h2 client。访问http服务和protobuf没什么关系,直接调用CallMethod即可,除了Controller和done均为NULL,详见[访问http/h2服务](http_client.md)
## 同步访问
......@@ -531,7 +535,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相关的错误,而你的程序中希望在碰到HTTP_STATUS_FORBIDDEN (403)时重试,可以这么做:
用户可以通过继承[brpc::RetryPolicy](https://github.com/brpc/brpc/blob/master/src/brpc/retry_policy.h)自定义重试条件。比如brpc默认不重试http/h2相关的错误,而你的程序中希望在碰到HTTP_STATUS_FORBIDDEN (403)时重试,可以这么做:
```c++
#include <brpc/retry_policy.h>
......@@ -539,7 +543,7 @@ Controller.set_max_retry(0)或ChannelOptions.max_retry=0关闭重试。
class MyRetryPolicy : public brpc::RetryPolicy {
public:
bool DoRetry(const brpc::Controller* cntl) const {
if (cntl->ErrorCode() == brpc::EHTTP && // HTTP错误
if (cntl->ErrorCode() == brpc::EHTTP && // http/h2错误
cntl->http_response().status_code() == brpc::HTTP_STATUS_FORBIDDEN) {
return true;
}
......@@ -573,19 +577,25 @@ Channel的默认协议是baidu_std,可通过设置ChannelOptions.protocol换
目前支持的有:
- PROTOCOL_BAIDU_STD 或 “baidu_std",即[百度标准协议](baidu_std.md),默认为单连接。
- PROTOCOL_HTTP 或 ”http", http/1.0或http/1.1协议,默认为连接池(Keep-Alive)。
- 访问普通http服务的方法见[访问http/h2服务](http_client.md)
- 通过http:json或http:proto访问pb服务的方法见[基于http/h2的协议](http_derivatives.md)
- PROTOCOL_H2 或 ”h2", http/2.0协议,默认是单连接。
- 访问普通h2服务的方法见[访问http/h2服务](http_client.md)
- 通过h2:json或h2:proto访问pb服务的方法见[基于http/h2的协议](http_derivatives.md)
- "h2:grpc", [gRPC](https://grpc.io)的协议,也是h2的衍生协议,默认为单连接,具体见[基于http/h2的协议](http_derivatives.md)
- PROTOCOL_THRIFT 或 "thrift",[apache thrift](https://thrift.apache.org)的协议,默认为连接池, 具体方法见[访问thrift](thrift.md)
- PROTOCOL_MEMCACHE 或 "memcache",memcached的二进制协议,默认为单连接。具体方法见[访问memcached](memcache_client.md)
- PROTOCOL_REDIS 或 "redis",redis 1.2后的协议(也是hiredis支持的协议),默认为单连接。具体方法见[访问Redis](redis_client.md)
- PROTOCOL_HULU_PBRPC 或 "hulu_pbrpc",hulu的协议,默认为单连接。
- PROTOCOL_NOVA_PBRPC 或 ”nova_pbrpc“,网盟的协议,默认为连接池。
- PROTOCOL_HTTP 或 ”http", http 1.0或1.1协议,默认为连接池(Keep-Alive)。具体方法见[访问HTTP服务](http_client.md)
- PROTOCOL_SOFA_PBRPC 或 "sofa_pbrpc",sofa-pbrpc的协议,默认为单连接。
- PROTOCOL_PUBLIC_PBRPC 或 "public_pbrpc",public_pbrpc的协议,默认为连接池。
- PROTOCOL_UBRPC_COMPACK 或 "ubrpc_compack",public/ubrpc的协议,使用compack打包,默认为连接池。具体方法见[ubrpc (by protobuf)](ub_client.md)。相关的还有PROTOCOL_UBRPC_MCPACK2或ubrpc_mcpack2,使用mcpack2打包。
- PROTOCOL_NSHEAD_CLIENT 或 "nshead_client",这是发送baidu-rpc-ub中所有UBXXXRequest需要的协议,默认为连接池。具体方法见[访问UB](ub_client.md)
- PROTOCOL_NSHEAD 或 "nshead",这是发送NsheadMessage需要的协议,默认为连接池。具体方法见[nshead+blob](ub_client.md#nshead-blob)
- PROTOCOL_MEMCACHE 或 "memcache",memcached的二进制协议,默认为单连接。具体方法见[访问memcached](memcache_client.md)
- PROTOCOL_REDIS 或 "redis",redis 1.2后的协议(也是hiredis支持的协议),默认为单连接。具体方法见[访问Redis](redis_client.md)
- PROTOCOL_NSHEAD_MCPACK 或 "nshead_mcpack", 顾名思义,格式为nshead + mcpack,使用mcpack2pb适配,默认为连接池。
- PROTOCOL_ESP 或 "esp",访问使用esp协议的服务,默认为连接池。
- PROTOCOL_THRIFT 或 "thrift",访问使用thrift协议的服务,默认为连接池, 具体方法见[访问thrift](thrift.md)
## 连接方式
......@@ -661,7 +671,7 @@ brpc支持[Streaming RPC](streaming_rpc.md),这是一种应用层的连接,
baidu_std和hulu_pbrpc协议支持附件,这段数据由用户自定义,不经过protobuf的序列化。站在client的角度,设置在Controller::request_attachment()的附件会被server端收到,response_attachment()则包含了server端送回的附件。附件不受压缩选项影响。
在http协议中,附件对应[message body](http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html),比如要POST的数据就设置在request_attachment()中。
在http/h2协议中,附件对应[message body](http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html),比如要POST的数据就设置在request_attachment()中。
## 开启SSL
......@@ -718,7 +728,7 @@ set_request_compress_type()设置request的压缩方式,默认不压缩。
注意:附件不会被压缩。
HTTP body的压缩方法见[client压缩request body](http_client#压缩request-body)
http/h2 body的压缩方法见[client压缩request body](http_client#压缩request-body)
支持的压缩方法有:
......
......@@ -4,22 +4,28 @@
[example/http_c++](https://github.com/brpc/brpc/blob/master/example/http_c++/http_client.cpp)
# 关于h2
brpc把HTTP/2协议统称为"h2",不论是否加密。然而未开启ssl的HTTP/2连接在/connections中会按官方名称h2c显示,而开启ssl的会显示为h2。
brpc中http和h2的编程接口基本没有区别。除非特殊说明,所有提到的http特性都同时对h2有效。
# 创建Channel
brpc::Channel可访问HTTP服务,ChannelOptions.protocol须指定为PROTOCOL_HTTP
brpc::Channel可访问http/h2服务,ChannelOptions.protocol须指定为PROTOCOL_HTTP或PROTOCOL_H2
设定为HTTP协议后,`Channel::Init`的第一个参数可为任意合法的URL。注意:允许任意URL是为了省去用户取出host和port的麻烦,`Channel::Init`只用其中的host及port,其他部分都会丢弃。
设定协议后,`Channel::Init`的第一个参数可为任意合法的URL。注意:允许任意URL是为了省去用户取出host和port的麻烦,`Channel::Init`只用其中的host及port,其他部分都会丢弃。
```c++
brpc::ChannelOptions options;
options.protocol = brpc::PROTOCOL_HTTP;
options.protocol = brpc::PROTOCOL_HTTP; // or brpc::PROTOCOL_H2
if (channel.Init("www.baidu.com" /*any url*/, &options) != 0) {
LOG(ERROR) << "Fail to initialize channel";
return -1;
}
```
http channel也支持bns地址或其他NamingService。
http/h2 channel也支持bns地址或其他NamingService。
# GET
......@@ -29,7 +35,7 @@ cntl.http_request().uri() = "www.baidu.com/index.html"; // 设置为待访问
channel.CallMethod(NULL, &cntl, NULL, NULL, NULL/*done*/);
```
HTTP和protobuf关系不大,所以除了Controller和done,CallMethod的其他参数均为NULL。如果要异步操作,最后一个参数传入done。
HTTP/h2和protobuf关系不大,所以除了Controller和done,CallMethod的其他参数均为NULL。如果要异步操作,最后一个参数传入done。
`cntl.response_attachment()`是回复的body,类型也是butil::IOBuf。IOBuf可通过to_string()转化为std::string,但是需要分配内存并拷贝所有内容,如果关注性能,处理过程应直接支持IOBuf,而不要求连续内存。
......@@ -56,6 +62,18 @@ os << "A lot of printing" << printable_objects << ...;
os.move_to(cntl.request_attachment());
channel.CallMethod(NULL, &cntl, NULL, NULL, NULL/*done*/);
```
# 控制HTTP版本
brpc的http行为默认是http 1.1。
http 1.0相比1.1缺少长连接功能,brpc client与一些古老的http server通信时可能需要按如下方法设置为1.0。
```c++
cntl.http_request().set_version(1, 0);
```
设置http版本对h2无效,但是client收到的h2 response和server收到的h2 request中的version会被设置为(2, 0)。
brpc server会自动识别HTTP版本,并相应回复,无需用户设置。
# URL
......@@ -87,17 +105,19 @@ URL的一般形式如下图:
确实,在简单使用场景下,这两者有所重复,但在复杂场景中,两者差别很大,比如:
- 访问命名服务(如BNS)下的多个http server。此时Channel.Init传入的是对该命名服务有意义的名称(如BNS中的节点名称),对uri()的赋值则是包含Host的完整URL(比如"www.foo.com/index.html?name=value")。
- 通过http proxy访问目标server。此时Channel.Init传入的是proxy server的地址,但uri()填入的是目标server的URL。
- 访问命名服务(如BNS)下的多个http/h2 server。此时Channel.Init传入的是对该命名服务有意义的名称(如BNS中的节点名称),对uri()的赋值则是包含Host的完整URL(比如"www.foo.com/index.html?name=value")。
- 通过http/h2 proxy访问目标server。此时Channel.Init传入的是proxy server的地址,但uri()填入的是目标server的URL。
## Host字段
若用户自己填写了host字段(http header),框架不会修改。
若用户自己填写了"host"字段(大小写不敏感),框架不会修改。
若用户没有填且URL中包含host,比如http://www.foo.com/path,则http request中会包含"Host: www.foo.com"。
若用户没有填且URL不包含host,比如"/index.html?name=value",则框架会以目标server的ip和port为Host,地址为10.46.188.39:8989的http server将会看到"Host: 10.46.188.39:8989"。
对应的字段在h2中叫":authority"。
# 常见设置
以http request为例 (对response的操作自行替换), 常见操作方式如下所示:
......@@ -118,7 +138,7 @@ const std::string* value = cntl->http_request().uri().GetQuery("Foo"); // 不存
```c++
cntl->http_request().uri().SetQuery("Foo", "value");
```
设置HTTP方法
设置HTTP Method
```c++
cntl->http_request().set_method(brpc::HTTP_METHOD_POST);
```
......@@ -150,11 +170,11 @@ Notes on http header:
# 查看HTTP消息
打开[-http_verbose](http://brpc.baidu.com:8765/flags/http_verbose)即可看到所有的http request和response,注意这应该只用于线下调试,而不是线上程序。
打开[-http_verbose](http://brpc.baidu.com:8765/flags/http_verbose)即可看到所有的http/h2 request和response,注意这应该只用于线下调试,而不是线上程序。
# HTTP错误
当Server返回的http status code不是2xx时,该次http访问被视为失败,client端会把`cntl->ErrorCode()`设置为EHTTP,用户可通过`cntl->http_response().status_code()`获得具体的http错误。同时server端可以把代表错误的html或json置入`cntl->response_attachment()`作为http body传递回来。
当Server返回的http status code不是2xx时,该次http/h2访问被视为失败,client端会把`cntl->ErrorCode()`设置为EHTTP,用户可通过`cntl->http_response().status_code()`获得具体的http错误。同时server端可以把代表错误的html或json置入`cntl->response_attachment()`作为http body传递回来。
# 压缩request body
......
[English version](../en/http_derivatives.md)
http协议的基本用法见[http_client](http_client.md)[http_service](http_service.md)
下文中的小节名均为可填入ChannelOptions.protocol中的协议名。冒号后的内容是协议参数,用于动态选择衍生行为,但基本协议仍然是http/1.x或http/2,故这些协议在服务端只会被显示为http或h2/h2c。
# http:json, h2:json
如果pb request不为空,则会被转为json并作为http/h2请求的body,此时Controller.request_attachment()必须为空否则报错。
如果pb response不为空,则会以json解析http/h2回复的body,并转填至pb response的对应字段。
http/1.x默认是这个行为,所以"http"和"http:json"等价。
# http:proto, h2:proto
如果pb request不为空,则会把pb序列化结果作为http/h2请求的body,此时Controller.request_attachment()必须为空否则报错。
如果pb response不为空,则会以pb序列化格式解析http/h2回复的body,并填至pb response。
http/2默认是这个行为,所以"h2"和"h2:proto"等价。
# h2:grpc
[gRPC](https://github.com/grpc)的默认协议,具体格式可阅读[gRPC over HTTP2](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md)
使用brpc的客户端把ChannelOptions.protocol设置为"h2:grpc"一般就能连通gRPC。
使用brpc的服务端一般无需修改代码即可自动被gRPC客户端访问。
gRPC默认序列化是pb二进制格式,所以"h2:grpc"和"h2:grpc+proto"等价。
TODO: gRPC其他配置
# h2:grpc+json
这个协议相比h2:grpc就是用json序列化结果代替pb序列化结果。gRPC未必直接支持这个格式,如grpc-go可参考[这里](https://github.com/johanbrandhorst/grpc-json-example/blob/master/codec/json.go)注册对应的codec后才会支持。
[English version](../en/http_service.md)
这里指我们通常说的HTTP服务,而不是可通过HTTP访问的pb服务。
这里指我们通常说的http/h2服务,而不是可通过http/h2访问的pb服务。
虽然用不到pb消息,但brpc中的HTTP服务接口也得定义在.proto文件中,只是request和response都是空的结构体。这确保了所有的服务声明集中在proto文件中,而不是散列在proto文件、程序、配置等多个地方。示例代码见[http_server.cpp](https://github.com/brpc/brpc/blob/master/example/http_c++/http_server.cpp)
虽然用不到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)
# 关于h2
brpc把HTTP/2协议统称为"h2",不论是否加密。然而未开启ssl的HTTP/2连接在/connections中会按官方名称h2c显示,而开启ssl的会显示为h2。
brpc中http和h2的编程接口基本没有区别。除非特殊说明,所有提到的http特性都同时对h2有效。
# URL类型
## 前缀为/ServiceName/MethodName
定义一个service名为ServiceName(不包含package名), method名为MethodName的pb服务,且让request和reponse定义为空,则该服务默认在/ServiceName/MethodName上提供HTTP服务。
定义一个service名为ServiceName(不包含package名), method名为MethodName的pb服务,且让request和reponse定义为空,则该服务默认在/ServiceName/MethodName上提供http/h2服务。
request和response可为空是因为http数据在Controller中:
request和response可为空是因为数据都在Controller中:
* http request的header在Controller.http_request()中,body在Controller.request_attachment()中。
* http response的header在Controller.http_response()中,body在Controller.response_attachment()中。
* http/h2 request的header在Controller.http_request()中,body在Controller.request_attachment()中。
* http/h2 response的header在Controller.http_response()中,body在Controller.response_attachment()中。
实现步骤如下:
......@@ -71,7 +80,7 @@ public:
## 前缀为/ServiceName
资源类的HTTP服务可能需要这样的URL,ServiceName后均为动态内容。比如/FileService/foobar.txt代表./foobar.txt,/FileService/app/data/boot.cfg代表./app/data/boot.cfg。
资源类的http/h2服务可能需要这样的URL,ServiceName后均为动态内容。比如/FileService/foobar.txt代表./foobar.txt,/FileService/app/data/boot.cfg代表./app/data/boot.cfg。
实现方法:
......@@ -120,15 +129,15 @@ public:
brpc支持为service中的每个方法指定一个URL。API如下:
```c++
// 如果restful_mappings不为空, service中的方法可通过指定的URL被HTTP协议访问,而不是/ServiceName/MethodName.
// 如果restful_mappings不为空, service中的方法可通过指定的URL被http/h2协议访问,而不是/ServiceName/MethodName.
// 映射格式:"PATH1 => NAME1, PATH2 => NAME2 ..."
// PATHs是有效的HTTP路径, NAMEs是service中的方法名.
// PATHs是有效的路径, NAMEs是service中的方法名.
int AddService(google::protobuf::Service* service,
ServiceOwnership ownership,
butil::StringPiece restful_mappings);
```
下面的QueueService包含多个http方法。如果我们像之前那样把它插入server,那么只能通过`/QueueService/start, /QueueService/stop`等url来访问。
下面的QueueService包含多个方法。如果我们像之前那样把它插入server,那么只能通过`/QueueService/start, /QueueService/stop`等url来访问。
```protobuf
service QueueService {
......@@ -167,7 +176,7 @@ if (server.AddService(&queue_svc,
关于映射规则:
- 多个路径可映射至同一个方法。
- service不要求是纯HTTP,pb service也支持。
- service不要求是纯http/h2,pb service也支持。
- 没有出现在映射中的方法仍旧通过/ServiceName/MethodName访问。出现在映射中的方法不再能通过/ServiceName/MethodName访问。
- ==> ===> ...都是可以的。开头结尾的空格,额外的斜杠(/),最后多余的逗号,都不要紧。
- PATH和PATH/*两者可以共存。
......@@ -273,7 +282,7 @@ cntl->http_request().uri().SetQuery("time", "2015/1/2");
# 调试
打开[-http_verbose](http://brpc.baidu.com:8765/flags/http_verbose)即可看到所有的http request和response,注意这应该只用于线下调试,而不是线上程序。
打开[-http_verbose](http://brpc.baidu.com:8765/flags/http_verbose)即可看到所有的http/h2 request和response,注意这应该只用于线下调试,而不是线上程序。
# 压缩response body
......
......@@ -42,13 +42,13 @@ RPC不是万能的抽象,否则我们也不需要TCP/IP这一层了。但是
你可以使用它:
* 搭建能在**一个端口**支持多协议的服务, 或访问各种服务
* restful http/https, h2/h2c (与[grpc](https://github.com/grpc/grpc)兼容, 即将开源). 使用brpc的http实现比[libcurl](https://curl.haxx.se/libcurl/)方便多了。
* 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).
* hadoop_rpc(可能开源)
* 支持[rdma](https://en.wikipedia.org/wiki/Remote_direct_memory_access)(即将开源)
* 支持[thrift](thrift.md) , 线程安全,比官方client更方便
* 各种百度内使用的协议: [baidu_std](baidu_std.md), [streaming_rpc](streaming_rpc.md), hulu_pbrpc, [sofa_pbrpc](https://github.com/baidu/sofa-pbrpc), nova_pbrpc, public_pbrpc, ubrpc和使用nshead的各种协议.
* 从其他语言通过HTTP+json访问基于protobuf的协议.
* 基于工业级的[RAFT算法](https://raft.github.io)实现搭建[高可用](https://en.wikipedia.org/wiki/High_availability)分布式系统,已在[braft](https://github.com/brpc/braft)开源。
* Server能[同步](server.md)[异步](server.md#异步service)处理请求。
* Client支持[同步](client.md#同步访问)[异步](client.md#异步访问)[半同步](client.md#半同步),或使用[组合channels](combo_channel.md)简化复杂的分库或并发访问。
......
......@@ -249,9 +249,11 @@ server.RunUntilAskedToQuit();
Join()完成后可以修改其中的Service,并重新Start。
# 被HTTP client访问
# 被http/h2访问
使用Protobuf的服务通常可以通过HTTP+json访问,存于http body的json串可与对应protobuf消息相互转化。以[echo server](https://github.com/brpc/brpc/blob/master/example/echo_c%2B%2B/server.cpp)为例,你可以用[curl](https://curl.haxx.se/)访问这个服务。
使用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/)访问这个服务。
```shell
# -H 'Content-Type: application/json' is optional
......@@ -259,7 +261,7 @@ $ curl -d '{"message":"hello"}' http://brpc.baidu.com:8765/EchoService/Echo
{"message":"hello"}
```
注意:也可以指定`Content-Type: application/proto`用http+protobuf二进制串访问服务,序列化性能更好。
注意:也可以指定`Content-Type: application/proto`用http/h2+protobuf二进制串访问服务,序列化性能更好。
## json<=>pb
......@@ -269,7 +271,7 @@ json字段通过匹配的名字和结构与pb字段一一对应。json中一定
## 兼容早期版本client
早期的brpc允许一个pb service被http协议访问时不设置pb请求,即使里面有required字段。一般来说这种service会自行解析http请求和设置http回复,并不会访问pb请求。但这也是非常危险的行为,毕竟这是pb service,但pb请求却是未定义的。
早期的brpc允许一个pb service被http协议访问时不填充pb请求,即使里面有required字段。一般来说这种service会自行解析http请求和设置http回复,并不会访问pb请求。但这也是非常危险的行为,毕竟这是pb service,但pb请求却是未定义的。
这种服务在升级到新版本rpc时会遇到障碍,因为brpc已不允许这种行为。为了帮助这种服务升级,brpc允许经过一些设置后不把http body自动转化为pb request(从而可自行处理),方法如下:
......@@ -277,11 +279,11 @@ json字段通过匹配的名字和结构与pb字段一一对应。json中一定
brpc::ServiceOptions svc_opt;
svc_opt.ownership = ...;
svc_opt.restful_mappings = ...;
svc_opt.allow_http_body_to_pb = false; //关闭http body至pb request的自动转化
svc_opt.allow_http_body_to_pb = false; //关闭http/h2 body至pb request的自动转化
server.AddService(service, svc_opt);
```
如此设置后service收到http请求后不会尝试把body转化为pb请求,所以pb请求总是未定义状态,用户得在`cntl->request_protocol() == brpc::PROTOCOL_HTTP`认定请求是http时自行解析http body。
如此设置后service收到http/h2请求后不会尝试把body转化为pb请求,所以pb请求总是未定义状态,用户得在`cntl->request_protocol() == brpc::PROTOCOL_HTTP || cntl->request_protocol() == brpc::PROTOCOL_H2`成立时自行解析body。
相应地,当cntl->response_attachment()不为空且pb回复不为空时,框架不再报错,而是直接把cntl->response_attachment()作为回复的body。这个功能和设置allow_http_body_to_pb与否无关。如果放开自由度导致过多的用户犯错,可能会有进一步的调整。
......@@ -293,7 +295,9 @@ server端会自动尝试其支持的协议,无需用户指定。`cntl->protoco
- [流式RPC协议](streaming_rpc.md),显示为"streaming_rpc", 默认启用。
- http 1.0/1.1,显示为”http“,默认启用。
- http/1.0和http/1.1协议,显示为”http“,默认启用。
- http/2和gRPC协议,显示为"h2c"(未加密)或"h2"(加密),默认启用。
- RTMP协议,显示为"rtmp", 默认启用。
......
......@@ -123,6 +123,10 @@ Pros: Versatility of DNS, useable both in private or public network.
Cons: limited by transmission formats of DNS, unable to implement notification mechanisms.
### https://\<url\>
Similar with "http" prefix besides that the connections will be encrypted with SSL.
### consul://\<service-name\>
Get a list of servers with the specified service-name through consul. The default address of consul is localhost:8500, which can be modified by setting -consul\_agent\_addr in gflags. The connection timeout of consul is 200ms by default, which can be modified by -consul\_connect\_timeout\_ms.
......@@ -253,7 +257,7 @@ Or even:
```c++
XXX_Stub(&channel).some_method(controller, request, response, done);
```
A exception is http client, which is not related to protobuf much. Call CallMethod directly to make a http call, setting all parameters to NULL except for `Controller` and `done`, check [Access HTTP](http_client.md) for details.
A exception is http/h2 client, which is not related to protobuf much. Call CallMethod directly to make a http call, setting all parameters to NULL except for `Controller` and `done`, check [Access http/h2](http_client.md) for details.
## Synchronous call
......@@ -540,7 +544,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 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/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:
```c++
#include <brpc/retry_policy.h>
......@@ -548,7 +552,7 @@ Users can inherit [brpc::RetryPolicy](https://github.com/brpc/brpc/blob/master/s
class MyRetryPolicy : public brpc::RetryPolicy {
public:
bool DoRetry(const brpc::Controller* cntl) const {
if (cntl->ErrorCode() == brpc::EHTTP && // HTTP error
if (cntl->ErrorCode() == brpc::EHTTP && // http/h2 error
cntl->http_response().status_code() == brpc::HTTP_STATUS_FORBIDDEN) {
return true;
}
......@@ -582,16 +586,23 @@ The default protocol used by Channel is baidu_std, which is changeable by settin
Supported protocols:
- PROTOCOL_BAIDU_STD or "baidu_std", which is [the standard binary protocol inside Baidu](baidu_std.md), using single connection by default.
- PROTOCOL_HTTP or "http", which is http/1.0 or http/1.1, using pooled connection by default (Keep-Alive).
- Methods for accessing ordinary http services are listed in [Access http/h2](http_client.md).
- Methods for accessing pb services by using http:json or http:proto are listed in [Protocols based on http/h2](http_derivatives.md)
- PROTOCOL_H2 or ”h2", which is http/2.0, using single connection by default.
- Methods for accessing ordinary h2 services are listed in [Access http/h2](http_client.md).
- Methods for accessing pb services by using h2:json or h2:proto are listed in [Protocols based on http/h2](http_derivatives.md)
- "h2:grpc", which is the protocol of [gRPC](https://grpc.io) and based on h2, using single connection by default, check out [Protocols based on http/h2](http_derivatives.md) for details.
- PROTOCOL_THRIFT or "thrift", which is the protocol of [apache thrift](https://thrift.apache.org), using pooled connection by default, check out [access thrift](thrift.md) for details.
- PROTOCOL_MEMCACHE or "memcache", which is binary protocol of memcached, using **single connection** by default. Check out [access memcached](memcache_client.md) for details.
- PROTOCOL_REDIS or "redis", which is protocol of redis 1.2+ (the one supported by hiredis), using **single connection** by default. Check out [Access Redis](redis_client.md) for details.
- PROTOCOL_HULU_PBRPC or "hulu_pbrpc", which is protocol of hulu-pbrpc, using single connection by default.
- PROTOCOL_NOVA_PBRPC or "nova_pbrpc", which is protocol of Baidu ads union, using pooled connection by default.
- PROTOCOL_HTTP or "http", which is http 1.0 or 1.1, using pooled connection by default (Keep-Alive). Check out [Access HTTP service](http_client.md) for details.
- PROTOCOL_SOFA_PBRPC or "sofa_pbrpc", which is protocol of sofa-pbrpc, using single connection by default.
- PROTOCOL_PUBLIC_PBRPC or "public_pbrpc", which is protocol of public_pbrpc, using pooled connection by default.
- PROTOCOL_UBRPC_COMPACK or "ubrpc_compack", which is protocol of public/ubrpc, packing with compack, using pooled connection by default. check out [ubrpc (by protobuf)](ub_client.md) for details. A related protocol is PROTOCOL_UBRPC_MCPACK2 or ubrpc_mcpack2, packing with mcpack2.
- PROTOCOL_NSHEAD_CLIENT or "nshead_client", which is required by UBXXXRequest in baidu-rpc-ub, using pooled connection by default. Check out [Access UB](ub_client.md) for details.
- PROTOCOL_NSHEAD or "nshead", which is required by sending NsheadMessage, using pooled connection by default. Check out [nshead+blob](ub_client.md#nshead-blob) for details.
- PROTOCOL_MEMCACHE or "memcache", which is binary protocol of memcached, using **single connection** by default. Check out [access memcached](memcache_client.md) for details.
- PROTOCOL_REDIS or "redis", which is protocol of redis 1.2+ (the one supported by hiredis), using **single connection** by default. Check out [Access Redis](redis_client.md) for details.
- PROTOCOL_NSHEAD_MCPACK or "nshead_mcpack", which is as the name implies, nshead + mcpack (parsed by protobuf via mcpack2pb), using pooled connection by default.
- PROTOCOL_ESP or "esp", for accessing services with esp protocol, using pooled connection by default.
......@@ -600,7 +611,7 @@ The default protocol used by Channel is baidu_std, which is changeable by settin
brpc supports following connection types:
- short connection: Established before each RPC, closed after completion. Since each RPC has to pay the overhead of establishing connection, this type is used for occasionally launched RPC, not frequently launched ones. No protocol use this type by default. Connections in http 1.0 are handled similarly as short connections.
- pooled connection: Pick an unused connection from a pool before each RPC, return after completion. One connection carries at most one request at the same time. One client may have multiple connections to one server. http and the protocols using nshead use this type by default.
- pooled connection: Pick an unused connection from a pool before each RPC, return after completion. One connection carries at most one request at the same time. One client may have multiple connections to one server. http 1.1 and the protocols using nshead use this type by default.
- single connection: all clients in one process has at most one connection to one server, one connection may carry multiple requests at the same time. The sequence of received responses does not need to be same as sending requests. This type is used by baidu_std, hulu_pbrpc, sofa_pbrpc by default.
| | short connection | pooled connection | single connection |
......@@ -671,7 +682,7 @@ baidu_std and hulu_pbrpc supports attachments which are sent along with messages
Attachment is not compressed by framework.
In http, attachment corresponds to [message body](http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html), namely the data to post to server is stored in request_attachment().
In http/h2, attachment corresponds to [message body](http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html), namely the data to post to server is stored in request_attachment().
## Turn on SSL
......@@ -729,7 +740,7 @@ set_request_compress_type() sets compress-type of the request, no compression by
NOTE: Attachment is not compressed by brpc.
Check out [compress request body](http_client#压缩request-body) to compress http body.
Check out [compress request body](http_client#压缩request-body) to compress http/h2 body.
Supported compressions:
......
......@@ -4,22 +4,28 @@
[example/http_c++](https://github.com/brpc/brpc/blob/master/example/http_c++/http_client.cpp)
# About h2
brpc names the HTTP/2 protocol to "h2", no matter encrypted or not. However HTTP/2 connections without SSL are shown on /connections with the official name "h2c", and the ones with SSL are shown as "h2".
The APIs for http and h2 in brpc are basically same. Without explicit statement, mentioned http features work for h2 as well.
# Create Channel
In order to use `brpc::Channel` to access HTTP services, `ChannelOptions.protocol` must be set to `PROTOCOL_HTTP`.
In order to use `brpc::Channel` to access http/h2 services, `ChannelOptions.protocol` must be set to `PROTOCOL_HTTP` or `PROTOCOL_H2`.
Once the HTTP protocol is set, the first parameter of `Channel::Init` can be any valid URL. *Note*: Only host and port inside the URL are used by Init(), other parts are discarded. Allowing full URL simply saves the user from additional parsing code.
Once the protocol is set, the first parameter of `Channel::Init` can be any valid URL. *Note*: Only host and port inside the URL are used by Init(), other parts are discarded. Allowing full URL simply saves the user from additional parsing code.
```c++
brpc::ChannelOptions options;
options.protocol = brpc::PROTOCOL_HTTP;
options.protocol = brpc::PROTOCOL_HTTP; // or brpc::PROTOCOL_H2
if (channel.Init("www.baidu.com" /*any url*/, &options) != 0) {
LOG(ERROR) << "Fail to initialize channel";
return -1;
}
```
http channel also support BNS address or other naming services.
http/h2 channel also support BNS address or other naming services.
# GET
......@@ -29,9 +35,9 @@ cntl.http_request().uri() = "www.baidu.com/index.html"; // Request URL
channel.CallMethod(NULL, &cntl, NULL, NULL, NULL/*done*/);
```
HTTP does not relate to protobuf much, thus all parameters of `CallMethod` are NULL except `Controller` and `done`. Issue asynchronous RPC with non-NULL `done`.
http/h2 does not relate to protobuf much, thus all parameters of `CallMethod` are NULL except `Controller` and `done`. Issue asynchronous RPC with non-NULL `done`.
`cntl.response_attachment()` is body of the http response and typed `butil::IOBuf`. `IOBuf` can be converted to `std::string` by `to_string()`, which needs to allocate memory and copy all data. If performance is important, the code should consider supporting `IOBuf` directly rather than requiring continuous memory.
`cntl.response_attachment()` is body of the http/h2 response and typed `butil::IOBuf`. `IOBuf` can be converted to `std::string` by `to_string()`, which needs to allocate memory and copy all data. If performance is important, the code should consider supporting `IOBuf` directly rather than requiring continuous memory.
# POST
......@@ -57,6 +63,19 @@ os.move_to(cntl.request_attachment());
channel.CallMethod(NULL, &cntl, NULL, NULL, NULL/*done*/);
```
# Change HTTP version
brpc behaves as http 1.1 by default.
Comparing to 1.1, http 1.0 lacks of long connections(KeepAlive). To communicate brpc client with some legacy http servers, the client may be configured as follows:
```c++
cntl.http_request().set_version(1, 0);
```
Setting http version does not work for h2, but the versions in h2 responses received by client and h2 requests received by server are set to (2, 0).
brpc server recognizes http versions automically and responds accordingly without users' aid.
# URL
Genaral form of an URL:
......@@ -88,16 +107,18 @@ As we saw in examples above, `Channel.Init()` and `cntl.http_request().uri()` bo
Indeed, the settings are repeated in simple cases. But they are different in more complex scenes:
- Access multiple servers under a NamingService (for example BNS), in which case `Channel::Init` accepts a name meaningful to the NamingService(for example node names in BNS), while `uri()` is assigned with the URL.
- Access servers via http proxy, in which case `Channel::Init` takes the address of the proxy server, while `uri()` is still assigned with the URL.
- Access servers via http/h2 proxy, in which case `Channel::Init` takes the address of the proxy server, while `uri()` is still assigned with the URL.
## Host header
If user already sets `Host` (a http header), framework makes no change.
If user already sets `Host` header(case insensitive), framework makes no change.
If user does not set `Host` header and the URL has host, for example http://www.foo.com/path, the http request contains "Host: www.foo.com".
If user does not set host header and the URL does not have host as well, for example "/index.html?name=value", framework sets `Host` header with IP and port of the target server. A http server at 10.46.188.39:8989 should see `Host: 10.46.188.39:8989`.
The header is named ":authority" in h2.
# Common usages
Take http request as an example (similar with http response), common operations are listed as follows:
......
[中文版](../cn/http_derivatives.md)
Basics for accessing and serving http in brpc are listed in [http_client](http_client.md) and [http_service](http_service.md).
Following section names are protocol names that can be directly set to ChannelOptions.protocol. The content after colon is parameters for the protocol to select derivative behaviors dynamically, but the base protocol is still http/1.x or http/2. As a result, these protocols are displayed at server-side as http or h2/h2c only.
# http:json, h2:json
Non-empty pb request is serialized to json and set to the body of the http/h2 request. The Controller.request_attachment() must be empty otherwise the RPC fails.
Non-empty pb response is converted from a json which is parsed from the body of the http/h2 response.
http/1.x behaves in this way by default, so "http" and "http:json" are just same.
# http:proto, h2:proto
Non-empty pb request is serialized (in pb's wire format) and set to the body of the http/h2 request. The Controller.request_attachment() must be empty otherwise the RPC fails.
Non-empty pb response is parsed from the body of the http/h2 response(in pb's wire format).
http/2 behaves in this way by default, so "h2" and "h2:proto" are just same.
# h2:grpc
Default protocol of [gRPC](https://github.com/grpc). The detailed format is described in [gRPC over HTTP2](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md).
Clients using brpc should be able to talk with gRPC after changing ChannelOptions.protocol to "h2:grpc".
Servers using brpc should be accessible by gRPC clients automatically without changing the code.
gRPC serializes message into pb wire format by default, so "h2:grpc" and "h2:grpc+proto" are just same.
TODO: Other configurations for gRPC
# h2:grpc+json
Comparing to h2:grpc, this protocol serializes messages into json instead of pb, which may not be supported by gRPC directly. For example, grpc-go may reference [here](https://github.com/johanbrandhorst/grpc-json-example/blob/master/codec/json.go) to register the corresponding codec and turn on the support.
[中文版](../cn/http_service.md)
This document talks about ordinary HTTP services rather than protobuf services accessible via HTTP. HTTP services in brpc have to declare interfaces with empty request and response in a .proto file. This requirement keeps all service declarations inside proto files rather than scattering in code, configurations, and proto files. Check [http_server.cpp](https://github.com/brpc/brpc/blob/master/example/http_c++/http_server.cpp) for an example.
This document talks about ordinary htt/h2 services rather than protobuf services accessible via http/h2.
http/h2 services in brpc have to declare interfaces with empty request and response in a .proto file. This requirement keeps all service declarations inside proto files rather than scattering in code, configurations, and proto files.
# Example
[http_server.cpp](https://github.com/brpc/brpc/blob/master/example/http_c++/http_server.cpp)
# About h2
brpc names the HTTP/2 protocol to "h2", no matter encrypted or not. However HTTP/2 connections without SSL are shown on /connections with the official name "h2c", and the ones with SSL are shown as "h2".
The APIs for http and h2 in brpc are basically same. Without explicit statement, mentioned http features work for h2 as well.
# URL types
## /ServiceName/MethodName as the prefix
Define a service named `ServiceName`(not including the package name), with a method named `MethodName` and empty request/response, the service will provide http service on `/ServiceName/MethodName` by default.
Define a service named `ServiceName`(not including the package name), with a method named `MethodName` and empty request/response, the service will provide http/h2 service on `/ServiceName/MethodName` by default.
The reason that request and response can be empty is that the HTTP data is in Controller:
The reason that request and response can be empty is that all data are in Controller:
- Header of the http request is in Controller.http_request() and the body is in Controller.request_attachment().
- Header of the http response is in Controller.http_response() and the body is in Controller.response_attachment().
- Header of the http/h2 request is in Controller.http_request() and the body is in Controller.request_attachment().
- Header of the http/h2 response is in Controller.http_response() and the body is in Controller.response_attachment().
Implementation steps:
......@@ -69,7 +80,7 @@ public:
## /ServiceName as the prefix
HTTP services to manage resources may need this kind of URL, such as `/FileService/foobar.txt` represents `./foobar.txt` and `/FileService/app/data/boot.cfg` represents `./app/data/boot.cfg`.
http/h2 services for managing resources may need this kind of URL, such as `/FileService/foobar.txt` represents `./foobar.txt` and `/FileService/app/data/boot.cfg` represents `./app/data/boot.cfg`.
Implementation steps:
......@@ -121,13 +132,13 @@ brpc supports specifying a URL for each method in a service. The API is as follo
// If `restful_mappings' is non-empty, the method in service can
// be accessed by the specified URL rather than /ServiceName/MethodName.
// Mapping rules: "PATH1 => NAME1, PATH2 => NAME2 ..."
// where `PATH' is a valid HTTP path and `NAME' is the method name.
// where `PATH' is a valid path and `NAME' is the method name.
int AddService(google::protobuf::Service* service,
ServiceOwnership ownership,
butil::StringPiece restful_mappings);
```
`QueueService` defined below contains several HTTP methods. If the service is added into the server normally, it's accessible via URLs like `/QueueService/start` and ` /QueueService/stop`.
`QueueService` defined below contains several methods. If the service is added into the server normally, it's accessible via URLs like `/QueueService/start` and ` /QueueService/stop`.
```protobuf
service QueueService {
......@@ -165,7 +176,7 @@ There are 3 mappings separated by comma in the 3rd parameter (which is a string
More about mapping rules:
- Multiple paths can be mapped to a same method.
- Both HTTP and protobuf services are supported.
- Both http/h2 and protobuf services are supported.
- Un-mapped methods are still accessible via `/ServiceName/MethodName`. Mapped methods are **not** accessible via `/ServiceName/MethodName` anymore.
- `==>` and ` ===>` are both OK, namely extra spaces at the beginning or the end, extra slashes, extra commas at the end, are all accepted.
- Pattern `PATH` and `PATH/*` can coexist.
......
......@@ -38,13 +38,13 @@ An industrial-grade RPC framework used throughout [Baidu](http://ir.baidu.com/ph
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/h2c (compatible with [grpc](https://github.com/grpc/grpc), will be opensourced). using http in brpc is much more friendly than [libcurl](https://curl.haxx.se/libcurl/).
* 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).
* 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.
* all sorts of protocols used in Baidu: [baidu_std](../cn/baidu_std.md), [streaming_rpc](streaming_rpc.md), hulu_pbrpc, [sofa_pbrpc](https://github.com/baidu/sofa-pbrpc), nova_pbrpc, public_pbrpc, ubrpc, and nshead-based ones.
* Access protobuf-based protocols with HTTP+json, probably from another language.
* Build [HA](https://en.wikipedia.org/wiki/High_availability) distributed services using an industrial-grade implementation of [RAFT consensus algorithm](https://raft.github.io) which is opensourced at [braft](https://github.com/brpc/braft)
* Servers can handle requests [synchronously](server.md) or [asynchronously](server.md#asynchronous-service).
* Clients can access servers [synchronously](client.md#synchronus-call), [asynchronously](client.md#asynchronous-call), [semi-synchronously](client.md#semi-synchronous-call), or use [combo channels](combo_channel.md) to simplify sharded or parallel accesses declaratively.
......
......@@ -251,9 +251,12 @@ server.RunUntilAskedToQuit();
Services can be added or removed after Join() returns and server can be Start() again.
# Accessed by HTTP client
# Accessed by http/h2
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/).
Services using protobuf can be accessed via http+json generally. The json string stored in http 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/).
```shell
# -H 'Content-Type: application/json' is optional
......@@ -261,7 +264,7 @@ $ curl -d '{"message":"hello"}' http://brpc.baidu.com:8765/EchoService/Echo
{"message":"hello"}
```
Note: Set `Content-Type: application/proto` to access services with http + protobuf-serialized-data, which performs better at serialization.
Note: Set `Content-Type: application/proto` to access services with http/h2 + protobuf-serialized-data, which performs better at serialization.
## json<=>pb
......@@ -271,7 +274,7 @@ When -pb_enum_as_number is turned on, enums in pb are converted to values instea
## Adapt old clients
Early-version brpc allows pb service being accessed via http without setting the pb request, even if there're required fields in. This kind of service often parses http requests and sets http responses by itself, and does not touch the pb request. However this behavior is still very dangerous: a service with an undefined request.
Early-version brpc allows pb service being accessed via http without filling the pb request, even if there're required fields. This kind of service often parses http requests and sets http responses by itself, and does not touch the pb request. However this behavior is still very dangerous: a service with an undefined request.
This kind of services may meet issues after upgrading to latest brpc, which already deprecated the behavior for a long time. To help these services to upgrade, brpc allows bypassing the conversion from http body to pb request (so that users can parse http requests differently), the setting is as follows:
......@@ -279,13 +282,13 @@ This kind of services may meet issues after upgrading to latest brpc, which alre
brpc::ServiceOptions svc_opt;
svc_opt.ownership = ...;
svc_opt.restful_mappings = ...;
svc_opt.allow_http_body_to_pb = false; // turn off conversion from http body to pb request
svc_opt.allow_http_body_to_pb = false; // turn off conversion from http/h2 body to pb request
server.AddService(service, svc_opt);
```
After the setting, service does not convert http body to pb request after receiving http request, which also makes the pb request undefined. Users have to parse the http body by themselves when `cntl->request_protocol() == brpc::PROTOCOL_HTTP` is true which indicates the request is from http.
After the setting, service does not convert the body to pb request after receiving http/h2 request, which also makes the pb request undefined. Users have to parse the body by themselves when `cntl->request_protocol() == brpc::PROTOCOL_HTTP || cntl->request_protocol() == brpc::PROTOCOL_H2` is true which indicates the request is from http/h2.
As a correspondence, if cntl->response_attachment() is not empty and pb response is set as well, brpc does not report the ambiguous anymore, instead cntl->response_attachment() will be used as body of the http response. This behavior is unaffected by setting allow_http_body_to_pb or not. If the relaxation results in more users' errors, we may restrict it in future.
As a correspondence, if cntl->response_attachment() is not empty and pb response is set as well, brpc does not report the ambiguous anymore, instead cntl->response_attachment() will be used as body of the http/h2 response. This behavior is unaffected by setting allow_http_body_to_pb or not. If the relaxation results in more users' errors, we may restrict it in future.
# Protocols
......@@ -295,7 +298,9 @@ Server detects supported protocols automatically, without assignment from users.
- [Streaming RPC](streaming_rpc.md), shown as "streaming_rpc", enabled by default.
- http 1.0/1.1, shown as "http", enabled by default.
- http/1.0 and http/1.1, shown as "http", enabled by default.
- http/2 and gRPC, shown as "h2c"(unencrypted) or "h2"(encrypted), enabled by default.
- Protocol of RTMP, shown as "rtmp", enabled by default.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment