zeroc 公司ice的3.6+的使用心得

不可否认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, 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();
                }
            }
        }
    }
}

你可能感兴趣的:(zeroc 公司ice的3.6+的使用心得)