You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@thrift.apache.org by panfei <cn...@gmail.com> on 2012/07/19 08:45:47 UTC

reuse Ttransport or not ?

Hi all:

there maybe a lot of RPC calls from the client to the server, I want to
know , in this case, should I create a transport and keep it opened to do
the RPC calls , or should I create a transport on every RPC call ? and why
? thanks !


-- 
不学习,不知道

Re: reuse Ttransport or not ?

Posted by panfei <cn...@gmail.com>.
2012/7/20 Mark Slee <ms...@fb.com>

> Agreed with Rush. A couple other considerations worth mentioning here:
>
> - There is a bit of TCP overhead every time you create and then tear down
> a connection, if you're trying to squeeze out really high performance and
> this is the same client talking to the same server, it's preferable not to
> pay that every time
>
> - Re-using the client does mean that the socket is also held open longer
> on the server side. Timeouts may come into play here if there are
> significant delays between client calls. If your server specifies a read
> timeout - it *will* close the client connection after that period elapses
> with no new call being made.
>

Hi Mark , thanks for your reply, and I want to know How to change the read
timeout or set the server without timeout until the client close the
connection?

>
> So, as long as your server is not going to be maxed out on connections
> from tons of different clients, it's generally preferable to re-use.
>
> On 7/19/12 10:02 AM, "Rush Manbert" <ru...@manbert.com> wrote:
>
> >On Jul 18, 2012, at 11:45 PM, panfei wrote:
> >
> >> Hi all:
> >>
> >> there maybe a lot of RPC calls from the client to the server, I want to
> >> know , in this case, should I create a transport and keep it opened to
> >>do
> >> the RPC calls , or should I create a transport on every RPC call ? and
> >>why
> >> ? thanks !
> >>
> >>
> >> --
> >> 不学习,不知道
> >
> >On a *nix system, opening a transport for each RPC call uses a socket.
> >When you close the transport, the system keeps the socket around for a
> >while, so it is unavailable for re-use. Depending on the rate at which
> >you make RPC calls, your system can get starved for sockets, and you will
> >need to add retry logic to handle that. So it's better to open a single
> >client and use it for multiple calls.
> >
> >I'm guessing you would see the same effect from a Windows client.
> >
> >- Rush
>
>


-- 
不学习,不知道

Re: reuse Ttransport or not ?

Posted by Rush Manbert <ru...@manbert.com>.
Disclaimer: I know a lot about the C++ implementation, but I'm not a Java guy and have never looked at the Java code.

That being said:
As near as I can tell, the code as written should work, and you should be able to call updateMemCache() any number of times using the single client object.

The fact that you get 3 successful calls suggests that there is some sort of race and some code thread completed and closed the transport when you didn't expect it. There's something in the stack trace called java.util.concurrent.ThreadPoolExecutor$Worker.runTask that makes me doubly suspicious, but, as I said, I don't write Java code, so I don't know what the real implications might be.

If I were debugging this I would put a breakpoint in transport.close() and I would also monitor what's happening on the server side to see if it closes the socket for some reason.

Do any of you Jave guys have anything to add? Maybe Bryan?

- Rush

On Jul 19, 2012, at 9:26 PM, panfei wrote:

