pos機如何手寫,手寫微服務核心技術(shù)——負載均衡算法

 新聞資訊2  |   2023-05-28 12:28  |  投稿人:pos機之家

網(wǎng)上有很多關于pos機如何手寫,手寫微服務核心技術(shù)——負載均衡算法的知識,也有很多人為大家解答關于pos機如何手寫的問題,今天pos機之家(m.afbey.com)為大家整理了關于這方面的知識,讓我們一起來看下吧!

本文目錄一覽:

1、pos機如何手寫

pos機如何手寫

轉(zhuǎn)至小眼睛聊技術(shù)

概述

「負載均衡」是指,通過一定的算法使請求可以均勻的寵幸服務提供方,做到雨露均沾。市面上,軟件硬件產(chǎn)品一大把,解決的最最核心的問題都是選誰。

分類

按實現(xiàn)方式,可以分為硬件負載均衡(如 F5 、A10)、軟件負載均衡(如 LVS、Nginx、HAProxy)、DNS 負載均衡。硬件負載均衡和DNS 負載均衡我們不過多關注,重點看一下軟件負載均衡。

軟件負載均衡又分四層和七層負載均衡,四層負載均衡就是在網(wǎng)絡層利用 IP 地址端口進行請求的轉(zhuǎn)發(fā),基本上就是起個轉(zhuǎn)發(fā)分配作用。而七層負載均衡就是可以根據(jù)訪問用戶的 HTTP 請求頭、URL 信息將請求轉(zhuǎn)發(fā)到特定的主機。LVS 為四層負載均衡。Nginx、HAProxy 可四可七。

除了專用硬件和 Nginx 這種專業(yè)軟件提供負載均衡外,在代碼中直接實現(xiàn)也是種常見的方式。比如 Spring Cloud 體系中的 Ribbon 組件提供了輪詢、隨機、根據(jù)響應時間加權(quán)幾種負載策略,比如使用 Memcached 集群時通常會在 client 中采用 hash 取模或者一致性哈希來使數(shù)據(jù)均勻分布。

常見算法

最常見的負載均衡算法有隨機、加權(quán)隨機、輪詢、最小連接數(shù)、一致性哈希這幾種,我們分別看看用 Java 代碼如何實現(xiàn)。為了方便對比,我們定義了 Balanceable 接口,假定所有參與負載均衡處理的 server 都實現(xiàn)了 Balanceable 接口。

1. 隨機(random)

根據(jù)后端服務器列表的大小值來隨機選擇其中一臺進行訪問,代碼如下:

 public Balanceable choice(Balanceable[] servers) {     int index = (int) (Math.random() * servers.length);     return servers[index]; }

優(yōu)點:實現(xiàn)簡單,通過系統(tǒng)隨機函數(shù)隨機選擇其中一臺進行訪問

缺點:不適用后端機器承載能力不一致的情況

2. 權(quán)重隨機(Weighted Random)

各個節(jié)點帶有不同的權(quán)重,雖然隨機選擇但是期望不同權(quán)重的節(jié)點被選擇的幾率不一樣, 權(quán)重高的被選中的幾率大,權(quán)重低的被選中的幾率小。代碼如下:

 public Balanceable choice(Balanceable[] servers) {     int seed = 0;     for (Balanceable server : servers) {         seed += server.getWeight();     }     int random = r.nextInt(seed);     Collections.sort(Arrays.asList(servers));     int tmp = 0;     for (Balanceable server : servers) {         tmp += server.getWeight();         if (tmp >= random) {             return server;         }     }     return null; }

假設有三個節(jié)點 A、B、C 它們的權(quán)重分別是 3、2、4 ,那么就可以這樣表示

取直線上的任意一個點,這個點屬于直線上哪個節(jié)點的區(qū)域內(nèi)就是選擇了哪個節(jié)點:

