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需要配置多个连接池。