> Hi Rush:
> 
> very thank you for your kindly help. but I encountered a  strange problem,
> I use only one TSocket object to connect to a thrift server and then do rpc
> calls in a for loop (10 calls), but it gives:
> 
> *TTransport transport = null;*
> * *
> * try{*
> * transport = new TSocket(host, port); *
> * TProtocol protocol = new TBinaryProtocol(transport); *
> * BIClientServer.Client client = new BIClientServer.Client(protocol);*
> * transport.open(); *
> * *
> * for(String arg : args){*
> * logger.info(String.format("[%s] need value for key [%s]", hostport, arg));
> *
> * String val = hb.get(arg);*
> * client.updateMemCache(arg, val); *
> * }*
> * }catch(Exception e){*
> * e.printStackTrace();*
> * }finally{*
> * transport.close(); *
> * }*
> 
> it report exception as follows, only 3 of 10 calls succeeds, I want to know
> how to solve it , I really want to reuse TSocket... thanks:
> 
> org.apache.thrift.transport.TTransportException: java.net.SocketException:
> Broken pipe
>        at
> org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:161)
>        at
> com.hoolai.dataservice.BIClientServer$Client.send_updateMemCache(BIClientServer.java:105)
>        at
> com.hoolai.dataservice.BIClientServer$Client.updateMemCache(BIClientServer.java:94)
>        at
> com.hoolai.dataservice.BIServerHandler.processUpdateMemCacheSignalAgent(BIServerHandler.java:111)
>        at
> com.hoolai.dataservice.utils.ServerConsumer.run(ServerConsumer.java:38)
>        at
> java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
>        at
> java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
>        at java.lang.Thread.run(Thread.java:662)
> Caused by: java.net.SocketException: Broken pipe
>        at java.net.SocketOutputStream.socketWrite0(Native Method)
>        at
> java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
>        at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
>        at
> java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
>        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
>        at
> org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:159)
> 
> 
> after I change the code as follow , it works well -_- :
> 
> try{
> for(String arg : args){
> transport = new TSocket(host, port); // 底层数据传输层
> TProtocol protocol = new TBinaryProtocol(transport); // 对数据读写的封装协议
> BIClientServer.Client client = new BIClientServer.Client(protocol);
> transport.open(); // 连接到远程Server
> System.out.println("********");
> logger.info(String.format("[%s] need value for key [%s]", hostport, arg));
> String val = hb.get(arg);
> client.updateMemCache(arg, val); // arg就是key
> }
> }catch(Exception e){
> e.printStackTrace();
> }finally{
> transport.close(); // 处理完之后关闭transport
> }
> 
> 2012/7/20 Rush Manbert <ru...@manbert.com>
> 
>> On Jul 18, 2012, at 11:45 PM, panfei wrote:
>> 
>>> Hi all:
>>> 
>>> there maybe a lot of RPC calls from the client to the server, I want to
>>> know , in this case, should I create a transport and keep it opened to do
>>> the RPC calls , or should I create a transport on every RPC call ? and
>> why
>>> ? thanks !
>>> 
>>> 
>>> --
>>> 不学习,不知道
>> 
>> On a *nix system, opening a transport for each RPC call uses a socket.
>> When you close the transport, the system keeps the socket around for a
>> while, so it is unavailable for re-use. Depending on the rate at which you
>> make RPC calls, your system can get starved for sockets, and you will need
>> to add retry logic to handle that. So it's better to open a single client
>> and use it for multiple calls.
>> 
>> I'm guessing you would see the same effect from a Windows client.
>> 
>> - Rush
> 
> 
> 
> 
> -- 
> 不学习,不知道


Re: reuse Ttransport or not ?

Posted by panfei <cn...@gmail.com>.
Hi Rush:

very thank you for your kindly help. but I encountered a  strange problem,
I use only one TSocket object to connect to a thrift server and then do rpc
calls in a for loop (10 calls), but it gives:

*TTransport transport = null;*
* *
* try{*
* transport = new TSocket(host, port); *
* TProtocol protocol = new TBinaryProtocol(transport); *
* BIClientServer.Client client = new BIClientServer.Client(protocol);*
* transport.open(); *
* *
* for(String arg : args){*
* logger.info(String.format("[%s] need value for key [%s]", hostport, arg));
*
* String val = hb.get(arg);*
* client.updateMemCache(arg, val); *
* }*
* }catch(Exception e){*
* e.printStackTrace();*
* }finally{*
* transport.close(); *
* }*

it report exception as follows, only 3 of 10 calls succeeds, I want to know
how to solve it , I really want to reuse TSocket... thanks:

org.apache.thrift.transport.TTransportException: java.net.SocketException:
Broken pipe
        at
org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:161)
        at
com.hoolai.dataservice.BIClientServer$Client.send_updateMemCache(BIClientServer.java:105)
        at
com.hoolai.dataservice.BIClientServer$Client.updateMemCache(BIClientServer.java:94)
        at
com.hoolai.dataservice.BIServerHandler.processUpdateMemCacheSignalAgent(BIServerHandler.java:111)
        at
com.hoolai.dataservice.utils.ServerConsumer.run(ServerConsumer.java:38)
        at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
