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

来源:互联网 发布:淘宝的所在地怎么修改 编辑:程序博客网 时间:2024/06/01 09:33

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

github项目地址:

github项目地址

本文介绍的是多服务的调用与使用动态代理进行透明化调用

因为每次调用方法时都要对transport (io/socket 资源) 进行开启关闭,所以就想设计client 代理起来,然后在前后添加 transport 的open 和 close() (finally);

当然之后在研究自己写一款thrift的连接池,因为io资源不一定每次都需要创建!!!

thrift 版本号 0.10.0

thrift 文件:
IThriftInfoTestService.thriftIThriftTestService.thrift
IThriftInfoTestService.thrift

代码:

namespace java com.java.thrift.servicenamespace cpp com.java.thrift.servicenamespace perl com.java.thrift.servicenamespace php com.java.thrift.serviceservice  IThriftInfoTestService {  string showInfoData(1:string name,2:bool b2,3:map<string,string> m2)}
IThriftTestService.thrift

代码:

namespace java com.java.thrift.servicenamespace cpp com.java.thrift.servicenamespace perl com.java.thrift.servicenamespace php com.java.thrift.serviceservice  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..等)
0 0
原创粉丝点击