thrift 使用 TFramedTransport 分层传输协议.如何获取客户端IP?报错-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

thrift 使用 TFramedTransport 分层传输协议.如何获取客户端IP?报错

爱吃鱼的程序员 2020-06-09 14:12:11 174

服务端:

  

TNonblockingServerSocket serverTransport = new TNonblockingServerSocket(new InetSocketAddress("0.0.0.0", port), timeout);
 THsHaServer.Args trArgs = new THsHaServer.Args(serverTransport);
 /**TTransport协议类型参见thrift.txt文件 */
 trArgs.protocolFactory(new TCompactProtocol.Factory());
 trArgs.transportFactory(new TFramedTransport.Factory());
 trArgs.processorFactory(new TProcessorFactory(new LogProcessor(processor)));
 server = new THsHaServer(trArgs);
 Executors.newSingleThreadExecutor().execute(new Runnable() {
 @Override
 public void run() {
 server.serve(); //启动服务
 }
 });



LogProcessor:

public class LogProcessor implements TProcessor {

	private Logger logger = Logger.getLogger("access");
	
	 private TProcessor processor;  
     
    public LogProcessor(TProcessor processor)  
    {  
        this.processor = processor;  
    } 
    
	 /** 
     * 该方法,客户端每调用一次,就会触发一次 
     */ 
	@Override
	public boolean process(TProtocol in, TProtocol out) throws TException {
		  
		 /** 
         * 从TProtocol里面获取TTransport对象 
         * 把TTransport对象转换成TSocket,然后在TSocket里面获取Socket,就可以拿到客户端IP 
         */  
		TSocket socket = (TSocket)in.getTransport();  
	   SocketAddress clientIp = socket.getSocket().getRemoteSocketAddress();
	   logger.info("接收到来至[" + clientIp + "]的请求.");
	   return processor.process(in, out);
	}

}



 

TSocket socket = (TSocket)in.getTransport();   强转会报错。

in.getTransport() 得到的是TFramedTransport


错误信息:

11:35:25,941 [pool-1-thread-1] ERROR (org.apache.thrift.server.AbstractNonblockingServer$FrameBuffer.java:524) - Unexpected throwable while invoking!
java.lang.ClassCastException: org.apache.thrift.transport.TFramedTransport cannot be cast to org.apache.thrift.transport.TSocket
at com.retail.wst.thrift.monitor.LogProcessor.process(LogProcessor.java:48)
at org.apache.thrift.server.AbstractNonblockingServer$FrameBuffer.invoke(AbstractNonblockingServer.java:518)
at org.apache.thrift.server.Invocation.run(Invocation.java:18)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)


