Thrift 使用以及使用动态代理透明化调用

Thrift 使用以及使用动态代理透明化调用

github项目地址:

github项目地址

本文介绍的是多服务的调用与使用动态代理进行透明化调用
因为每次调用方法时都要对transport (io/socket 资源) 进行开启关闭,所以就想设计client 代理起来,然后在前后添加 transport 的open 和 close() (finally);
当然之后在研究自己写一款thrift的连接池,因为io资源不一定每次都需要创建!!!
thrift 版本号 0.10.0
thrift 文件:
IThriftInfoTestService.thrift
IThriftTestService.thrift
IThriftInfoTestService.thrift

代码:

namespace java com.java.thrift.service
namespace cpp com.java.thrift.service
namespace perl com.java.thrift.service
namespace php com.java.thrift.service

service  IThriftInfoTestService {
  string showInfoData(1:string name,2:bool b2,3:map<string,string> m2)
}
IThriftTestService.thrift

代码:

namespace java com.java.thrift.service
namespace cpp com.java.thrift.service
namespace perl com.java.thrift.service
namespace php com.java.thrift.service

service  IThriftTestService {
  string showThriftResult(1:string name,2:bool b2,3:map<string,string> m2)
}

provider

spring配置文件 spring-thrift.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd    
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd    
            http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd  
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd"
>

    <!-- 两个thrift 服务的实现类 -->
    <bean id="thriftInfoTestServiceTarget" class="com.java.core.rpc.thrift.service.impl.ThriftInfoTestServiceImpl" ></bean>
    <bean id="thriftTestServiceTarget" class="com.java.core.rpc.thrift.service.impl.ThriftTestServiceImpl" ></bean>



    <!-- Processor调用过程工厂,创建多服务类的工厂类  -->
    <bean id="thriftProcessorFactory"  class="com.java.core.rpc.thrift.supports.ThriftProcessorFactory" 
        init-method="convertTargetToTProcessor"
        >
        <property name="targets" >
            <list >
                <ref bean="thriftInfoTestServiceTarget"/>
                <ref bean="thriftTestServiceTarget"/>
            </list>
        </property>

    </bean>

    <!--  thrift 的provider的启动类 -->
    <bean class="com.java.core.rpc.thrift.provider.AppThriftServer" init-method="initThriftServer"  ></bean>


</beans>

ThriftInfoTestServiceImpl.java

package com.java.core.rpc.thrift.service.impl;



import java.util.Map;

import org.apache.thrift.TException;

import com.alibaba.fastjson.JSONObject;
import com.java.core.rpc.thrift.service.IThriftInfoTestService;

public class ThriftInfoTestServiceImpl implements IThriftInfoTestService.Iface {

    @Override
    public String showInfoData(String name, boolean success, Map<String, String> map) throws TException {
        // TODO Auto-generated method stub



        System.out.println(" ThriftInfoTestServiceImpl doing ...showInfoData()... ");
        System.out.println(" map : "+ JSONObject.toJSONString(map));
        System.out.println(" success : "+ success);
        System.out.println(" name : "+ name);
        String result = name +" time : " + System.currentTimeMillis();

        return result;
    }

}

ThriftTestServiceImpl.java 代码就不贴了。都一样
ThriftProcessorFactory.java processor工厂类

public class ThriftProcessorFactory {

    private final static String IFACE_NAME="$Iface";
    private final static String PROCESS_NAME="$Processor";

    private List<Object> targets;
    private Map<String, TProcessor> processors;
    private TMultiplexedProcessor multiplexedProcessor;
    public TMultiplexedProcessor getMultiplexedProcessor() {
        return multiplexedProcessor;
    }


    public void setMultiplexedProcessor(TMultiplexedProcessor multiplexedProcessor) {
        this.multiplexedProcessor = multiplexedProcessor;
    }


    public ThriftProcessorFactory() {
        super();
        // TODO Auto-generated constructor stub
    }


