使用集群,比如zk來控制註冊中心,當乙個服務有多個請求位址的時候,會返回多個位址。
那麼就需要負載均衡來控制我們要請求哪台機器來得到請求。
方案一:隨機
傳入key值和key所包含的ip位址值,該位址值存入treeset中(有序儲存)
獲得treeset的長度,然後隨機得到其索引,挑出隨機的乙個。
public string route(string servicekey, treesetaddressset)
方案二:輪詢
treeset中的位址值存入乙個陣列中,並設定乙個map集合來記錄該函式呼叫了幾次,每次呼叫,就將索引加1,然後返回該索引的位址值。這樣就會按照treeset中的順序依次選取請求位址。
private concurrenthashmaproutecounteachjob = new concurrenthashmap();private
long cache_valid_time = 0;
private
intcount(string servicekey)
//count++
integer count =routecounteachjob.get(servicekey);
count = (count==null || count>1000000)?(new random().nextint(100)):++count; //
初始化時主動random一次,緩解首次壓力
routecounteachjob.put(servicekey, count);
system.out.println("count:"+count);
return
count;
}@override
public string route(string servicekey, treesetaddressset)
方案三: lru(最近最少使用排程演算法)
每次使用了每個節點的時候,就將該節點放置在最後面,這樣就保證每次使用的節點都是最近最久沒有使用過的節點,當節點數大於最大空間的時候,就直接將前面的節點刪掉。
實現:使用linkedhashmap來實現。它內部有乙個雙向鍊錶在維護
public string doroute(string servicekey, treesetaddressset)//init lru
linkedhashmaplruitem =joblrumap.get(servicekey);
if (lruitem == null
) else}};
joblrumap.putifabsent(servicekey, lruitem);
}//put
for(string address: addressset)
}//load
string eldestkey =lruitem.entryset().iterator().next().getkey();
string eldestvalue = lruitem.get(eldestkey);//
lru演算法關鍵體現在這裡,實現了固定長度的lru演算法
return
eldestvalue;
}
方案四:lfu(訪問最頻繁的使用概率也最高),因此,將使用最頻繁的放在最後面使用,保證了使用不頻繁的也能使用上
hashmap的存放是無序的。
public string doroute(string servicekey, treesetaddressset)//lfu item init
hashmaplfuitemmap = joblfumap.get(servicekey); //
key排序可以用treemap+構造入參compare;value排序暫時只能通過arraylist;
if (lfuitemmap == null
)
for(string address: addressset)
}//load least userd count address
list> lfuitemlist = new arraylist>(lfuitemmap.entryset());
collections.sort(lfuitemlist,
new comparator>()
});system.out.println(lfuitemlist);
map.entry
addressitem = lfuitemlist.get(0);
string minaddress =addressitem.getkey();
addressitem.setvalue(addressitem.getvalue() + 1);
return
minaddress;
//return null;
}
方案五:一致性雜湊
consistent hashing 是一種 hash 演算法,簡單的說,在移除 / 新增乙個 cache 時,它能夠盡可能小的改變已存在 key 對映關係,盡可能的滿足單調性的要求。
每個節點設定5個虛擬節點
計算servicekey的hash值
使用treemap的tailmap方法返回其鍵大於或等於fromkey的部分檢視
取檢視的第乙個作為服務呼叫的address
privateint virtual_node_num = 5;
/*** get hash code on 2^32 ring (md5雜湊的方式計算hash值)
* @param
key *
@return
*/private
long
hash(string key)
catch
(nosuchalgorithmexception e)
md5.reset();
byte keybytes = null
;
try
catch
(unsupportedencodingexception e)
md5.update(keybytes);
byte digest =md5.digest();
//hash code, truncate to 32-bits
long hashcode = ((long) (digest[3] & 0xff) << 24)
| ((long) (digest[2] & 0xff) << 16)
| ((long) (digest[1] & 0xff) << 8)
| (digest[0] & 0xff);
long truncatehashcode = hashcode & 0xffffffffl;
return
truncatehashcode;
}public string doroute(string servicekey, treesetaddressset)
}//treemap的存放是根據addresshash值排序
long jobhash =hash(servicekey);
sortedmap
lastring =addressring.tailmap(jobhash);
//將addresshash值大於jobhash值的adress都取出來
if (!lastring.isempty())
//返回沒有減少的位址的第乙個
return
addressring.firstentry().getvalue();
}
一文詳解 RPC 之負載均衡
假設有一次流量高峰,突然發現線上服務的可用率降低了,經過排查發現是有幾台機器比較舊了,當流量達到高峰時,這幾台機器由於負載太高,就扛不住壓力,那怎麼解決這種問題呢?首先我們可能會想到,在治理平台上調低這幾台機器的權重,這樣的話,流量自然就減少了。但是這樣會導致服務可用率降低,業務請求受到影響,那 r...
RPC實現原理之核心技術 路由與負載均衡
為什麼要採用路由?真實的環境中一般是以集群的方式提供服務,但對於服務呼叫方來說,乙個介面會有多個服務提供方同時提供服務,所以 rpc 在每次發起請求的時候,都需要從多個服務節點裡面選取乙個用於處理請求的服務節點。每次上線應用的時候都不止執行一台伺服器例項,上線就會涉及到變更,只要變更就可能導致原本正...
負載均衡之lvs
集群 cluster 將一組計算機軟 硬體連線起來,高度緊密的協作完成計算工作,其中的單個計算機通常稱為節點。負載均衡集群 load balancing 通過負載均衡器,將負載盡可能平均分攤處理。lvs linux virtul server linux虛擬服務,分為三層結構 排程器 上面的虛擬ip...