所有權(quán)重相加得到 S(其實就是直線的長度)從 [0, S) 的區(qū)間內(nèi)取一個隨機數(shù) R(直線中隨機選擇一個點)遍歷節(jié)點列表,把訪問過的節(jié)點的權(quán)重相加得到 V,比較 V 與 R 的值,如果 V > R 當前節(jié)點即為選中的節(jié)點。(查找 R 在直線中的位置屬于哪個節(jié)點所在的區(qū)域)

優(yōu)點:實現(xiàn)簡單,采用權(quán)重改變了被選中的概率

缺點:不適用后端機器承載能力不一致的情況

3. 輪詢(Round Robin)

輪詢指的是從已有的后端節(jié)點列表中按順序依次選擇一個節(jié)點出來提供服務。代碼如下:

  Integer pos = 0;  public Balanceable choice(Balanceable[] servers) {     Balanceable result = null;     synchronized(pos) {         if (pos >= servers.length){             pos = 0;         }         result = servers[pos];         pos++;     }     return result; }

把所有待選擇的機器看做是一個個的點,所有點串起來一個圓。想象一下,輪詢就是對圓上的每一個點,順時針遍歷,在每個節(jié)點上停留一下。我們通過請求的次數(shù) pos ,來實現(xiàn)順時針選擇。需要修改 pos 的線程,只有獲取到鎖才能對該值做修改,當該值大于等于服務器列表長度時,重新從 0 開始遍歷,達到循環(huán)一周的目的。

優(yōu)點:相對來說請求可以做到絕對平衡

缺點:為了絕對平衡,需要保證 pos 修改時的互斥性,引入了同步鎖會帶來性能下降

4. 最小連接數(shù)(Least Connections)

從已有的后端列表中,選擇正在處理的連接數(shù) / 請求數(shù)最少的節(jié)點出來提供服務。既然要判斷連接數(shù) / 請求數(shù),那么每個節(jié)點都需要保存一個正在處理的連接數(shù) / 請求數(shù)的信息,然后選取節(jié)點的時候判斷一下, 選擇連接數(shù)最少的那個節(jié)點。代碼如下:

 public Balanceable choice(Balanceable[] servers) {     int length = servers.size();                                                                                           int leastactive = -1;     int leastCount = 0;     int[] leastIndexs = new int[length];     int totalWeight = 0;     int firstWeight = 0;     boolean sameWeight = true;     for (int i = 0; i < length; i++) {                                                                                                                                     Balanceable invoker = servers[i];         int active = status.getStatus(servers).getActive();         int weight = server.getWeight();                  if (leastActive == -1 || active < leastActive) {             leastActive = active;             leastCount = 1;             leastIndexs[0] = i;             totalWeight = weight;             firstWeight = weight;             sameWeight = true;         } else if (active == leastActive) {             leastIndexs[leastCount++] = i;             totalWeight += weight;             if (sameWeight && i > 0                     && weight != firstWeight) {                 sameWeight = false;             }         }     }          if (leastCount == 1) {             return servers[leastIndexs[0]];     }     if (!sameWeight && totalWeight > 0) {             int offsetWeight = random.nextInt(totalWeight);         for (int i = 0; i < leastCount; i++) {             int leastIndex = leastIndexs[i];             offsetWeight -= getWeight(servers[leastIndex]);             if (offsetWeight <= 0)                 return servers[leastIndex];         }     }          return servers[leastIndexs[random.nextInt(leastCount)]]; }

首先找到服務提供者當前最小的活躍連接數(shù),如果一個服務提供者的服務連接數(shù)比其他的都要小,則選擇這個活躍連接數(shù)最小的服務提供者發(fā)起調(diào)用,如果存在多個服務提供者的活躍連接數(shù),并且是最小的,則在這些服務提供者之間選擇加權(quán)隨機算法選擇一個服務提供者。

優(yōu)點:根據(jù)服務器當前的請求處理情況,動態(tài)分配

缺點:算法實現(xiàn)相對復雜,需要監(jiān)控服務器請求連接數(shù)

5. 一致性哈希(Consistent Hash)

