使用brpc遇到的一些bug和解决方案
这篇文章记录一下在使用brpc的时候遇到的bug以及解决方案,长期更新。
流式RPC遇到"pure virtual method called"错误
流式RPC的使用需要继承brpc::StreamInputHandler
,并且实现它的三个纯虚函数,如下:
1 |
|
在有些应用场景中,StreamReceiver
可能并不长,在完成一次流式传输以后就立刻析构了,代码结构类似于:
1 |
|
这样的代码结构里,stream_recevier
的生命周期仅限于中括号内部,一旦运行退出中括号,它就被析构了。但是前面有说到StreamReciver::on_closed
方法会在stream被关闭以后调用,而brpc::StreamClose(sd)
不会等到StreamReciver::on_close
被调用才返回。因此,有可能出现stream_recevier
先被析构,而后on_close
被调用的情况,此时虚函数表找到的就是brpc::StreamInputHandler
这个基类的on_close
了,是一个纯虚函数,从而引发了"pure virtual method called"的错误。
解决方案
首先,理所当然的解决方案当然是避免这种代码结构,可以让StreamReciver
作为brpc Service的成员变量,生命周期和服务一致。
但是,有时候不可避免地会出现这种代码结构,例如不同的情况下需要构造不同的StreamReciver
,在准备建立stream时才构造,完成传输后立刻销毁。我对于这种情况的对策是给StreamReciver
加一个close_
的成员变量,并在on_close
方法内将其置为true
。关闭stream以后,轮询close_
,判断on_close
方法是否已经被调用,确认被调用后再退出。具体如下:
1 |
|
1 |
|
这样就可以确保on_close
方法在stream_recevier
被析构前得到调用,避免纯虚函数调用错误。
流式RPC遇到"Fail to parse response from xxxx:xxxx by streaming_rpc at client-side"错误
这个问题在brpc的issue#392有被讨论到,具体原因不明,可能是普通RPC和流式RPC混用同一个连接导致的。
解决方案
目前的解决方案是客户端创建brpc::Channel
时,将brpc::ChannelOptions
的connection_type
设置为"pooled"
,如下:
1 |
|
按照这样修改代码后,暂时没遇到错误了,但是不确保是不是真的解决了问题。