    public Map<String, TProcessor> getProcessors() {
        return processors;
    }


    public void setProcessors(Map<String, TProcessor> processors) {
        this.processors = processors;
    }
    public List<Object> getTargets() {
        return targets;
    }

    public void setTargets(List<Object> targets) {
        this.targets = targets;
    }

    /**
     * 将实现类封装成TProcessor类的集合
     * 
     */
    public void convertTargetToTProcessor(){
        if (targets.isEmpty()) {
            return ;
        }
        processors = new HashMap<String, TProcessor>();
        try {
            for (Object target : targets ) {
                Class iface= target.getClass().getInterfaces()[0];
                String ifaceName =iface.getName();
                String serviceName = ifaceName.substring(0, ifaceName.lastIndexOf(IFACE_NAME));

                Class processorClazz = Class.forName(serviceName.concat(PROCESS_NAME));
                Object processorObj = processorClazz.getConstructor(iface).newInstance(iface.cast(target));
                if (processorObj instanceof TProcessor) {
                    TProcessor processor = (TProcessor) processorObj;
                    processors.put(serviceName, processor);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        initMultiplexedProcessor();
    }

    /**
     * 初始化多服务调用过程 TMultiplexedProcessor 
     * 并且注册服务
     */
    private void initMultiplexedProcessor(){
        if (processors.isEmpty()) {
            return ;
        }
        multiplexedProcessor = new TMultiplexedProcessor();
        Set<String> serviceNames = processors.keySet();
        for (String serviceName : serviceNames) {
            if (!processors.containsKey(serviceName)) {
                continue;
            }
            multiplexedProcessor.registerProcessor(serviceName, processors.get(serviceName));
        }
    }
}
AppThriftServer.java 重点,服务启动

public class AppThriftServer  implements ApplicationContextAware {

    /**线程池**/
    private static ExecutorService executorService;
    // ApplicationContextAware 可以调用spring 生命周期获取上下文
    private static ApplicationContext context;

    public AppThriftServer() {
        super();
        // TODO Auto-generated constructor stub
        executorService = Executors.newSingleThreadExecutor();
    }


    public void initThriftServer(){
        executorService.execute(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                System.out.println(" ThriftServer start ing ....");
                TNonblockingServerSocket transport = null;
                try { 
                    //非阻塞 ServerSocket
                    transport =new TNonblockingServerSocket(new InetSocketAddress(29999));  
                    // 获取 TProcessor 
                    ThriftProcessorFactory thriftProcessorFactory=context.getBean(ThriftProcessorFactory.class);
                    TProcessor processor =thriftProcessorFactory.getProcessor();
                    //  nio selectorThreads处理io,  workerThreads 处理服务调用过程
                    TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args(transport);
                    args.processor(processor);
                    // customer也要TFramedTransport对应 否则报错
                    args.transportFactory(new TFramedTransport.Factory());  
                    //二进制协议  
                    args.protocolFactory(new TBinaryProtocol.Factory());  
                    TThreadedSelectorServer server =new TThreadedSelectorServer(args);
                    server.serve();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (transport != null) {
                        transport.close();
                    }

                }





            }
        });

    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // TODO Auto-generated method stub
        context=applicationContext;
    }

}

接着启动项目,服务端便开始监听;

接着是 customer 客户端

调用主体
public class App 
{

    private static ApplicationContext applicationContext;

    public static void main( String[] args )
    {
        System.out.println( "Hello World!" );
        init();
        final TestService testService=applicationContext.getBean(TestService.class);

        for (int i=0 ;i<10 ;i++) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    testService.doThriftTest();


                }
            }).start();
        }

    }



    public static void init(){

        applicationContext = new FileSystemXmlApplicationContext("/resources/applicationContext.xml"); 

    }
}
TestService.java 中的 doThriftTest() 方法

