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