Caused by: java.net.SocketException: Broken pipe
        at java.net.SocketOutputStream.socketWrite0(Native Method)
        at
java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
        at
java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
        at
org.apache.thrift.transport.TIOStreamTransport.flush(TIOStreamTransport.java:159)


after I change the code as follow , it works well -_- :

try{
for(String arg : args){
transport = new TSocket(host, port); // 底层数据传输层
TProtocol protocol = new TBinaryProtocol(transport); // 对数据读写的封装协议
BIClientServer.Client client = new BIClientServer.Client(protocol);
transport.open(); // 连接到远程Server
System.out.println("********");
logger.info(String.format("[%s] need value for key [%s]", hostport, arg));
String val = hb.get(arg);
client.updateMemCache(arg, val); // arg就是key
}
}catch(Exception e){
e.printStackTrace();
}finally{
transport.close(); // 处理完之后关闭transport
}

2012/7/20 Rush Manbert <ru...@manbert.com>

> On Jul 18, 2012, at 11:45 PM, panfei wrote:
>
> > Hi all:
> >
> > there maybe a lot of RPC calls from the client to the server, I want to
> > know , in this case, should I create a transport and keep it opened to do
> > the RPC calls , or should I create a transport on every RPC call ? and
> why
> > ? thanks !
> >
> >
> > --
> > 不学习,不知道
>
> On a *nix system, opening a transport for each RPC call uses a socket.
> When you close the transport, the system keeps the socket around for a
> while, so it is unavailable for re-use. Depending on the rate at which you
> make RPC calls, your system can get starved for sockets, and you will need
> to add retry logic to handle that. So it's better to open a single client
> and use it for multiple calls.
>
> I'm guessing you would see the same effect from a Windows client.
>
> - Rush




-- 
不学习,不知道

Re: reuse Ttransport or not ?

Posted by Mark Slee <ms...@fb.com>.
Agreed with Rush. A couple other considerations worth mentioning here:

- There is a bit of TCP overhead every time you create and then tear down
a connection, if you're trying to squeeze out really high performance and
this is the same client talking to the same server, it's preferable not to
pay that every time

- Re-using the client does mean that the socket is also held open longer
on the server side. Timeouts may come into play here if there are
significant delays between client calls. If your server specifies a read
timeout - it *will* close the client connection after that period elapses
with no new call being made.

So, as long as your server is not going to be maxed out on connections
from tons of different clients, it's generally preferable to re-use.

On 7/19/12 10:02 AM, "Rush Manbert" <ru...@manbert.com> wrote:

>On Jul 18, 2012, at 11:45 PM, panfei wrote:
>
>> Hi all:
>> 
>> there maybe a lot of RPC calls from the client to the server, I want to
>> know , in this case, should I create a transport and keep it opened to
>>do
>> the RPC calls , or should I create a transport on every RPC call ? and
>>why
>> ? thanks !
>> 
>> 
>> -- 
>> 不学习,不知道
>
>On a *nix system, opening a transport for each RPC call uses a socket.
>When you close the transport, the system keeps the socket around for a
>while, so it is unavailable for re-use. Depending on the rate at which
>you make RPC calls, your system can get starved for sockets, and you will
>need to add retry logic to handle that. So it's better to open a single
>client and use it for multiple calls.
>
>I'm guessing you would see the same effect from a Windows client.
>
>- Rush


Re: reuse Ttransport or not ?

Posted by Rush Manbert <ru...@manbert.com>.
On Jul 18, 2012, at 11:45 PM, panfei wrote:

> Hi all:
> 
> there maybe a lot of RPC calls from the client to the server, I want to
> know , in this case, should I create a transport and keep it opened to do
> the RPC calls , or should I create a transport on every RPC call ? and why
> ? thanks !
> 
> 
> -- 
> 不学习,不知道

On a *nix system, opening a transport for each RPC call uses a socket. When you close the transport, the system keeps the socket around for a while, so it is unavailable for re-use. Depending on the rate at which you make RPC calls, your system can get starved for sockets, and you will need to add retry logic to handle that. So it's better to open a single client and use it for multiple calls.

I'm guessing you would see the same effect from a Windows client.

- Rush