/* * Copyright 2009-2016 Weibo, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.weibo.api.motan.cluster.loadbalance; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import com.weibo.api.motan.common.MotanConstants; import com.weibo.api.motan.core.extension.SpiMeta; import com.weibo.api.motan.rpc.Referer; import com.weibo.api.motan.rpc.Request; import com.weibo.api.motan.util.MathUtil; /** * * Use consistent hash to choose referer * * @author fishermen * @version V1.0 created at: 2013-5-21 */ @SpiMeta(name = "consistent") public class ConsistentHashLoadBalance<T> extends AbstractLoadBalance<T> { private List<Referer<T>> consistentHashReferers; @Override public void onRefresh(List<Referer<T>> referers) { super.onRefresh(referers); List<Referer<T>> copyReferers = new ArrayList<Referer<T>>(referers); List<Referer<T>> tempRefers = new ArrayList<Referer<T>>(); for (int i = 0; i < MotanConstants.DEFAULT_CONSISTENT_HASH_BASE_LOOP; i++) { Collections.shuffle(copyReferers); for (Referer<T> ref : copyReferers) { tempRefers.add(ref); } } consistentHashReferers = tempRefers; } @Override protected Referer<T> doSelect(Request request) { int hash = getHash(request); Referer<T> ref; for (int i = 0; i < getReferers().size(); i++) { ref = consistentHashReferers.get((hash + i) % consistentHashReferers.size()); if (ref.isAvailable()) { return ref; } } return null; } @Override protected void doSelectToHolder(Request request, List<Referer<T>> refersHolder) { List<Referer<T>> referers = getReferers(); int hash = getHash(request); for (int i = 0; i < referers.size(); i++) { Referer<T> ref = consistentHashReferers.get((hash + i) % consistentHashReferers.size()); if (ref.isAvailable()) { refersHolder.add(ref); } } } private int getHash(Request request) { int hashcode; if (request.getArguments() == null || request.getArguments().length == 0) { hashcode = request.hashCode(); } else { hashcode = Arrays.hashCode(request.getArguments()); } return MathUtil.getPositive(hashcode); } }