thrift常见异常及原因分析(updating)
作者发现,本文被多个博客和网站转发。赠人玫瑰,手有余香!
本文版权归作者和博客园共有,欢迎转载,转载请注明出处: https://www.cnblogs.com/buguge
【org.apache.thrift.TException家族】
【Thrift架构】
以下是thrift的客户端和服务端交互的一个原理图。可以看到遵循了rpc框架的传输层、协议层和应用层三层。本文提到的异常就是与这三层相对应的传输异常TTransportException(ConnectException、SocketTimeoutException)、协议异常TProtocolException和应用异常TApplicationException。
■ org.apache.thrift.transport.TTransportException: java.net.SocketException: Connection reset
既然是Connection reset,即“连接被重置”,从字面意思就可以判断出来,是连接的问题。那么,Thrift框架底层就是传输层,自然就是TTransport的问题了。什么问题呢?这个异常是由于client端指定的TTransport与服务端不一致导致的。demo中服务端是TFramedTransport,client端的TTransport实例是TSocket。
org.apache.thrift.transport.TTransportException: java.net.SocketException: Connection reset
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:129)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:86)
at org.apache.thrift.protocol.TBinaryProtocol.readAll(TBinaryProtocol.java:425)
at org.apache.thrift.protocol.TBinaryProtocol.readI32(TBinaryProtocol.java:321)
at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:225)
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:77)
at com.emaxcard.route.thrift.quickpay.TBatchPayQueryService$Client.recv_batchPayQuery(TBatchPayQueryService.java:61)
at com.emaxcard.route.thrift.quickpay.TBatchPayQueryService$Client.batchPayQuery(TBatchPayQueryService.java:48)
at com.emaxcard.ThriftTest.main(ThriftTest.java:38)
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:209)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286)
at java.io.BufferedInputStream.read(BufferedInputStream.java:345)
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:127)
... 8 more
■ org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: connect timed out
在执行transport.open()与服务端建立连接时,超时了。服务端响应时间超出了客户端设置的connectTimeout值。BTW,因为thrift多应用于局域网分布式系统,所以通常情况下不会出现连接超时,可能是所指定的服务压根儿就不存在(需检查IP和端口是否正确)
org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: connect timed out
at org.apache.thrift.transport.TSocket.open(TSocket.java:226)
at com.emaxcard.ThriftTest.main(ThriftTest.java:30)
Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at org.apache.thrift.transport.TSocket.open(TSocket.java:221)
... 1 more
■ org.apache.thrift.transport.TTransportException: java.net.ConnectException: Connection refused: connect
连接被拒绝
- 服务端服务停止,客户端无法建立soket连接,最终会出现这个TTransportException异常。
- 我TSocket指定的是192.168.40.212的9898端口,在212上通过lsof -i:9898命令发现这个端口并没有开放。也会报这个异常。
注意到这个异常是java.net.ConnectException的Connection refused: connect。由此联想一下当我们发起一个http请求时,如果http接口的服务端是上面两种情况,那么,也会出现这个异常。
org.apache.thrift.transport.TTransportException: java.net.ConnectException: Connection refused: connect
at org.apache.thrift.transport.TSocket.open(TSocket.java:226)
at HelloServiceClient.main(HelloServiceClient.java:26)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at org.apache.thrift.transport.TSocket.open(TSocket.java:221)
... 1 more
■ org.apache.thrift.transport.TTransportException: Cannot write to null outputstream
原因:客户端未调用transport的open()方法,或者open失败了,因socket输出流是null而报TTransportException。一种情况是指定的远程服务的地址(ip+端口)/节点名(zk负载情况下)或服务名压根都不对,必然无法建立socket连接。
■ org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: Read timed out
这个socketTimeout异常就很容易理解了。客户端设置了socketTimeout,而服务端方法未能在这个时间内响应。
TTransport transport = new TSocket("localhost", 9898, socketTimeout, connectTimeout);
示例中我设置socketTimeout=2000,让服务端方法线程sleep3秒,结果就会出现这个异常。监测客户端调用的duration=2027,大于设定的2000。
org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: Read timed out
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:129)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:86)
at org.apache.thrift.protocol.TBinaryProtocol.readAll(TBinaryProtocol.java:425)
at org.apache.thrift.protocol.TBinaryProtocol.readI32(TBinaryProtocol.java:321)
at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:225)
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:77)
at com.zhanggz.test.rpc.service.AgentPayService$Client.recv_apply(AgentPayService.java:61)
at com.zhanggz.test.rpc.service.AgentPayService$Client.apply(AgentPayService.java:48)
at HelloServiceClient.main(HelloServiceClient.java:36)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:235)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:275)
at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:127)
... 8 more
■ org.apache.thrift.transport.TTransportException
我在demo里如下2种调用rpc方法的情况报了这个异常。
- 客户端指向本机127.0.0.1的8080端口,在调用rpc方法时,报如下异常。因为本机Tomcat的8080端口虽然存在,但并未暴露所指定的thrift服务。
org.apache.thrift.transport.TTransportException
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:132)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:86)
at org.apache.thrift.protocol.TBinaryProtocol.readStringBody(TBinaryProtocol.java:379)
at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:236)
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:77)
at com.zhanggz.test.rpc.service.AgentPayService$Client.recv_apply(AgentPayService.java:61)
at com.zhanggz.test.rpc.service.AgentPayService$Client.apply(AgentPayService.java:48)
at HelloServiceClient.main(HelloServiceClient.java:36)
- 服务端协议层使用的传输格式是TMultiplexedProtocol,而client端调用时指定的是TCompactProtocol,在调用rpc方法时出现了异常。
org.apache.thrift.transport.TTransportException
at org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:132)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:86)
at org.apache.thrift.transport.TFramedTransport.readFrame(TFramedTransport.java:132)
at org.apache.thrift.transport.TFramedTransport.read(TFramedTransport.java:100)
at org.apache.thrift.transport.TTransport.readAll(TTransport.java:86)
at org.apache.thrift.protocol.TCompactProtocol.readByte(TCompactProtocol.java:637)
at org.apache.thrift.protocol.TCompactProtocol.readMessageBegin(TCompactProtocol.java:505)
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:77)
at com.emaxcard.route.thrift.TBatchPayQueryService$Client.recv_batchPayQuery(TBatchPayQueryService.java:61)
at com.emaxcard.route.thrift.TBatchPayQueryService$Client.batchPayQuery(TBatchPayQueryService.java:48)
at com.emaxcard.ThriftTest.main(ThriftTest.java:43)
■ org.apache.thrift.TApplicationException: Internal error processing *方法名*
当服务端出现未经捕获的异常时,客户端会收到这个异常。
这就要求thrift接口服务端一定要规避异常的抛出。
org.apache.thrift.TApplicationException: Internal error processing apply
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:79)
at com.zhanggz.test.rpc.service.AgentPayService$Client.recv_apply(AgentPayService.java:61)
at com.zhanggz.test.rpc.service.AgentPayService$Client.apply(AgentPayService.java:48)
at HelloServiceClient.main(HelloServiceClient.java:35)
■ org.apache.thrift.TApplicationException: *方法名* failed: unknown result
当服务端响应值为null时,客户端会收到这个异常。其中,TApplicationException是TException的一个派生类。
这就要求thrift接口服务端是不允许返回null的。
org.apache.thrift.TApplicationException: apply failed: unknown result
at com.zhanggz.test.rpc.service.AgentPayService$Client.recv_apply(AgentPayService.java:65)
at com.zhanggz.test.rpc.service.AgentPayService$Client.apply(AgentPayService.java:48)
at HelloServiceClient.main(HelloServiceClient.java:35)
■ org.apache.thrift.TApplicationException: Invalid method name: '*方法名*'
字面意思来理解是:客户端调用的远程方法,服务端并未暴露出来,导致这个异常。
实际上是什么情况呢?因为一个interface的方法默认都是public的,所以并不存在一个interface的某个方法不能被访问。之所以抛出这个异常,实际上是客户端所调用的thrift接口.Client实例,服务端并未暴露thrift接口.Processor。
见如下这种情况:
服务端暴露的接口(Processor):TProcessor tprocessor = new AgentPayService.Processor<AgentPayService.Iface>(new AgentPayServiceImpl());
---么么哒(incaseof 服务端提供的thrift接口jar包里有AgentPayService和HelloService)---
客户端调用的接口(Client): HelloService.Client client = new HelloService.Client(protocol);
又见如下这种情况:
thrift接口定义了方法,但是服务端实现类并未实现这个方法。 (我们现在的项目是thrfit接口单独放在一个jar里,当给某个接口新加了方法后,server端没有获取最新jar是不会报错的,而这时如果client端获取最新jar了,那么在rpc调用时就会出现这个异常)
org.apache.thrift.TApplicationException: Invalid method name: 'helloString'
at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:79)
at com.zhanggz.test.rpc.service.HelloService$Client.recv_helloString(HelloService.java:61)
at com.zhanggz.test.rpc.service.HelloService$Client.helloString(HelloService.java:48)
at HelloServiceClient.main(HelloServiceClient.java:36)
■ org.apache.thrift.protocol.TProtocolException: Required field '***' was not present!
thrift定义了参数为required。而程序在请求或返回时未对其赋值,会出现这个异常。
struct BatchPayQueryResponseVO{
/**返回码*/
1: required i32 responseCode; ~~~
~~~ /**上游渠道paymentId*/
9:required string channelPaymentId;
org.apache.thrift.protocol.TProtocolException: Required field 'channelPaymentId' was not present! Struct: BatchPayQueryResponseVO(responseCode:1002, responseMsg:渠道处理失败, payStatus:null, payStatusText:null, paymentId:32300, amount:0, fee:0, bankSerTime:null, channelPaymentId:null, channelBatchId:null, pyerBankSerialNo:null, pyeeBankSerialNo:null)
at com.emaxcard.route.thrift.quickpay.BatchPayQueryResponseVO.validate(BatchPayQueryResponseVO.java:1292) ~[gateway_thrift-1.0-SNAPSHOT.jar:?]
at com.emaxcard.route.thrift.quickpay.TBatchPayQueryService$batchPayQuery_result.validate(TBatchPayQueryService.java:856) ~[gateway_thrift-1.0-SNAPSHOT.jar:?]
at com.emaxcard.route.thrift.quickpay.TBatchPayQueryService$batchPayQuery_result$batchPayQuery_resultStandardScheme.write(TBatchPayQueryService.java:915) ~[gateway_thrift-1.0-SNAPSHOT.jar:?]
at com.emaxcard.route.thrift.quickpay.TBatchPayQueryService$batchPayQuery_result$batchPayQuery_resultStandardScheme.write(TBatchPayQueryService.java:882) ~[gateway_thrift-1.0-SNAPSHOT.jar:?]
at com.emaxcard.route.thrift.quickpay.TBatchPayQueryService$batchPayQuery_result.write(TBatchPayQueryService.java:833) ~[gateway_thrift-1.0-SNAPSHOT.jar:?]
at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:57) ~[libthrift-0.11.0.jar:0.11.0]
at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:39) ~[libthrift-0.11.0.jar:0.11.0]
at org.apache.thrift.TMultiplexedProcessor.process(TMultiplexedProcessor.java:134) ~[libthrift-0.11.0.jar:0.11.0]
at org.apache.thrift.server.AbstractNonblockingServer$FrameBuffer.invoke(AbstractNonblockingServer.java:518) [libthrift-0.11.0.jar:0.11.0]
at org.apache.thrift.server.Invocation.run(Invocation.java:18) [libthrift-0.11.0.jar:0.11.0]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_181]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_181]
■ NPE
原因:thrift服务端可能停了
☞ Stay Hungry,Stay Foolish. 如果对阁下有帮助,就动动手指,点一下“推荐”哟~
thrift常见异常及原因分析(updating)的更多相关文章
- 【FAQ】接入HMS Core推送服务,服务端下发消息常见错误码原因分析及解决方法
HMS Core推送服务支持开发者使用HTTPS协议接入Push服务端,可以从服务器发送下行消息给终端设备.这篇文章汇总了服务端下发消息最常见的6个错误码,并提供了原因分析和解决方法,有遇到类似问题的 ...
- Nodejs通过Thrift操作hbase卡住原因分析及与javascript的垃圾回收机制的关系
在最近使用Nodejs通过Thrift操作hbase的时候写了个脚本,不断发送http请求,从而取得hbase下所需的数据,但是在run的过程中for循环并没有执行完全,在执行一部分后会卡住,就再也进 ...
- 常见 core dump 原因分析signal 11 - SIGSEGV
signal 6 - SIGABRT free 多次 char *p = malloc(100); free(p); free(p); fclose 多次 // fclose 内部调用 free FI ...
- 【FAQ】应用内支付服务无法拉起支付页面常见原因分析和解决方法
华为应用内支付服务(In-App Purchases)通过简便的接入流程为用户提供良好的应用内支付体验,然而在实际接入过程中,有一些开发者反馈测试时会无法正常拉起支付页面,下文将详细分析问题出现的5种 ...
- 1.Android常见异常:android.view.WindowLeaked 分析以及解决办法
在项目中遇到WindowManager: Activity has leaked window问题,其实在stackoverflow.com可以找到详细答案:http://stackoverflow ...
- 修改List报ConcurrentModificationException异常原因分析
使用迭代器遍历List的时候修改List报ConcurrentModificationException异常原因分析 在使用Iterator来迭代遍历List的时候如果修改该List对象,则会报jav ...
- struts2.1.8+hibernate2.5.6+spring3.0(ssh2三大框架)常见异常原因和解决方案
---------------------------------------------------------------------------------------------------- ...
- PHPWAMP自启异常,服务器重启后Apache等服务不会自动重启的原因分析
在使用“PHPWAMP自动任务”时,不少学生遇到如下问题: “phpwamp绿色集成环境重启动电脑(服务器)后,不会自动启动网站服务” (如果是其他环境或是自己搭建时遇到此问题,也是可以用此法解决) ...
- 2019.12.11 java程序中几种常见的异常以及出现此异常的原因
1.java.lang.NullpointerException(空指针异常) 原因:这个异常经常遇到,异常的原因是程序中有空指针,即程序中调用了未经初始化的对象或者是不存在的对象. 经常出现在创建对 ...
随机推荐
- 【工具】idea工具 java代码 gbk转utf8
idea工具 https://github.com/downgoon/gbk2utf8 安装在目录下: /usr/local/gbk2utf8/bin 进入目录后直接执行 gbk2utf8 sourc ...
- python全栈开发day110-Flask基础语法
1.Flask 初识: 短小精悍,三方支持的组件多 稳定性较差 2.三行 :启动flask服务 from flask import Flask app = Flask(__name__) app.ru ...
- linux添加新磁盘
先fdisk -l 看一下有哪些没有挂载的盘符. 然后将创建的文件夹与待挂载的盘符绑定,即:mount /dev/vdc /data
- sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') #改变标准输出的默认编码
不论使用urllib还是使用requests库经常会遇到中文编码错误的问题,我就经常遇到,因为python安装在windows平台上,cmd的默认编码为GBK,所以在cmd中显示中文时会经常提示gbk ...
- 一天带你入门到放弃vue.js(二)
接下来我们继续学习一天带你入门到放弃系列vue.js(二),如有问题请留言讨论! v-if index.html <div id="app"> <p v-if=& ...
- vue加载优化策略
vue.js是一个比较流行的前端框架,与react.js.angular.js相比来说,vue.js入手曲线更加流畅,不管掌握多少都可以快速上手.但是单页面应用也都有其弊病,有时候首屏加载慢的让人捏舌 ...
- rabbitmq-cluster搭建
一.前期准备: 准备3台linux系统,配置好公司源,或者官网下载相应的网络源 1.条件:准备3台linux系统,确保能连到download.yunwei.edu 2.编写yum源下载脚本: #vim ...
- .Net简单工厂模式,工厂模式,抽象工厂模式实例
1.定义 简单工厂模式:是由一个工厂对象决定创建出哪一种产品类的实例.简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现. 工厂模式:定义一个用于创建对象的接口, ...
- Beta(2/7)
鐵鍋燉腯鱻 项目:小鱼记账 团队成员 项目燃尽图 冲刺情况描述 站立式会议照片 各成员情况 团队成员 学号 姓名 git地址 博客地址 031602240 许郁杨 (组长) https://githu ...
- CSS文字垂直居中的一些问题
说到CSS文字垂直居中,很多初学者都喜欢用调整行高等于div高度的方式来达到效果, div { height:30px; line-height:30px; } 但其实这么做会遇到一个问题:多行文本溢 ...