ThriftServiceProxy 类的静态方法 getThriftClient() 获取接口类实例,在 doThriftTest()方法中是透明化的直接调用



    public void doThriftTest(){

        //运用动态代理 使thrift 接口透明化调用
        IThriftInfoTestService.Iface client =ThriftServiceProxy.getThriftClient(IThriftInfoTestService.Iface.class);
        Map<String, String> map =new HashMap<String, String>();
        map.put("name", "庄杰森");
        map.put("IThriftInfoTestService", "client");
        map.put("content", "thrift 的 rpc 调用");
        String name = "zhuangjiesen ...IThriftInfoTestService doing...";
        try {
            client.showInfoData(name, true, map);
        } catch (TException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
ThriftServiceProxy.java

可以链接 jdk动态代理



public class ThriftServiceProxy {
    //client缓存
    private static ConcurrentHashMap<String,Object> thriftClientCache;

    public static <T> T getThriftClient(Class<T> clazz){
        if (!clazz.isInterface()) {
            throw new RuntimeException("类型错误");
        }
        if (thriftClientCache == null) {
            thriftClientCache = new ConcurrentHashMap<String,Object>();
        }
        T client =null;
        String cacheKey = clazz.getName();
        if (thriftClientCache.containsKey(cacheKey)) {
            client=(T)thriftClientCache.get(cacheKey);
        } else {
            //运用jdk代理方式实现接口类的方法,并且调用 同时 transport 资源通过代理进行close与open 简化代码-->类比事务实现
            ThriftServiceProxyInvocation proxyInvocation =new ThriftServiceProxyInvocation();
            proxyInvocation.setIfaceClazz(clazz);
            client = (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{ clazz }, proxyInvocation);
            if (client != null) {
                thriftClientCache.put(cacheKey, client);
            }
        }
        return client;  
    }

}
ThriftServiceProxyInvocation.java 重点类

初学的因为每次调用方法时都要对transport (io资源) 进行开启关闭,所以就想设计将io资源代理起来可以直接透明调用;此处还用了反射方法

之后研究连接池时,也需要用到动态代理;


public class ThriftServiceProxyInvocation implements InvocationHandler {

    private final static String IFACE_NAME="$Iface";
    private final static String CLIENT_NAME="$Client";
    private Class ifaceClazz;

    public Class getIfaceClazz() {
        return ifaceClazz;
    }
    public void setIfaceClazz(Class ifaceClazz) {
        this.ifaceClazz = ifaceClazz;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println(" ThriftServiceProxyInvocation  invoke doing before ....");
        if (ifaceClazz == null) {
            return null;
        }
        TTransport transport = null;
        Object result = null;
        try {

             // 设置调用的服务地址为本地,端口 
            transport = new TSocket("127.0.0.1", 29999); 
            TFramedTransport framedTransport =new TFramedTransport(transport);
            TBinaryProtocol binaryProtocol =new TBinaryProtocol(framedTransport);
            TMultiplexedProtocol multiplexedProtocol =new TMultiplexedProtocol(binaryProtocol, IThriftInfoTestService.class.getName());
            transport.open();

            String ifaceName =ifaceClazz.getName();
            String className = ifaceName.substring(0, ifaceName.lastIndexOf(IFACE_NAME));
            String clientName = className.concat(CLIENT_NAME);
            Class clientClazz = Class.forName(clientName);


            //构造方法实例化 对应   Hello.Client client = new Hello.Client(protocol); 
            Object clientInstance= clientClazz.getConstructor(TProtocol.class).newInstance(multiplexedProtocol);
            result=method.invoke(clientInstance, args);
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            if (transport != null) {
                transport.close();
            }
        }

        System.out.println(" ThriftServiceProxyInvocation  invoke doing after ....");

        return result;
    }

}

因为是rpc 框架,又看了dubbo 框架的实现,所有这个thrift 还可以进行根据业务深度的封装(注册中心,多服务端,多客户端,monitor..等)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值