dubbo 扩展LoadBalance

public class MyRandomLoadBalance extends RandomLoadBalance {

    private static Logger log = LoggerFactory.getLogger(MyRandomLoadBalance.class);

    @Override
    protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
        if (System.getProperty(url.getServiceInterface()) != null) {
            //直连
            return super.doSelect(invokers, url, invocation);
        }

        List<InvokerHacker<T>> hackedInvokers = new ArrayList<>(invokers.size());
        for (Invoker<T> invoker : invokers) {
            hackedInvokers.add(new InvokerHacker<T>(invoker));
        }
        String envId = null;
        CommonRequest cr = RequestContext.get(RequestContextKey.COMMON_REQUEST, CommonRequest.class);
        if(cr != null && cr.getTraceZone() != null){
            envId = cr.getTraceZone();
        }

        if(StringUtils.isBlank(envId)){
            return super.doSelect(invokers,url,invocation);
        }

        List<Invoker<T>> availableInvokers = new ArrayList<>();
        for(InvokerHacker invokerHacker : hackedInvokers){
            if(invokerHacker.envMatch(envId)){
                availableInvokers.add(invokerHacker);
            }
        }
        if(availableInvokers.isEmpty()){
            log.warn("not found invokers match envId={}",envId);
            availableInvokers = invokers;
        }
        return super.doSelect(availableInvokers, url, invocation);
    }

    /**
     * 默认的Invoker实现是不可见的com.alibaba.dubbo.registry.integration.RegistryDirectory.InvokerDelegate
     * 为了访问providerUrl而加多下面这个
     * @param <T>
     */
    private static class InvokerHacker<T> extends InvokerWrapper<T> {
        private URL providerUrl;

        InvokerHacker(Invoker<T> invoker) {
            super(invoker, invoker.getUrl());
            providerUrl = hackUrl(invoker);
        }
        private <E> URL hackUrl(Invoker<E> invoker) {
            try {
                Field providerUrlField = invoker.getClass().getDeclaredField("providerUrl");
                providerUrlField.setAccessible(true);
                return (URL) providerUrlField.get(invoker);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new IllegalStateException("Could not get providerUrl", e);
            }
        }

        boolean envMatch(String envId) {
            return StringUtils.equals(envId, providerUrl.getParameter("envId"));
        }
    }
}

rt

 

上一篇:Java中自动清理资源的方式(虚引用的作用)


下一篇:Java实现类的重载及使用垃圾回收钩子函数