Java
分享到
取消 提交回答
全部回答(1)
  • 爱吃鱼的程序员
    2020-06-09 14:12:27

    可以通过TServerEventHandler获取到.

    给你一段代码,不清楚的可以追问:

    importjava.net.Socket;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;importorg.apache.thrift.protocol.TProtocol;importorg.apache.thrift.transport.TSocket;importorg.apache.thrift.server.ServerContext;importorg.apache.thrift.server.TServerEventHandler;importorg.apache.thrift.transport.TTransport;/***Thrift调用监控事件**仅打印连接信息日志.**@author<a*@version0.1*/publicclassMonitorServerEventHandlerimplementsTServerEventHandler{privatestaticfinalLogLOG=LogFactory.getLog(MonitorServerEventHandler.class);@OverridepublicServerContextcreateContext(TProtocolarg0,TProtocolarg1){if(arg0!=null&&arg0.getTransport()!=null){Socketsocket=((TSocket)arg0.getTransport()).getSocket();LOG.info("[Monitor]ThriftServerSocketInfo:server地址:"+socket.getLocalAddress()+",server端口:"+socket.getLocalPort()+",client地址:"+socket.getInetAddress()+",client端口:"+socket.getPort());}returnnull;}@OverridepublicvoiddeleteContext(ServerContextarg0,TProtocolarg1,TProtocolarg2){}@OverridepublicvoidpreServe(){}@OverridepublicvoidprocessContext(ServerContextarg0,TTransportarg1,TTransportarg2){}}



    引用来自“LarrySu”的评论

    可以通过TServerEventHandler获取到.

    给你一段代码,不清楚的可以追问:

    importjava.net.Socket;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;importorg.apache.thrift.protocol.TProtocol;importorg.apache.thrift.transport.TSocket;importorg.apache.thrift.server.ServerContext;importorg.apache.thrift.server.TServerEventHandler;importorg.apache.thrift.transport.TTransport;/***Thrift调用监控事件**仅打印连接信息日志.**@author<a*@version0.1*/publicclassMonitorServerEventHandlerimplementsTServerEventHandler{privatestaticfinalLogLOG=LogFactory.getLog(MonitorServerEventHandler.class);@OverridepublicServerContextcreateContext(TProtocolarg0,TProtocolarg1){if(arg0!=null&&arg0.getTransport()!=null){Socketsocket=((TSocket)arg0.getTransport()).getSocket();LOG.info("[Monitor]ThriftServerSocketInfo:server地址:"+socket.getLocalAddress()+",server端口:"+socket.getLocalPort()+",client地址:"+socket.getInetAddress()+",client端口:"+socket.getPort());}returnnull;}@OverridepublicvoiddeleteContext(ServerContextarg0,TProtocolarg1,TProtocolarg2){}@OverridepublicvoidpreServe(){}@OverridepublicvoidprocessContext(ServerContextarg0,TTransportarg1,TTransportarg2){}}



    引用来自“LarrySu”的评论

    可以通过TServerEventHandler获取到.

    给你一段代码,不清楚的可以追问:

    importjava.net.Socket;importorg.apache.commons.logging.Log;importorg.apache.commons.logging.LogFactory;importorg.apache.thrift.protocol.TProtocol;importorg.apache.thrift.transport.TSocket;importorg.apache.thrift.server.ServerContext;importorg.apache.thrift.server.TServerEventHandler;importorg.apache.thrift.transport.TTransport;/***Thrift调用监控事件**仅打印连接信息日志.**@author<a*@version0.1*/publicclassMonitorServerEventHandlerimplementsTServerEventHandler{privatestaticfinalLogLOG=LogFactory.getLog(MonitorServerEventHandler.class);@OverridepublicServerContextcreateContext(TProtocolarg0,TProtocolarg1){if(arg0!=null&&arg0.getTransport()!=null){Socketsocket=((TSocket)arg0.getTransport()).getSocket();LOG.info("[Monitor]ThriftServerSocketInfo:server地址:"+socket.getLocalAddress()+",server端口:"+socket.getLocalPort()+",client地址:"+socket.getInetAddress()+",client端口:"+socket.getPort());}returnnull;}@OverridepublicvoiddeleteContext(ServerContextarg0,TProtocolarg1,TProtocolarg2){}@OverridepublicvoidpreServe(){}@OverridepublicvoidprocessContext(ServerContextarg0,TTransportarg1,TTransportarg2){}}



    还有一个办法,但比较恶心:


    复制TFramedTransport.java的源代码新建一个类TFramedTransport2.java.
    将代码"privateTTransporttransport_=null;"改为"publicTTransporttransport_=null;".
    其它调用的地方都用TFramedTransport2.java.
    然后通过
    TSocketsocket=(TSocket)((TFramedTransport2)in.getTransport()).transport_; 
    获取TSocket对象.

    引用来自“LarrySu”的评论

    还有一个办法,但比较恶心:


    复制TFramedTransport.java的源代码新建一个类TFramedTransport2.java.
    将代码"privateTTransporttransport_=null;"改为"publicTTransporttransport_=null;".
    其它调用的地方都用TFramedTransport2.java.
    然后通过
    TSocketsocket=(TSocket)((TFramedTransport2)in.getTransport()).transport_; 
    获取TSocket对象.

    你用本地内存方式,而的不是socket方式调用吗?

    引用来自“LarrySu”的评论

    还有一个办法,但比较恶心:


    复制TFramedTransport.java的源代码新建一个类TFramedTransport2.java.
    将代码"privateTTransporttransport_=null;"改为"publicTTransporttransport_=null;".
    其它调用的地方都用TFramedTransport2.java.
    然后通过
    TSocketsocket=(TSocket)((TFramedTransport2)in.getTransport()).transport_; 
    获取TSocket对象.

    引用来自“LarrySu”的评论

    还有一个办法,但比较恶心:


    复制TFramedTransport.java的源代码新建一个类TFramedTransport2.java.
    将代码"privateTTransporttransport_=null;"改为"publicTTransporttransport_=null;".
    其它调用的地方都用TFramedTransport2.java.
    然后通过
    TSocketsocket=(TSocket)((TFramedTransport2)in.getTransport()).transport_; 
    获取TSocket对象.

    引用来自“小乞丐”的评论

    引用来自“LarrySu”的评论

    还有一个办法,但比较恶心:


    复制TFramedTransport.java的源代码新建一个类TFramedTransport2.java.
    将代码"privateTTransporttransport_=null;"改为"publicTTransporttransport_=null;".
    其它调用的地方都用TFramedTransport2.java.
    然后通过
    TSocketsocket=(TSocket)((TFramedTransport2)in.getTransport()).transport_; 
    获取TSocket对象.

    如果你坚持要使用THsHaServer服务,那么这个也要复制一份.eg:publicclassWstTHsHaServerextendsWstTNonblockingServer
    0 0
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

推荐文章
相似问题
推荐课程