不可否认ice在跨平台rpc中有很高的历史历史地位,但是随着Dubbo,protobuf,ws协议的越来越成熟,ice被淘汰已经不可避免,最近项目要用到ice,翻看了很多实现。觉得ice对于未来可优化空间,已经被ws restful 模式挤压待进,现阶段duboo剩下的优势除了可监控以及分布式集群优势,protobuf序列化优势外,这种高可见性rpc已经看不到好多的使用价值了。(个人浅见),下面帖一个ice 3.6+客户端优化工具类实现。
package com.launch.lc_ice_pas.utils; import Ice.Communicator; import Ice.ObjectPrx; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * ice use side register service */ public class IceClientUtil { //连接实体实例。 private static volatile Communicator communicator = null; //存放代理实例的集合。 private static Map<Class, ObjectPrx> classObjectPrxMap = new HashMap<>(); //最有一次使用使用communicator的时间。 private static volatile long lastAccessTimeTarge; //子线程控制communicator的销毁。 private static volatile MonitorThread thread1; //100秒不调用就销毁communicator private static long idleTimeOutSeconds = 100; //静态属性需要进行读取这是需要连接的网址与ip以及连接方式的值 如 Default -h ... -p ...或IceGrid/Locator:tcp -h -p /** * 这里仅给还需要用到ice的同事留一个意见参考。 * @return */ public static Communicator getIceCommunictor() { if (communicator == null) { synchronized (IceClientUtil.class) { if (communicator == null) { Ice.InitializationData initData = new Ice.InitializationData(); //set properties ice communicator Ice.Properties props = Ice.Util.createProperties(); //props.setProperty("Ice.Warn.Connections", "0");关闭网络连接与追踪 //props.setProperty("Ice.Trace.Protocol", "0");关闭网络连接与追踪 props.setProperty("Ice.ThreadPool.Client.Size", "10"); props.setProperty("Ice.ThreadPool.Client.SizeMax", "30"); props.setProperty("Ice.ThreadPool.Client.SizeWarn", "20"); initData.properties = props; communicator = Ice.Util.initialize(initData); createMonitorThread(); } } } lastAccessTimeTarge = System.currentTimeMillis(); return communicator; } /** * 监管communicator ,因为他过去重,当不使用的时候关闭,如果不要关闭,则可不写节省1m线程内存 * @param removeIf */ public static void closeCommunicator(boolean removeIf) { synchronized (IceClientUtil.class) { if (communicator != null) { safaShuatdown(); thread1.interrupt(); if (removeIf && !classObjectPrxMap.isEmpty()) { classObjectPrxMap.clear(); } } } } private static void safaShuatdown() { communicator.shutdown(); communicator.destroy(); communicator = null; } /** * * 这个方法封装的并不是特别好,3.5的时候communicator可以带地址与端口创建adapter适配 * 3.6已经不行了, * @param serviceCls pre class * @return * @throws IllegalAccessException */ public static ObjectPrx getServicePrx(String address, Class serviceCls) { ObjectPrx proxy = classObjectPrxMap.get(serviceCls); if (proxy != null) { lastAccessTimeTarge = System.currentTimeMillis(); return proxy; } Communicator com = getIceCommunictor(); proxy = createIceProxy(address, com, serviceCls); classObjectPrxMap.put(serviceCls, proxy); lastAccessTimeTarge = System.currentTimeMillis(); return proxy; } /** * * * @param ic1 have init communicator * @param serviceCls will create object prx * @return * @throws IllegalAccessException */ private static ObjectPrx createIceProxy(String address, Communicator ic1, Class serviceCls) { ObjectPrx prx = null; // String claName = serviceCls.getName();//get the object path ObjectPrx base = ic1.stringToProxy(address);//register Proxy name try { /** * 在这里具体ObjectHelper都属于ObjectPrx的子类但是父类中没有 * cast的方法,所以在实体中取得所有的方法,即unchecekeCast,正常情况下我们是用的checkcast进行代理。 * checkcast为需要检查接收的对象需要制定对象接收并转化。 * 但是里面直接转换的过程中,我自己重写了方法之后进行转换报转化异常错误。 * 在其cast方法中,catch异常之后,使用uncheckecast进行强制转化,需要注入hepler以及prx,返回到checkcast中 * 在放回到正常代理。 * 且这里不能使用具体的类型进行强制转化接收,所以需要使用uncheckeedcast。强制转化为Objectprx接口进行接收 * 并转回你自己调用的地方。 */ prx = (ObjectPrx) Class.forName(claName + "Helper").newInstance();//get zhe Helper Method m1 = null; m1 = prx.getClass().getDeclaredMethod("uncheckedCast", ObjectPrx.class); prx = (ObjectPrx) m1.invoke(prx, base); return prx; } catch (Exception e) { e.printStackTrace(); } return prx; } /** * this place use it to destroy communicator */ private static void createMonitorThread() { thread1 = new MonitorThread(); thread1.setDaemon(true); thread1.start(); } static class MonitorThread extends Thread { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { try { Thread.sleep(10000); if (lastAccessTimeTarge + idleTimeOutSeconds * 1000 < System.currentTimeMillis()) { closeCommunicator(true); } } catch (InterruptedException e) { e.printStackTrace(); } } } } }