baidu / sofa-pbrpc Goto Github PK
View Code? Open in Web Editor NEWA light-weight RPC implement of google protobuf RPC framework.
License: Other
A light-weight RPC implement of google protobuf RPC framework.
License: Other
线程初始化回调函数不存入任何参数(ExtClosure<bool()>* work_thread_init_func; )求问线程数据如何attach上去呢?
Hi folks,
This is really good work and I'd like to try it out. While looks like it doesn't compile on 32 bit platform, it failed with following error:
src/sofa/pbrpc/atomic.h: Assembler messages:
src/sofa/pbrpc/atomic.h:59: Error: invalid instruction suffix for `xadd'
make: *** [src/sofa/pbrpc/dynamic_rpc_channel_impl.o] Error 1
After adding -m64 flag to the Makefile, and installing 64 bit gcc library, it compiles but failed to link because there is no 64 bit protobuf library.
I could try it on a 64 bit platform, but just to want to check if 32 bit is supported or not. Thank you!
Regards
Xiangning
问题描述:目前keep_alive_time功能实现依赖于stream的最后读写操作时间(last_rw_time),如果now - last_rw_time > keep_alive_time,则认为连接的空闲时间超过阈值,就会主动关闭stream。但是这样可能**产生误杀**:如果一个连接上正在处理一个请求,而这个请求的处理时间很长(大于keep_alive_time),并且在等待处理完成的这段时间中stream上没有发生读写,则stream也会被提前关闭,造成请求处理完成后无法response,这是不合理的。
解决办法:对RpcClientStream和RpcServerStream各自维护pending_process_count值,如果pending_process_count > 0,则stream不能被关闭。
CXXFLAGS ?= -DSOFA_PBRPC_ENABLE_DETAILED_LOGGING
导致mac版编译失败
sofa::pbrpc::RpcServerMessageStream<>::try_start_send()
{
...
// now send
_sent_size = 0;
bool ret = _sending_message->Next(
reinterpret_cast<const void**>(&_sending_data), &_sending_size);
SCHECK(ret);
async_write_some(_sending_data, _sending_size);
started = true;
break;
...
}
上面的try_start_send
函数调用应该循环多次调用Next
,否则可能会造成_sending_message
中的数据未发送完成。
sofa::pbrpc::RpcMessageStream<>
也有同样的问题
for custom installed protobuf, --proto_path should be assigned
PROTO_INCLUDE=${PROTOBUF_DIR}/include
g++ -O2 -pipe -W -Wall -fPIC -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -DHAVE_SNAPPY -Isrc -I/usr/local/include -I/usr/local/include -I/usr/local/include -I/include -c -o src/sofa/pbrpc/builtin_service.pb.o src/sofa/pbrpc/builtin_service.pb.cc
src/sofa/pbrpc/builtin_service.pb.cc: 在函数‘void sofa::pbrpc::builtin::protobuf_AddDesc_builtin_5fservice_2eproto()’中:
src/sofa/pbrpc/builtin_service.pb.cc:413:3: 错误: ‘protobuf_AddDesc_sofa_2fpbrpc_2frpc_5foption_2eproto’不是‘sofa::pbrpc’的成员
make: *** [src/sofa/pbrpc/builtin_service.pb.o] 错误 1
【我的环境:ubuntu12.04 gcc4.6.3 pb2.5】
在rpc的应用场景中,用户需要传输非protobuf协议封装的数据,数据的格式和操作由用户定义,这些数据最终都以字节流的方式在client和server之间传输。需要在sofa-pbrpc内部实现一套attachment机制,支持用户自定义附加数据的格式和操作,用户在client端设置附加数据,server端接受并进行操作。基于该机制为用户提供默认的Cookie插件,用于存储和传输logid等client端的状态信息。
实现sofa-pbrpc attachment机制,支持用户附加数据,附加数据的定义和操作在用户层实现。并基于此机制实现cookie插件
Attachment基类:
class RpcAttachment
{
public:
virtual ~RpcAttachment() { }
virtual bool Serialize(ReadBufferPtr attactment_buffer) = 0;
virtual bool Deserialize (ReadBufferPtr attachment_buffer) = 0;
};
RpcController增加接口:
RpcAttachmentPtr_request_attachment; //RPC请求的附加数据buffer
RpcAttachmentPtr _response_attachment; //RPC应答的附加数据buffer
ReadBufferPtr _request_attach_buffer; //RPC请求的附加数据buffer
ReadBufferPtr _response_attach_buffer; //RPC应答的附加数据buffer
//用户接口
//设置请求的附加数据
void SetRequestAttachment(RpcAttachment* request_attachment);
//获取请求的附加数据
void GetRequestAttachment(RpcAttachment* request_attachment);
//设置应答的附加数据
void SetResponseAttachment(RpcAttachment* response_attachment);
//获取应答的附加数据
void GetResponseAttachment(RpcAttachment* response_attachment);
//Rpc内部接口
//设置request_attachment_buffer
void SetRequestAttachmentBuffer(const ReadBufferPtr& attachment_buffer);
//获取request_attachment_buffer
const ReadBufferPtr& GetRequestBuffer() const;
//设置response_attachment_buffer
void SetResponseAttachmentBuffer(const ReadBufferPtr& attachment_buffer);
////获取response_attachment_buffer
const ReadBufferPtr& GetResponseBuffer() const;
Cookie插件:
Class RpcCookie : public sofa::pbrpc:: RpcAttachment
{
virtual bool Serialize(ReadBufferPtr& attactment_buffer) ;
virtual bool Deserialize (const ReadBufferPtr& attachment_buffer);
void Get(const std::string key, std::string& value);
void Set(const std::string& key, const std::string value);
void Erase(const std::string& key);
void Clear();
}
Client端示例:
sofa::pbrpc::RpcController* cntl = new sofa::pbrpc::RpcController();
cntl->SetTimeout(3000);
CookiePtr cookie(new Cookie());
cookie->set("type", "sync");
cntl->SetRequestAttachment(cookie.get());
sofa::pbrpc::test::EchoRequest* request = new sofa::pbrpc::test::EchoRequest();
request->set_message("Hello from client");
sofa::pbrpc::test::EchoResponse* response = new sofa::pbrpc::test::EchoResponse();
sofa::pbrpc::test::EchoServer_Stub* stub =new sofa::pbrpc::test::EchoServer_Stub(&rpc_channel);
stub->Echo(cntl, request, response, NULL);
if (cntl->Failed())
{
SLOG(ERROR, "request failed: %s", cntl->ErrorText().c_str());
}
else
{
cookie.reset(new Cookie());
cntl->GetResponseAttachment(cookie.get());
std::string version;
cookie->Get(“version”, version);
SLOG(NOTICE, "request succeed: %s, version: %s", response->message().c_str(), version.c_str());
}
Server端示例:
virtual void Echo(google::protobuf::RpcController* controller,
const sofa::pbrpc::test::EchoRequest* request,
sofa::pbrpc::test::EchoResponse* response,
google::protobuf::Closure* done)
{
sofa::pbrpc::RpcController* cntl = static_cast<sofa::pbrpc::RpcController*>(controller);
SLOG(INFO, "Echo(): request message from %s: %s",
cntl->RemoteAddress().c_str(), request->message().c_str());
CookiePtr cookie(new Cookie());
cntl->GetRequestAttachment(cookie.get());
cookie->Set(“version”, “1.00”);
cntl->SetResponseAttachment(cookie.get());
response->set_message("echo message: " + request->message());
done->Run();
}
before making a new release, we should change the SOFA_PBRPC_VERSION macro in file "src/sofa/pbrpc/common.h" to proper value, to make it consistent.
栈状态
#0 0x00007f1834e7b22d in pthread_join () from /lib64/libpthread.so.0
#1 0x00000000006215ab in sofa::pbrpc::ThreadGroupImpl::stop (this=0x228f6b0) at src/sofa/pbrpc/thread_group_impl.h:182
#2 0x00000000006176c7 in sofa::pbrpc::RpcClientImpl::Stop (this=0x22be000) at src/sofa/pbrpc/rpc_client_impl.cc:109
查看io_service的内存信息如下
(gdb) p *(boost::asio::detail::task_io_service * const) 0x22738e0
$26 = {boost::asio::detail::service_baseboost::asio::detail::task_io_service = {boost::asio::io_service::service = {boost::noncopyable_::noncopyable = {},
vptr.service = 0xa24a90 <vtable for boost::asio::detail::task_io_service+16>, key = {type_info_ = 0xa245a0 <typeinfo for boost::asio::detail::typeid_wrapperboost::asio::detail::task_io_service>,
id_ = 0x0}, owner_ = @0x228f6d0, next_ = 0x0}, static id = {boost::asio::io_service::id = {boost::noncopyable_::noncopyable = {}, }, }},
one_thread_ = false, mutex_ = {boost::noncopyable_::noncopyable = {}, mutex_ = {__data = {__lock = 0, __count = 0, __owner = 0, _nusers = 7, kind = 0, spins = 0, list = {
prev = 0x0, next = 0x0}}, size = '\000' <repeats 12 times>, "\a", '\000' <repeats 26 times>, align = 0}}, task = 0x2266e10,
task_operation = {boost::asio::detail::task_io_service_operation = {next = 0x0, func = 0x0, task_result = 0}, }, task_interrupted = false, outstanding_work = {value = 3},
op_queue = {boost::noncopyable::noncopyable = {}, front = 0x0, back = 0x0}, stopped = false, shutdown = false, first_idle_thread = 0x7f182991fce0}
我理解调用后stop函数后task_io_service 的 outstanding_work_变量会被减为0 并退出他的run函数。
从而使得pthread_join函数成功返回。可能的问题点在哪里呢?
非常期待java支持。
client的发送速率受限于boost::socket的发送速率(async_write_some ~ on_write_some间的延迟),当发送较大的数据包时,如果数据跨越多个bufhandle,发送速率会成比例下降。可通过提高bufhandle的大小,降低buf数来提高大包发送速率。
请问支持windows环境吗?
sofa-pbrpc,编译对g++的版本,有什么要求呢?我用g++ 4.8.2编译失败了,protubuf,用的是proto 3.0版本
g++ -O2 -pipe -W -Wall -fPIC -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -DHAVE_SNAPPY -Isrc -I/usr/include -I/home/kentpeng/sofa-pbrpc/thirty/protobuf/include -I/home/kentpeng/sofa-pbrpc/thirty/snappy/include -I/home/kentpeng/sofa-pbrpc/thirty/zlib/include -c -o src/sofa/pbrpc/boost_system_error_code.o src/sofa/pbrpc/boost_system_error_code.cc
src/sofa/pbrpc/boost_system_error_code.cc:440:1: internal compiler error: in function_and_variable_visibility, at ipa.c:815
} // namespace boost
^
Please submit a full bug report,
with preprocessed source if appropriate.
See file:///usr/share/doc/gcc-4.8/README.Bugs for instructions.
Preprocessed source stored into /tmp/ccpGeFhP.out file, please attach this to your bugreport.
make: *** [src/sofa/pbrpc/boost_system_error_code.o] Error 1
以php扩展的方式提供给用户,用户使用扩展库在php程序中向server发起RPC调用
service EchoServiceStub
{
rpc Echo(EchoRequest) returns(EchoResponse);
}
生成Service/Method函数接口如下:
class EchoServiceStub extends PHPRpcServiceStub
{
// 用户通过EchoServiceStub 类创建rpc服务实例
function __construct($address);
// 在stub中注册method
private function RegisterEcho();
// 设置rpc调用超时
public function SetTimeout($timeout);
// 发起RPC调用
public function Echo($request, $response, $closure);
// 获取错误码
public function Failed();
// 获取错误提示
public function ErrorText();
}
PHP_METHOD(PHPRpcServiceStub, InitService);
PHP_METHOD(PHPRpcServiceStub, SetTimeout);
PHP_METHOD(PHPRpcServiceStub, Failed);
PHP_METHOD(PHPRpcServiceStub, ErrorText);
PHP_METHOD(PHPRpcServiceStub, RegisterMethod);
PHP_METHOD(PHPRpcServiceStub, InitMethods);
PHP_METHOD(PHPRpcServiceStub, CallMethod);
Hi,升级c++11以后,编译没问题,但是运行初始化client的时候会挂。
gdb如下:
Program terminated with signal 11, Segmentation fault.
#0 signal_and_unlockboost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex > (this=0xd2ae4c80, lock=...) at thirdparty/boost/asio/detail/posix_event.hpp:60
60 signalled_ = true;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.166.el6_7.3.x86_64 zlib-1.2.3-29.el6.x86_64
core文件bt如下:
#0 signal_and_unlockboost::asio::detail::scoped_lock<boost::asio::detail::posix_mutex > (this=0xd2ae4c80, lock=...) at thirdparty/boost/asio/detail/posix_event.hpp:60
#1 wake_one_idle_thread_and_unlock (this=0xd2ae4c80, lock=...) at thirdparty/boost/asio/detail/impl/task_io_service.ipp:484
#2 boost::asio::detail::task_io_service::wake_one_thread_and_unlock (this=0xd2ae4c80, lock=...) at thirdparty/boost/asio/detail/impl/task_io_service.ipp:493
#3 0x000000000054f32e in boost::asio::detail::task_io_service::init_task (this=0xd2ae4c80) at thirdparty/boost/asio/detail/impl/task_io_service.ipp:130
#4 0x0000000000552307 in init_task (this=0x2b0b918, io_service=Unhandled dwarf expression opcode 0xf3
) at thirdparty/boost/asio/detail/impl/epoll_reactor.ipp:145
#5 boost::asio::detail::deadline_timer_serviceboost::asio::time_traits<boost::posix_time::ptime >::deadline_timer_service (this=0x2b0b918, io_service=Unhandled dwarf expression opcode 0xf3
) at thirdparty/boost/asio/detail/deadline_timer_service.hpp:68
#6 0x00000000005523a6 in deadline_timer_service (owner=...) at thirdparty/boost/asio/deadline_timer_service.hpp:77
#7 boost::asio::detail::service_registry::create<boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traitsboost::posix_time::ptime > > (owner=...) at thirdparty/boost/asio/detail/impl/service_registry.hpp:81
#8 0x000000000054c4a6 in boost::asio::detail::service_registry::do_use_service (this=0xd2add000, key=..., factory=0x552350 <boost::asio::detail::service_registry::create<boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traitsboost::posix_time::ptime > >(boost::asio::io_service&)>)
at thirdparty/boost/asio/detail/impl/service_registry.ipp:123
#9 0x000000000055076e in use_service<boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traitsboost::posix_time::ptime > > (this=0x2b1aac8, io_service=Unhandled dwarf expression opcode 0xf3
) at thirdparty/boost/asio/detail/impl/service_registry.hpp:48
#10 use_service<boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traitsboost::posix_time::ptime > > (this=0x2b1aac8, io_service=Unhandled dwarf expression opcode 0xf3
) at thirdparty/boost/asio/impl/io_service.hpp:33
#11 boost::asio::basic_io_object<boost::asio::deadline_timer_service<boost::posix_time::ptime, boost::asio::time_traitsboost::posix_time::ptime > >::basic_io_object (this=0x2b1aac8, io_service=Unhandled dwarf expression opcode 0xf3
) at thirdparty/boost/asio/basic_io_object.hpp:90
#12 0x0000000000707791 in basic_deadline_timer (this=0x2b1aa80, io_service=...) at thirdparty/boost/asio/basic_deadline_timer.hpp:149
#13 sofa::pbrpc::TimerWorker::TimerWorker (this=0x2b1aa80, io_service=...) at ./sofa/pbrpc/timer_worker.h:27
#14 0x00000000006fc16f in sofa::pbrpc::RpcClientImpl::Start (this=0x2b26c00) at sofa/pbrpc/rpc_client_impl.cc:88
#15 0x00000000006fad5c in sofa::pbrpc::RpcClient::RpcClient (this=0xd29f76a0, options=Unhandled dwarf expression opcode 0xf3
) at sofa/pbrpc/rpc_client.cc:16
#16 0x000000000053dc6d in XXXX::XXXX::SofaClientInit (this=0x2b68000) at xxx/xxx/xxxx/XXXCore.cpp:347
f 16如下:
client_options_ = (new sofa::pbrpc::RpcClientOptions());
345 client_options_->work_thread_num = work_thread_num;
346 client_options_->callback_thread_num = callback_thread_num;
347 rpc_client_ = (new sofa::pbrpc::RpcClient(*client_options_));
348 sofa_client_ = (new sofa::client::SofaClient<XXX_Stub>());
349 sofa_client_->Init(rpc_client_,ip_list_str);
错误出现在347行
请问这是已知错误吗?有解决方案吗?
hi
客户端和服务端建立链接后 关闭服务端,发现客户端和服务的链接仍然处于ESTABLISHED状态
我看客户端有定时检测机制 超过keep_alive_time会主动发起关闭 但是没有生效,帮忙看下
谢谢
#0 0x00007f89817f4625 in raise () from /lib64/libc.so.6
#1 0x00007f89817f5e05 in abort () from /lib64/libc.so.6
#2 0x00007f898204fa55 in __gnu_cxx::__verbose_terminate_handler () at ../../.././libstdc++-v3/libsupc++/vterminate.cc:95
#3 0x00007f898204dbf6 in __cxxabiv1::__terminate (handler=) at ../../.././libstdc++-v3/libsupc++/eh_terminate.cc:38
#4 0x00007f898204dc23 in std::terminate () at ../../.././libstdc++-v3/libsupc++/eh_terminate.cc:48
#5 0x00007f898204e6df in __cxxabiv1::__cxa_pure_virtual () at ../../.././libstdc++-v3/libsupc++/pure.cc:50
#6 0x0000000000631318 in sofa::pbrpc::RpcByteStream::on_connect(boost::system::error_code const&) ()
#7 0x000000000062aaed in boost::asio::detail::reactive_socket_connect_op<boost::bi::bind_t<void, boost::mfi::mf1<void, sofa::pbrpc::RpcByteStream, boost::system::error_code const&>, boost::bi::list2boost::bi::value<sofa::pbrpc::shared_ptr<sofa::pbrpc::RpcByteStream >, boost::arg<1> > > >::do_complete(boost::asio::detail::task_io_service, boost::asio::detail::task_io_service_operation, boost::system::error_code const&, unsigned long) ()
#8 0x000000000062dee9 in boost::asio::detail::epoll_reactor::descriptor_state::do_complete(boost::asio::detail::task_io_service, boost::asio::detail::task_io_service_operation, boost::system::error_code const&, unsigned long) ()
#9 0x000000000063081e in boost::asio::detail::task_io_service::run(boost::system::error_code&) ()
#10 0x000000000063118e in sofa::pbrpc::ThreadGroupImpl::thread_run(void*) ()
#11 0x00007f89827749d1 in start_thread () from /lib64/libpthread.so.0
sofa rpc的rpc server支持的连接数有办法控制么?
g++ -O2 -pipe -W -Wall -fPIC -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -DHAVE_SNAPPY -Isrc -I../boost_1_53_0 -I../protobuf-2.4.1/output/include -I/usr/local/include -I/include -c -o src/sofa/pbrpc/dynamic_rpc_channel_impl.o src/sofa/pbrpc/dynamic_rpc_channel_impl.cc
In file included from src/sofa/pbrpc/common_internal.h:19:0,
from src/sofa/pbrpc/dynamic_rpc_channel_impl.h:13,
from src/sofa/pbrpc/dynamic_rpc_channel_impl.cc:7:
src/sofa/pbrpc/ptime.h: 在函数‘std::string sofa::pbrpc::ptime_to_string(const PTime&)’中:
src/sofa/pbrpc/ptime.h:42:37: 警告: 格式 ‘%ld’ expects argument of type ‘long int’, but argument 10 has type ‘boost::date_time::time_duration<boost::posix_time::time_duration, boost::date_time::time_resolution_traits<boost::date_time::time_resolution_traits_adapted64_impl, (boost::date_time::time_resolutions)5u, 1000000, 6u> >::fractional_seconds_type {aka long long int}’ [-Wformat]
src/sofa/pbrpc/ptime.h:42:37: 警告: 格式 ‘%ld’ expects argument of type ‘long int’, but argument 10 has type ‘boost::date_time::time_duration<boost::posix_time::time_duration, boost::date_time::time_resolution_traits<boost::date_time::time_resolution_traits_adapted64_impl, (boost::date_time::time_resolutions)5u, 1000000, 6u> >::fractional_seconds_type {aka long long int}’ [-Wformat]
src/sofa/pbrpc/atomic.h: Assembler messages:
src/sofa/pbrpc/atomic.h:59: Error: invalid instruction suffix for `xadd'
make: *** [src/sofa/pbrpc/dynamic_rpc_channel_impl.o] 错误 1
OS:
Linux 3.2.0-59-generic-pae #90-Ubuntu SMP Tue Jan 7 23:07:06 UTC 2014 i686 i686 i386 GNU/Linux
gcc -v:
gcc 版本 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
进行RPC调用时,如果对方进程挂掉,会导致调用者进程段错误
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff488f700 (LWP 20041)]
google::protobuf::MessageLite::SerializePartialToCodedStream (this=this@entry=0x7fffd00027d0, output=output@entry=0x7ffff488e330) at google/protobuf/message_lite.cc:235
235 const int size = ByteSize(); // Force size to be cached.
(gdb) bt
#0 google::protobuf::MessageLite::SerializePartialToCodedStream (this=this@entry=0x7fffd00027d0, output=output@entry=0x7ffff488e330) at google/protobuf/message_lite.cc:235
#1 0x00007ffff7b20ee5 in google::protobuf::MessageLite::SerializeToCodedStream (this=this@entry=0x7fffd00027d0, output=output@entry=0x7ffff488e330)
at google/protobuf/message_lite.cc:230
#2 0x00007ffff7b20f1f in google::protobuf::MessageLite::SerializeToZeroCopyStream (this=0x7fffd00027d0, output=) at google/protobuf/message_lite.cc:263
#3 0x000000000048b100 in sofa::pbrpc::RpcClientImpl::CallMethod(google::protobuf::Message const_, google::protobuf::Message_, sofa::pbrpc::shared_ptrsofa::pbrpc::RpcControllerImpl const&) ()
#4 0x00000000004a2fc9 in sofa::pbrpc::SimpleRpcChannelImpl::CallMethod(google::protobuf::MethodDescriptor const_, google::protobuf::RpcController_, google::protobuf::Message const_, google::protobuf::Message_, google::protobuf::Closure*) ()
#5 0x000000000043d342 in bfs::ChunkServer_Stub::WriteBlock (this=0x740070, controller=0x7fffc4000a20, request=0x7fffd00027d0, response=0x7fffc4000940, done=0x7fffc4000e90)
at src/proto/chunkserver.pb.cc:2720
#6 0x000000000041d89a in bfs::RpcClient::AsyncRequest<bfs::ChunkServer_Stub, bfs::WriteBlockRequest, bfs::WriteBlockResponse, google::protobuf::Closure>(bfs::ChunkServer_Stub_, void (bfs::ChunkServer_Stub::)(google::protobuf::RpcController, bfs::WriteBlockRequest const_, bfs::WriteBlockResponse_, google::protobuf::Closure_), bfs::WriteBlockRequest const_, bfs::WriteBlockResponse_, boost::function<void (bfs::WriteBlockRequest const*, bfs::WriteBlockResponse*, bool, int)>, int, int) (this=0x742fc0, stub=0x740070,
func=&virtual table offset 48, request=0x7fffd00027d0, response=0x7fffc4000940, callback=..., rpc_timeout=60, retry_times=1) at ./src/rpc/rpc_client.h:86
#7 0x0000000000412b7a in bfs::BfsFileImpl::DelayWriteChunk (this=0x74e740, buffer=0x73f860, request=0x7fffd00027d0, retry_times=0, cs_addr="Porsche:8020")
at src/sdk/bfs.cc:846
#8 0x000000000042f0e5 in boost::_mfi::mf4<void, bfs::BfsFileImpl, bfs::WriteBuffer*, bfs::WriteBlockRequest const*, int, std::string>::operator() (this=0x7fffc4000900,
p=0x74e740, a1=0x73f860, a2=0x7fffd00027d0, a3=0, a4="Porsche:8020") at /usr/include/boost/bind/mem_fn_template.hpp:506
#9 0x000000000042e10c in boost::_bi::list5boost::_bi::value<bfs::BfsFileImpl*, boost::_bi::valuebfs::WriteBuffer*, boost::_bi::value<bfs::WriteBlockRequest const*>, boost::_bi::value, boost::_bi::valuestd::string >::operator()<boost::_mfi::mf4<void, bfs::BfsFileImpl, bfs::WriteBuffer*, bfs::WriteBlockRequest const*, int, std::string>, boost::_bi::list0> (this=0x7fffc4000910, f=..., a=...) at /usr/include/boost/bind/bind.hpp:525
#10 0x000000000042c4e0 in boost::_bi::bind_t<void, boost::_mfi::mf4<void, bfs::BfsFileImpl, bfs::WriteBuffer*, bfs::WriteBlockRequest const*, int, std::string>, boost::_bi::list5boost::_bi::value<bfs::BfsFileImpl*, boost::_bi::valuebfs::WriteBuffer*, boost::_bi::value<bfs::WriteBlockRequest const*>, boost::_bi::value, boost::_bi::valuestd::string > >::operator() (this=0x7fffc4000900) at /usr/include/boost/bind/bind_template.hpp:20
#11 0x0000000000429cca in boost::detail::function::void_function_obj_invoker0<boost::_bi::bind_t<void, boost::_mfi::mf4<void, bfs::BfsFileImpl, bfs::WriteBuffer*, bfs::WriteBlockRequest const*, int, std::string>, boost::_bi::list5boost::_bi::value<bfs::BfsFileImpl*, boost::_bi::valuebfs::WriteBuffer*, boost::_bi::value<bfs::WriteBlockRequest const*>, boost::_bi::value, boost::_bi::valuestd::string > >, void>::invoke (function_obj_ptr=...) at /usr/include/boost/function/function_template.hpp:153
#12 0x000000000041a6a5 in boost::function0::operator() (this=0x7ffff488ee40) at /usr/include/boost/function/function_template.hpp:767
#13 0x00000000004165de in common::ThreadPool::ThreadProc (this=0x738c80 bfs::g_thread_pool) at ./src/common/thread_pool.h:171
#14 0x00000000004162ce in common::ThreadPool::ThreadWrapper (arg=0x738c80 bfs::g_thread_pool) at ./src/common/thread_pool.h:145
#15 0x00007ffff76a50a5 in start_thread (arg=0x7ffff488f700) at pthread_create.c:309
#16 0x00007ffff6c93cfd in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
这里说的Cancel是指Client可以主动取消request的执行,包括在request还没有通过网络发送时取消发送,或者将Cancel命令通过网络传递到server端以提前终止服务的执行(在server端的服务实现支持Cancel功能的情况下),其目的都是避免不必要的资源消耗,无论是网络资源还是计算资源。
protobuf的RPC框架中定义了Cancel功能的接口和语义,具体在RpcController类中进行了定义:
// Client-side methods ---------------------------------------------
// Advises the RPC system that the caller desires that the RPC call be
// canceled. The RPC system may cancel it immediately, may wait awhile and
// then cancel it, or may not even cancel the call at all. If the call is
// canceled, the "done" callback will still be called and the RpcController
// will indicate that the call failed at that time.
virtual void StartCancel() = 0;
// Server-side methods ---------------------------------------------
// If true, indicates that the client canceled the RPC, so the server may
// as well give up on replying to it. The server should still call the
// final "done" callback.
virtual bool IsCanceled() const = 0;
// Asks that the given callback be called when the RPC is canceled. The
// callback will always be called exactly once. If the RPC completes without
// being canceled, the callback will be called after completion. If the RPC
// has already been canceled when NotifyOnCancel() is called, the callback
// will be called immediately.
//
// NotifyOnCancel() must be called no more than once per request.
virtual void NotifyOnCancel(Closure* callback) = 0;
考虑server端用户是如何使用cancel功能的:在用户实现的服务处理函数开始时,通过RpcController::NotifyOnCancel()注册一个Closure回调函数,回调函数的处理逻辑是提前终止服务处理,避免不必要的资源消耗。
考虑的一种实现方案是:在client端调用RpcController::StartCancel的时候,发送一个special的cancel_request到server端,server收到cancel_request后,找到这个request对应的RpcController,然后调用服务实现者通过RpcController::NotifyOnCancel()注册的回调函数。
g++ echo_service.pb.o server.o -o server ../../output/lib/libsofa-pbrpc.a /Users/wangdesheng/Desktop/code/cpp_program/sofa-pbrpc/lib/protobuf/output/lib/libprotobuf.a /Users/wangdesheng/Desktop/code/cpp_program/sofa-pbrpc/lib/snappy/output/lib/libsnappy.a -L/Users/wangdesheng/Desktop/code/cpp_program/sofa-pbrpc/lib/zlib/output/lib -lpthread -lz
Undefined symbols for architecture x86_64:
"_ProfilerStart", referenced from:
sofa::pbrpc::Profiling::CpuProfilingFunc() in libsofa-pbrpc.a(profiling.o)
sofa::pbrpc::Profiling::DoCpuProfiling(sofa::pbrpc::Profiling::DataType) in libsofa-pbrpc.a(profiling.o)
"_ProfilerStop", referenced from:
sofa::pbrpc::Profiling::CpuProfilingFunc() in libsofa-pbrpc.a(profiling.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [server] Error 1
比如 提供一个简易的http页面,可以填入Request需要的各个字段。然后可以请求后,网页展示出Response
sofa-pbrpc和bgcc都是百度的出品,请问哪个在百度内部使用会多点?
rpc client的回调线程负载不均衡,请问有类似的问题么?
echo sample里面的client_http.sh,将post的"Hello, world!"替换为一个长度为1k字节的字符串,响应时间会增加到两秒钟左右。
请问一下 后续php版本有支持安排么? php虽然可以通过http访问解决 但是像压缩这种需求还是不能很好支持吧
原来的call命令只支持text格式的request-message,在此基础上增加对json格式的支持,方便使用
40万qps在两年前处于领先地位,而今天已经被很多竞品超越。
希望拿出几天时间优化下性能,将极限吞吐提升到100万qps以上。
如题。
非常期待TODO里提到的功能:多语言客户端支持,多Server和自动负载均衡支持。
boost_system_error_code.cc
要把这里面的匿名namespace 注释掉才行,不然触发gcc 4.6的bug,编译通不过。
atomic.h 里面 atomic_inc_ret_old64 在32位机器编译通不过,改用__sync_fetch_and_add 就可以,为啥不直接用gcc内置的__sync_fetch_and_add那些函数呢。
protocol buffer那个最好改成make时生成吧。
当RequestTimeout之后,实际上对应Socket没有关闭,超时后数据还是会被接收,这在传输大数据块时,会占用较大带宽。
这个问题存在的原因在于:
考虑如下:
参见pull request #84
但是还有改进的地方:
g++ -O2 -pipe -W -Wall -fPIC -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -DHAVE_SNAPPY -Isrc -I/home/yan97ao/Downloads/boost_1_53_0 -I/home/yan97ao/Downloads/protobuf-2.4.1/output/include -I/home/yan97ao/Downloads/snappy-1.1.2/output/include -I/include -c -o src/sofa/pbrpc/block_wrappers.o src/sofa/pbrpc/block_wrappers.cc
g++ -O2 -pipe -W -Wall -fPIC -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -DHAVE_SNAPPY -Isrc -I/home/yan97ao/Downloads/boost_1_53_0 -I/home/yan97ao/Downloads/protobuf-2.4.1/output/include -I/home/yan97ao/Downloads/snappy-1.1.2/output/include -I/include -c -o src/sofa/pbrpc/boost_system_error_code.o src/sofa/pbrpc/boost_system_error_code.cc
src/sofa/pbrpc/boost_system_error_code.cc:440:1: internal compiler error: in function_and_variable_visibility, at ipa.c:929
Please submit a full bug report,
with preprocessed source if appropriate.
See file:///usr/share/doc/gcc-4.6/README.Bugs for instructions.
Preprocessed source stored into /tmp/ccG9Nrmn.out file, please attach this to your bugreport.
make: *** [src/sofa/pbrpc/boost_system_error_code.o] Error 1
tested in Ubuntu 12.04 gcc 4.6 and Ubuntu 14.04 gcc 4.8
最近在线上环境一些依赖sofa-pbrpc的服务出现"resolve address failed"的问题,导致client和一些server不能正常通信。
如 #37 中描述:RpcChannel在构造函数中调用具体实现channel的Init()函数对地址进行解析不能返回Init的结果,当地址解析失败会设置_resolve_address_succeed的状态,在之后每次RpcChannel的CallMethod都会检查_resolve_address_succeed状态,如果为false则返回用户失败并设置RPC_ERROR_RESOLVE_ADDRESS的错误码。
@qinzuoyan @cyshi 左言和承毅对这个问题有什么方案吗?
/a/b
/a/c
使用上述两个路径同时注册,后一个会注册失败
另外/a/* 可以匹配/a对应WebServlet这个实现需要斟酌一下,这样会导致以下问题
例如 我注册了一个 /a
同时我也注册了/a/b , /a/c 这个时候一切都符合预期
如果我没有注册 /a 这个时候注册 /a/b , /a/c 这个时候 第二个注册会失败
建议http路径解析不需要这样的容错逻辑,其下可能隐藏bug,即耗费性能,用户很少会去直接输url查询
Hi:
一直有个问题想咨询下您,我看到wiki上有描述了client是支持链接探活的(针对server端服务不可用的情况)。但是,如果用于生产环境,那么肯定存在一个上线时切流的问题,所以想问下,有没有类似于zookeeper的机制,能够保障主动切流量且不影响线上服务的feature。
谢谢
hi:
我试了在sample里面的echo例子,直接make会报ERROR: need snappy header
的错误提示。我是在mac osx 10.10的机子上面跑的。
我按照install教程里面的地址,把snappy1.1.2包下回来,也安装成功了。sofa-pbrpc也是安装成功的,能正常跑起来。
我看了下make脚本,貌似是SNAPPY_DIR这个变量没设置到之类的。
一个为:
int64 message_size; // 8 bytes: message_size = meta_size + data_size
另一个为:
message_size = message_size + data_size。
If so and user retry in the callback then may deadlock in RpcClientImpl::FindOrCreateStream because of the Reentrant of _stream_map_lock.
在server端,如果收到的请求是通过Http协议,需提供相关接口以获取http相关信息,包括Path、Headers、QueryParams。
问题描述:原来的ConnectionCount是一个非精确值,是通过TimerMaintain定期更新的,由于TimerMaintain每100ms执行一次,所以ConnectionCount值不是实时的。而通过max_connection_count限制最大连接数又依赖于ConnectionCount。
解决办法:对stream增加OnClosed()回调函数,在close stream的时候从RpcServerImpl::_stream_set或者RpcClientImpl::_stream_map中立即移除;获取ConnectionCount时直接获取_stream_set.size()或者_stream_map.size()。
用户通过连编 gperftools 库,即可查看server的profiling数据,数据展示支持文本和图片两种方式,server端不需要安装graphviz
class Profiling
{
public:
// 两个servlet注册到WebService,用于展示Profiling数据
bool CpuProfiling(HTTPRequest, HTTPResponse);
bool MemoryProfiling(HTTPRequest, HTTPResponse);
};
Profiling
中会增加一个线程用于进行profilingclass Profiling
{
public:
// 两个servlet注册到WebService,用于展示Profiling数据
bool CpuProfiling(HTTPRequest, HTTPResponse);
bool MemoryProfiling(HTTPRequest, HTTPResponse);
private:
// profiling 线程,专门负责进行Profiling
ThreadGroupImplPtr _profiling_thread_group;
};
增加 viz.js.cc
static const std::string vizjs = "content of viz.js";
为了生成dot,增加 pprof.perl.cc
static const std::string pprof = "content of pprof";
// file profiling.cc
extern "C"
{
// cpu profiling需要的函数
int __attribute__((weak)) ProfilerStart(const char* fname);
void __attribute__((weak)) ProfilerStop();
}
// file common.h
#ifdef SOFA_PBRPC_PROFILING
#include <gperftools/profiler.h>
#endif
namespace sofa {
namespace pbrpc {
#ifdef SOFA_PBRPC_PROFILING
void touch_gperftools_profiler()
{
SCHECK(false);
ProfilerStart("function_never_run");
ProfilerStop();
}
void touch_profiler()
{
SCHECK(false);
touch_gperftools_profiler();
}
#endif
}
}
@qinzuoyan @bluebore 两位先看下
rpc_channel对象初始化时会解析对端ip,如果解析失败会导致这个对象上后续所有的call_method全部失败,只能靠用户析构并重新创建channel。希望能在rpc层面解决一下,例如call_method时检查一下距上次解析失败的时间,适当的进行重试。
最新master代码
连接建立失败
libsofa_pbrpc ERROR src/sofa/pbrpc/rpc_byte_stream.h:285] on_connect(): connect error: 10.195.113.13:7701: The descriptor does not fit into the select call's fd_set
暂时没有复现 建个issue跟踪
在使用sofa-pbrpc时发现server有时候会不响应client发出去的最后一个请求,打出function trace后发现是如下场景:
发现1.1.0和master上都有该问题,该问题的影响是,如果客户端的逻辑是blocking的(使用 blocking接口或者必须等待上一个request的response才会触发下一次rpc),最后一个request会hang住或者超时。
多谢 Xi Liu([email protected])报告该问题。
how many options defined in this framework?
what is more, can we get the some low level info from the RPC, likely the fd, peer IP, as we may need to do the stats on this items, Thanks!
我通过max_throughput_out配置为10(限速为10MB/s)企图将发包的网络速度控制在10MB/s,但发现速度控制不住,远大于这个值。在我的环境不配置时速度为70MB/S,配置max_throughput_out为10后速度为42MB/S。
请问这个问题可以修正吗?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.