Thrift RPC實戰(六) spring集成thrift 原

1.服務端設置

通過採用spring配置以及反射的方式來實現.對於一個服務提供者來說,需要提供端口,接口以及接口實現類,因此在接口中spring配置文件中配置如下

<!-- 服務代理列表 -->
<util:list id="serverProxyList">
      <ref bean="resourceMgtProxy" />
</util:list>
<!-- 資源管理 -->
<bean id="resourceMgtServer" class="com.nari.rpc.server.ResourceMgtServer" />
<bean id="resourceMgtProxy" class="com.nari.proxy.RpcServerProxy">
    <property name="port" value="1002"/>
    <property name="serviceInterface" value="com.nari.api.resource.rpc.ResourceMgtRpc"/>
    <property name="serviceImplObject" ref="resourceMgtServer"/>
</bean>

接下來定義ThriftServerProxy類,定義bean中需要用到的3個屬性,接下來通過反射來實現服務的啓動。

public class RpcServerProxy {

    // 端口
    private int port;

    // 服務接口
    private String serviceInterface;

    //服務實現類
    private Object serviceImplObject;

    /**
     * 啓動RPC服務
     */
    public void start() {
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        cachedThreadPool.execute(() -> {
            try {
                TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(getPort());
                Class processor = Class.forName(getServiceInterface() + "$Processor");
                Class face = Class.forName(getServiceInterface() + "$Iface");
                Constructor con = processor.getConstructor(face);
                TProcessor tProcessor = (TProcessor) con.newInstance(serviceImplObject);
                TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory(true, true);
                TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args(serverTransport);
                args.protocolFactory(factory);
                args.processor(tProcessor);
                TServer server = new TThreadedSelectorServer(args);
                // 啓動服務
                server.serve();
            } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException
                    | InvocationTargetException | TTransportException e) {
                e.printStackTrace();
            }
        });
    }

    public Object getServiceImplObject() {
        return serviceImplObject;
    }

    public void setServiceImplObject(Object serviceImplObject) {
        this.serviceImplObject = serviceImplObject;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public String getServiceInterface() {
        return serviceInterface;
    }

    public void setServiceInterface(String serviceInterface) {
        this.serviceInterface = serviceInterface;
    }
}

配置監聽啓動服務

**
 * 服務啓動監聽器
 */
public class RpcServerStartListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        try {
            ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
            // 獲取服務代理列表
            List<RpcServerProxy> proxyList = ((List<RpcServerProxy>) context.getBean("serverProxyList"));
            if (!CollectionUtils.isEmpty(proxyList)) {
                // 啓動代理服務
                proxyList.forEach(proxy -> proxy.start());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

最後在web.xml中添加listener即可

2.客戶端配置

對於客戶端,從連接池裏面獲取一個可用的服務端連接,通過反射的方式獲取客戶端,在spring-client.xml中配置如下:

<!-- thrift連接池配置 -->
<bean id="connectionProvider" class="com.nari.common.thrift.pool.impl.ConnectionProviderImpl">
   <property name="serviceIP" value="localhost" />
   <property name="servicePort" value="1002" />
   <property name="maxActive" value="10" />
   <property name="maxIdle" value="10" />
   <property name="testOnBorrow" value="true" />
   <property name="testOnReturn" value="true" />
   <property name="testWhileIdle" value="true" />
   <property name="conTimeOut" value="30000" />
</bean>

<bean id="connectionManager" class="com.nari.common.thrift.pool.ConnectionManager">
   <property name="connectionProvider"  ref="connectionProvider"/>
</bean>

<bean id="thriftClientProxy" class="com.nari.common.thrift.proxy.ThriftClientProxy">
   <property name="connectionManager" ref="connectionManager"/>
</bean>

客戶端的代理對象獲取client代碼:

public class ThriftClientProxy {

    private ConnectionManager connectionManager;

    public ConnectionManager getConnectionManager() {
        return connectionManager;
    }
    public void setConnectionManager(ConnectionManager connectionManager) {
        this.connectionManager = connectionManager;
    }
    public Object getClient(Class clazz) {
        Object result = null;
        try {
            TTransport transport = connectionManager.getSocket();
            TProtocol protocol = new TBinaryProtocol(transport);
            Class client = Class.forName(clazz.getName() + "$Client");
            Constructor con = client.getConstructor(TProtocol.class);
            result = con.newInstance(protocol);
            //transport.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

使用:

ResourceMgtRpc.Iface client = (ResourceMgtRpc.Iface) thriftClientProxy.getClient(ResourceMgtRpc.class);
// 封裝請求參數
QuerySyncStatusRequest requestPo = new QuerySyncStatusRequest();
requestPo.setMasterSourceId(master.getResourceId());
QuerySyncStatusResponse responsePo = client.querySynStatus(requestPo);

當前的不足:
  沒有使用訂閱服務列表, 使得在配置中, 需要指定ip:port列表,如果有多個指定的ip:port需要配置多個連接池。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章