根據(jù)后端節(jié)點的某個固定屬性計算 hash 值,然后把所有節(jié)點計算出來的 hash 值組成一個 hash 環(huán)。請求過來的時候根據(jù)請求的特征計算該特征的 hash 值(使用跟計算后端節(jié)點 hash 值相同的 hash 函數(shù)進行計算), 然后順時針查找 hash 環(huán)上的 hash 值,第一個比請求特征的 hash 值大的 hash 值所對應的節(jié)點即為被選中的節(jié)點。

某一部分節(jié)點發(fā)生故障時,或者新的節(jié)點動態(tài)的增加進來時都只需重定位環(huán)空間中的一小部分數(shù)據(jù),具有較好的容錯性和可擴展性。

構(gòu)造哈希環(huán)

 public static TreeMap<long, String> populateConsistentBuckets(    String... servers) { // store buckets in tree map     TreeMap<Long, String> consistentBuckets = new TreeMap<Long, String>();      MessageDigest md5 = MD5.get();     int totalWeight = servers.length;      for (int i = 0; i < servers.length; i++) {         int thisWeight = 1;          double factor = Math             .floor(((double) (40 * servers.length * thisWeight))                    / (double) totalWeight);          for (long j = 0; j < factor; j++) {             byte[] d = md5.digest((servers[i] + "-" + j).getBytes());             for (int h = 0; h < 4; h++) {                 Long k = ((long) (d[3 + h * 4] & 0xFF) << 24)                     | ((long) (d[2 + h * 4] & 0xFF) << 16)                     | ((long) (d[1 + h * 4] & 0xFF) << 8)                     | ((long) (d[0 + h * 4] & 0xFF));                  consistentBuckets.put(k, servers[i]);             }         }     }     return consistentBuckets; }

上面的 hash 還有一個問題,就是節(jié)點的 hash 值不一定是均勻的分布在 hash 環(huán)上的,這樣就會導致部分節(jié)點上承受太多的請求。解決辦法是引入虛擬節(jié)點:每個節(jié)點重復 n 次,把這些虛擬節(jié)點的 hash 值(跟實際節(jié)點的 hash 值不一樣,也就是說需要在節(jié)點屬性中加點東西保證每個虛擬節(jié)點跟實際節(jié)點的 hash 值不一樣,互相之間也要不一樣)也加入到 hash 環(huán)中以此來保證分布更均勻。

從環(huán)中找到合適的節(jié)點:

 public static final Long getBucket(TreeMap<Long, String> buckets, Long hv) {     SortedMap<Long, String> t = buckets.tailMap(hv);     return (t.isEmpty()) ? buckets.firstKey() : t.firstKey(); }

這里有一個需要注意的點那就是臨界值的處理問題:可能會有部分請求處在 hash 環(huán)上最后一個點的后面,即 hash 環(huán)上找不到一個比請求特征的 hash 值更大的一個 hash。對于這種無法在 hash 環(huán)上找到對應的下一個節(jié)點的情況,一般是把 hash 環(huán)上的第一個 hash 值作為被選中的點,即進行第二圈的順時針查找。

優(yōu)點:具有較好的容錯性和可擴展性,節(jié)點加入或者去除,只有少量數(shù)據(jù)需要遷移

缺點:沒有解決熱點問題,會出現(xiàn)部分節(jié)點需要處理大量請求

總結(jié)負載均衡,目的是讓每臺服務器獲取到適合自己處理能力的負載可以采用硬件、軟件的方式進行實現(xiàn)常見的幾種負載均衡算法,各自有優(yōu)缺點,選擇不同場景使用

以上就是關于pos機如何手寫,手寫微服務核心技術(shù)——負載均衡算法的知識,后面我們會繼續(xù)為大家整理關于pos機如何手寫的知識,希望能夠幫助到大家!

轉(zhuǎn)發(fā)請帶上網(wǎng)址:http://m.afbey.com/newsone/59019.html

你可能會喜歡:

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關法律責任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 babsan@163.com 舉報,一經(jīng)查實,本站將立刻刪除。