noa*_*hlz 7 .net java tcp thrift
我有一个在Linux上运行的Java应用程序提供的Thrift API.我正在使用.NET客户端连接到API并执行操作.
对服务的前几次调用工作没有错误,但随后(看似随机)一个电话将"挂起".如果我强行退出我的客户端并尝试重新连接,该服务会再次挂起,或者我的客户端出现以下错误:
Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at Thrift.Transport.TStreamTransport.Read(Byte[] buf, Int32 off, Int32 len)
(etc.)
Run Code Online (Sandbox Code Playgroud)
当我使用JConsole获取线程转储时,服务器已启用 accept()
"Thread-1" prio=10 tid=0x00002aaad457a800 nid=0x79c7 runnable [0x00000000434af000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408)
- locked <0x00000005c0fef470> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:462)
at java.net.ServerSocket.accept(ServerSocket.java:430)
at org.apache.thrift.transport.TServerSocket.acceptImpl(TServerSocket.java:113)
at org.apache.thrift.transport.TServerSocket.acceptImpl(TServerSocket.java:35)
at org.apache.thrift.transport.TServerTransport.accept(TServerTransport.java:31)
at org.apache.thrift.server.TSimpleServer.serve(TSimpleServer.java:63)
Run Code Online (Sandbox Code Playgroud)
netstat在服务器上显示连接到服务端口,在TIME_WAIT强制退出客户端几分钟后,服务端口最终消失(正如预期的那样).
设置Thrift服务的代码如下:
int port = thriftServicePort;
String host = thriftServiceHost;
InetAddress adr = InetAddress.getByName(host);
InetSocketAddress address = new InetSocketAddress(adr, port);
TServerTransport serverTransport = new TServerSocket(address);
TServer server = new TSimpleServer(new TServer.Args(serverTransport).processor((org.apache.thrift.TProcessor)processor));
server.serve();
Run Code Online (Sandbox Code Playgroud)
请注意,我们使用的TServerTransport是带有显式主机名或IP地址的构造函数.我怀疑我应该改变它以获取仅指定端口(最终绑定到InetAddress.anyLocalAddress())的构造函数.或者,我想我可以将服务配置为绑定到"通配符"地址("0.0.0.0").
我应该提一下,该服务不是在开放的互联网上托管的.它托管在一个专用网络中,我使用SSH隧道来实现它.因此,服务绑定的主机名在我的本地网络中无法解析(尽管我可以通过隧道建立初始连接).我想知道这是否类似于RMI TCP回调问题?
对于正在发生的事情(如果这是一个常见问题),还是我可以采取的其他故障排除步骤,是否有技术说明?
UPDATE
今天遇到同样的问题,但这次jstack显示Thrift服务器正在阻止从输入流中读取:
"Thread-1" prio=10 tid=0x00002aaad43fc000 nid=0x60b3 runnable [0x0000000041741000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:127)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:84)
at org.apache.thrift.protocol.TBinaryProtocol.readAll(TBinaryProtocol.java:378)
at org.apache.thrift.protocol.TBinaryProtocol.readI32(TBinaryProtocol.java:297)
at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:204)
at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:22)
at org.apache.thrift.server.TSimpleServer.serve(TSimpleServer.java:70)
Run Code Online (Sandbox Code Playgroud)
所以我们需要在TServerSocket构造函数中设置"客户端超时" .但是为什么会导致应用程序在阻塞时拒绝连接accept()呢?
从你的堆栈跟踪来看,你似乎正在使用 TSimpleServer,其javadocs 说,
用于测试的简单单线程服务器。
可能您想要使用的是TThreadPoolServer。
最有可能发生的情况是 TSimpleServer 的单线程被阻塞,等待死客户端响应或超时。而且由于 TSimpleServer 是单线程的,因此没有线程可用于处理其他请求。
| 归档时间: |
|
| 查看次数: |
4523 次 |
| 最近记录: |