Unverified Commit a078785d authored by Ge Jun's avatar Ge Jun Committed by GitHub

Merge pull request #324 from kenshinxf/kenshinxf

Add thrift protocol documents
parents bdb163ec eea2303d
...@@ -17,7 +17,7 @@ before_script: ...@@ -17,7 +17,7 @@ before_script:
before_install: before_install:
- wget --no-clobber https://github.com/bazelbuild/bazel/releases/download/0.8.1/bazel_0.8.1-linux-x86_64.deb - wget --no-clobber https://github.com/bazelbuild/bazel/releases/download/0.8.1/bazel_0.8.1-linux-x86_64.deb
- sudo dpkg -i bazel_0.8.1-linux-x86_64.deb - sudo dpkg -i bazel_0.8.1-linux-x86_64.deb
- wget http://www.us.apache.org/dist/thrift/0.9.3/thrift-0.9.3.tar.gz && tar -xf thrift-0.9.3.tar.gz && cd thrift-0.9.3/ && ./configure --prefix=/usr --with-ruby=no --with-python=no --with-java=no --with-go=no --with-perl=no --with-php=no --with-csharp=no --with-erlang=no --with-lua=no --with-nodejs=no && make -j 3 -s && sudo make install && cd - - wget http://www.us.apache.org/dist/thrift/0.11.0/thrift-0.11.0.tar.gz && tar -xf thrift-0.11.0.tar.gz && cd thrift-0.11.0/ && ./configure --prefix=/usr --with-ruby=no --with-python=no --with-java=no --with-go=no --with-perl=no --with-php=no --with-csharp=no --with-erlang=no --with-lua=no --with-nodejs=no && make CPPFLAGS=-DFORCE_BOOST_SMART_PTR -j 3 -s && sudo make install && cd -
install: install:
- sudo apt-get install -qq realpath libgflags-dev libprotobuf-dev libprotoc-dev protobuf-compiler libleveldb-dev libgoogle-perftools-dev libboost-dev libssl-dev libevent-dev libboost-test-dev - sudo apt-get install -qq realpath libgflags-dev libprotobuf-dev libprotoc-dev protobuf-compiler libleveldb-dev libgoogle-perftools-dev libboost-dev libssl-dev libevent-dev libboost-test-dev
......
...@@ -9,11 +9,12 @@ A industrial-grade RPC framework used throughout [Baidu](http://ir.baidu.com/pho ...@@ -9,11 +9,12 @@ A industrial-grade RPC framework used throughout [Baidu](http://ir.baidu.com/pho
You can use it to: You can use it to:
* Build a server that can talk in multiple protocols (**on same port**), or access all sorts of services * 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/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/).
* [redis](docs/en/redis_client.md) and [memcached](docs/en/memcache_client.md), thread-safe, more friendly and performant than the official clients * [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 [live-streaming services](docs/cn/live_streaming.md). * [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 [live-streaming services](docs/cn/live_streaming.md).
* hadoop_rpc (may be opensourced) * hadoop_rpc (may be opensourced)
* [rdma](https://en.wikipedia.org/wiki/Remote_direct_memory_access) support (will be opensourced) * [rdma](https://en.wikipedia.org/wiki/Remote_direct_memory_access) support (will be opensourced)
* 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. * [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. * 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) * 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). * Servers can handle requests [synchronously](docs/en/server.md) or [asynchronously](docs/en/server.md#asynchronous-service).
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
* [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), 可用于搭建[直播服务](docs/cn/live_streaming.md). * [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), 可用于搭建[直播服务](docs/cn/live_streaming.md).
* hadoop_rpc(可能开源) * hadoop_rpc(可能开源)
* 支持[rdma](https://en.wikipedia.org/wiki/Remote_direct_memory_access)(即将开源) * 支持[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的各种协议. * 各种百度内使用的协议: [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的协议. * 从其他语言通过HTTP+json访问基于protobuf的协议.
* 基于工业级的[RAFT算法](https://raft.github.io)实现搭建[高可用](https://en.wikipedia.org/wiki/High_availability)分布式系统,已在[braft](https://github.com/brpc/braft)开源。 * 基于工业级的[RAFT算法](https://raft.github.io)实现搭建[高可用](https://en.wikipedia.org/wiki/High_availability)分布式系统,已在[braft](https://github.com/brpc/braft)开源。
......
...@@ -543,6 +543,7 @@ Channel的默认协议是baidu_std,可通过设置ChannelOptions.protocol换 ...@@ -543,6 +543,7 @@ Channel的默认协议是baidu_std,可通过设置ChannelOptions.protocol换
- PROTOCOL_REDIS 或 "redis",redis 1.2后的协议(也是hiredis支持的协议),默认为单连接。具体方法见[访问Redis](redis_client.md) - PROTOCOL_REDIS 或 "redis",redis 1.2后的协议(也是hiredis支持的协议),默认为单连接。具体方法见[访问Redis](redis_client.md)
- PROTOCOL_NSHEAD_MCPACK 或 "nshead_mcpack", 顾名思义,格式为nshead + mcpack,使用mcpack2pb适配,默认为连接池。 - PROTOCOL_NSHEAD_MCPACK 或 "nshead_mcpack", 顾名思义,格式为nshead + mcpack,使用mcpack2pb适配,默认为连接池。
- PROTOCOL_ESP 或 "esp",访问使用esp协议的服务,默认为连接池。 - PROTOCOL_ESP 或 "esp",访问使用esp协议的服务,默认为连接池。
- PROTOCOL_THRIFT 或 "thrift",访问使用thrift协议的服务,默认为连接池, 具体方法见[访问thrift](thrift.md)
## 连接方式 ## 连接方式
......
[English Version](../en/thrift.md)
[thrift](https://thrift.apache.org/)是近几年应用较广的Facebook发布的RPC服务, 为了使用户更方便,快捷的利用bthread的并发能力,brpc实现并支持thrift工作在NonBlocking模式下的协议(FramedProtocol), 注意本文中所说的thrift协议一律指的是此种情况下的thrift协议.
示例程序:[example/thrift_extension_c++](https://github.com/brpc/brpc/tree/master/example/thrift_extension_c++/)
相比使用官方原生的优势有:
- 线程安全。用户不需要为每个线程建立独立的client.
- 支持同步、异步、批量同步、批量异步等访问方式,能使用ParallelChannel等组合访问方式.
- 支持多种连接方式(连接池, 短连接), 支持超时、backup request、取消、tracing、内置服务等一系列RPC基本福利.
# 编译依赖及运行
默认brpc编译是不启用thrift协议支持的, 目的是在用户不需要thrift协议支持的情况下可以不安装thrift依赖. 如果用户启用thrift协议的话, 在配置brpc环境的时候加上--with-thrift参数.
安装thrift依赖, ubuntu环境下
```bash
从[官网](https://thrift.apache.org/download)下载thrift源代码
wget http://www.us.apache.org/dist/thrift/0.11.0/thrift-0.11.0.tar.gz
tar -xf thrift-0.11.0.tar.gz
cd thrift-0.11.0/
./configure --prefix=/usr --with-ruby=no --with-python=no --with-java=no --with-go=no --with-perl=no --with-php=no --with-csharp=no --with-erlang=no --with-lua=no --with-nodejs=no
make CPPFLAGS=-DFORCE_BOOST_SMART_PTR -j 3 -s
sudo make install
```
Debian请参考[官方wiki]](https://thrift.apache.org/docs/install/debian)
配置brpc支持thrift协议
```bash
sh config_brpc.sh --headers=/usr/include --libs=/usr/lib --nodebugsymbols --with-thrift
```
编译完成后会生成libbrpc.a, thrift扩展协议以静态库的方式提供给用户, 用户在需要启用thrift协议的时候链接即可.
# Thrift 原生消息定义, echo.thrift:
```c++
namespace cpp example
struct EchoRequest {
1: required string data;
2: required i32 s;
}
struct EchoResponse {
1: required string data;
}
service EchoService {
EchoResponse Echo(1:EchoRequest request);
}
```
# Client端访问下游thrift server
创建一个访问thrift server的Channel:
```c++
#include <brpc/channel.h>
#include <brpc/details/thrift_utils.h>
#include <brpc/thrift_message.h>
...
DEFINE_string(server, "0.0.0.0:8019", "IP Address of thrift server");
DEFINE_string(load_balancer, "", "The algorithm for load balancing");
...
brpc::ChannelOptions options;
options.protocol = brpc::PROTOCOL_THRIFT;
brpc::Channel thrift_channel;
if (thrift_channel.Init(Flags_server.c_str(), FLAGS_load_balancer.c_str(), &options) != 0) {
LOG(ERROR) << "Fail to initialize thrift channel";
return -1;
}
...
```
构造thrift请求, 并发送, ThriftMessage是模板类, 里面托管了thrift原生消息, 通过raw()方法可以可以直接操作原生thrift消息
```c++
// wrapper thrift raw request into ThriftMessage
// example::[EchoRequest/EchoResponse]是thrfit原生定义的消息(通过thrift代码生成工具生成)
brpc::ThriftMessage<example::EchoRequest> req;
brpc::ThriftMessage<example::EchoResponse> res;
req.raw().data = "hello";
cntl.set_thrift_method_name("Echo");
channel.CallMethod(NULL, &cntl, &req, &res, NULL);
if (cntl.Failed()) {
LOG(ERROR) << "Fail to send thrift request, " << cntl.ErrorText();
return -1;
}
```
# Server端处理上游thrfit请求
类似原生brpc协议, 用户需要实现自己的thrift handler, 继承自brpc::ThriftService
由于thrift协议本身的限制, 在服务端只能获取到method name(通过controller.thrift_method_name()方法), 无法获取到service name, 这和原生的thrift实现是一致的, 也就意味着在一个brpc server中只能有一个thrift service
```c++
// Implement User Thrift Service handler
class MyThriftProtocolPbManner : public brpc::ThriftService {
public:
void ProcessThriftFramedRequest(const brpc::Server&,
brpc::Controller* cntl,
brpc::ThriftMessage* request,
brpc::ThriftMessage* response,
brpc::ThriftClosure* done) {
// This object helps you to call done->Run() in RAII style. If you need
// to process the request asynchronously, pass done_guard.release().
brpc::ClosureGuard done_guard(done);
if (cntl->Failed()) {
// NOTE: You can send back a response containing error information
// back to client instead of closing the connection.
cntl->CloseConnection("Close connection due to previous error");
return;
}
example::EchoRequest* req = request->Cast<example::EchoRequest>();
example::EchoResponse* res = response->Cast<example::EchoResponse>();
// process with req and res
res->data = req->data + "user data";
LOG(INFO) << "success to process thrift request in brpc with pb manner";
}
};
```
注册thrift service并启动服务
```c++
brpc::Server server;
brpc::ServerOptions options;
options.thrift_service = new MyThriftProtocolPbManner;
options.idle_timeout_sec = FLAGS_idle_timeout_s;
options.max_concurrency = FLAGS_max_concurrency;
// Start the server.
if (server.Start(FLAGS_port, &options) != 0) {
LOG(ERROR) << "Fail to start EchoServer";
return -1;
}
```
\ No newline at end of file
[中文版](../cn/thrift.md)
[thrift](https://thrift.apache.org/)is a RPC framework used widely in production environment which was developed by Facebook. In order to access thrift servers more conveniently and make full use of concurrency ability of bthread, brpc directly supports the thrift protocol.
Check [example/thrift_extension_c++](https://github.com/brpc/brpc/tree/master/example/thrift_extension_c++/) for an example.
Advantages compared to the official thrift client:
- Thread safety. No need to set up separate clients for each thread.
- Supports synchronous, asynchronous, batch synchronous, batch asynchronous, and other access methods. Combination channels such as ParallelChannel are also supported.
- Support various connection types(short, connection pool). Support timeout, backup request, cancellation, tracing, built-in services, and other benefits offered by brpc.
# Compile and Run
In order to not depend on and compile with thrift library for most users, the thrift protocol wasn't supported in brpc by default. Configure brpc with --with-thrift if you want to enable thrift protocol in brpc.
Install Thrift in Ubuntu
```bash
Download thrift source code from offical [web site](https://thrift.apache.org/download)
wget http://www.us.apache.org/dist/thrift/0.11.0/thrift-0.11.0.tar.gz
tar -xf thrift-0.11.0.tar.gz
cd thrift-0.11.0/
./configure --prefix=/usr --with-ruby=no --with-python=no --with-java=no --with-go=no --with-perl=no --with-php=no --with-csharp=no --with-erlang=no --with-lua=no --with-nodejs=no
make CPPFLAGS=-DFORCE_BOOST_SMART_PTR -j 3 -s
sudo make install
```
Debian please refer [offical wiki]](https://thrift.apache.org/docs/install/debian)
Configure with thrift support
```bash
sh config_brpc.sh --headers=/usr/include --libs=/usr/lib --nodebugsymbols --with-thrift
```
Thrift extension was supported via static library, libbrpc.a was generated after compile, link with it if users want to enable thrift protocol.
# Thrift message definition, echo.thrift:
```c++
namespace cpp example
struct EchoRequest {
1: required string data;
2: required i32 s;
}
struct EchoResponse {
1: required string data;
}
service EchoService {
EchoResponse Echo(1:EchoRequest request);
}
```
# Client asscess thrift server
create a Channel to access thrift server:
```c++
#include <brpc/channel.h>
#include <brpc/details/thrift_utils.h>
#include <brpc/thrift_message.h>
...
DEFINE_string(server, "0.0.0.0:8019", "IP Address of thrift server");
DEFINE_string(load_balancer, "", "The algorithm for load balancing");
...
brpc::ChannelOptions options;
options.protocol = brpc::PROTOCOL_THRIFT;
brpc::Channel thrift_channel;
if (thrift_channel.Init(Flags_server.c_str(), FLAGS_load_balancer.c_str(), &options) != 0) {
LOG(ERROR) << "Fail to initialize thrift channel";
return -1;
}
...
```
Construct a thrift request and send it to server, ThriftMessage is a template class that hosts thrift navtive messages, raw() methods can directly manipulate native thrift messages.
```c++
// wrapper thrift raw request into ThriftMessage
// example::[EchoRequest/EchoResponse]is thrift native message generated by thrift toolkits
brpc::ThriftMessage<example::EchoRequest> req;
brpc::ThriftMessage<example::EchoResponse> res;
req.raw().data = "hello";
cntl.set_thrift_method_name("Echo");
channel.CallMethod(NULL, &cntl, &req, &res, NULL);
if (cntl.Failed()) {
LOG(ERROR) << "Fail to send thrift request, " << cntl.ErrorText();
return -1;
}
```
# Server side processing upstream thrift requests
Users need to implement their own thrift handler which was inherited from brpc::ThriftService.
Due to the limitation of thrift protocol itself, only the method name can be obtained on the server (via the controller.thrift_method_name() method), and the service name cannot be obtained. This is consistent with the native thrift implementation, which means that there can only be one thrift service in one brpc server.
```c++
// Implement User Thrift Service handler
class MyThriftProtocolPbManner : public brpc::ThriftService {
public:
void ProcessThriftFramedRequest(const brpc::Server&,
brpc::Controller* cntl,
brpc::ThriftMessage* request,
brpc::ThriftMessage* response,
brpc::ThriftClosure* done) {
// This object helps you to call done->Run() in RAII style. If you need
// to process the request asynchronously, pass done_guard.release().
brpc::ClosureGuard done_guard(done);
if (cntl->Failed()) {
// NOTE: You can send back a response containing error information
// back to client instead of closing the connection.
cntl->CloseConnection("Close connection due to previous error");
return;
}
example::EchoRequest* req = request->Cast<example::EchoRequest>();
example::EchoResponse* res = response->Cast<example::EchoResponse>();
// process with req and res
res->data = req->data + "user data";
LOG(INFO) << "success to process thrift request in brpc with pb manner";
}
};
```
Register thrift service and start brpc server
```c++
brpc::Server server;
brpc::ServerOptions options;
options.thrift_service = new MyThriftProtocolPbManner;
options.idle_timeout_sec = FLAGS_idle_timeout_s;
options.max_concurrency = FLAGS_max_concurrency;
// Start the server.
if (server.Start(FLAGS_port, &options) != 0) {
LOG(ERROR) << "Fail to start EchoServer";
return -1;
}
```
\ No newline at end of file
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <butil/logging.h> #include <butil/logging.h>
#include "gen-cpp/EchoService.h" #include "gen-cpp/EchoService.h"
#include <thrift/protocol/TBinaryProtocol.h> #include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h> #include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h> #include <thrift/transport/TServerSocket.h>
...@@ -27,9 +28,11 @@ ...@@ -27,9 +28,11 @@
#include <thrift/concurrency/PosixThreadFactory.h> #include <thrift/concurrency/PosixThreadFactory.h>
// _THRIFT_STDCXX_H_ is defined by thrift/stdcxx.h which was added since thrift 0.11.0 // _THRIFT_STDCXX_H_ is defined by thrift/stdcxx.h which was added since thrift 0.11.0
#include <thrift/TProcessor.h> // to include stdcxx.h if present
#ifndef THRIFT_STDCXX #ifndef THRIFT_STDCXX
#if defined(_THRIFT_STDCXX_H_) #if defined(_THRIFT_STDCXX_H_)
# define THRIFT_STDCXX apache::thrift::stdcxx # define THRIFT_STDCXX apache::thrift::stdcxx
#include <thrift/transport/TNonblockingServerSocket.h>
#else #else
# define THRIFT_STDCXX boost # define THRIFT_STDCXX boost
#endif #endif
...@@ -67,14 +70,23 @@ int main(int argc, char *argv[]) { ...@@ -67,14 +70,23 @@ int main(int argc, char *argv[]) {
new apache::thrift::transport::TBufferedTransportFactory()); new apache::thrift::transport::TBufferedTransportFactory());
THRIFT_STDCXX::shared_ptr<apache::thrift::concurrency::ThreadManager> thread_mgr( THRIFT_STDCXX::shared_ptr<apache::thrift::concurrency::ThreadManager> thread_mgr(
apache::thrift::concurrency::ThreadManager::newSimpleThreadManager(2)); apache::thrift::concurrency::ThreadManager::newSimpleThreadManager(2));
thread_mgr->threadFactory(thread_factory); thread_mgr->threadFactory(thread_factory);
thread_mgr->start(); thread_mgr->start();
#if defined(_THRIFT_STDCXX_H_)
THRIFT_STDCXX::shared_ptr<apache::thrift::transport::TNonblockingServerSocket> server_transport =
THRIFT_STDCXX::make_shared<apache::thrift::transport::TNonblockingServerSocket>(FLAGS_port);
apache::thrift::server::TNonblockingServer server(processor, apache::thrift::server::TNonblockingServer server(processor,
transport_factory, transport_factory, protocol_factory, transport_factory, transport_factory, protocol_factory,
protocol_factory, FLAGS_port, thread_mgr); protocol_factory, server_transport);
#else
apache::thrift::server::TNonblockingServer server(processor,
transport_factory, transport_factory, protocol_factory,
protocol_factory, FLAGS_port);
#endif
server.serve(); server.serve();
return 0; return 0;
} }
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#else #else
# include <boost/make_shared.hpp> # include <boost/make_shared.hpp>
# define THRIFT_STDCXX boost # define THRIFT_STDCXX boost
#include <boost/make_shared.hpp>
#endif #endif
#endif #endif
......
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