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

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

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

本文目錄一覽:

1、pos機(jī)如何手寫

pos機(jī)如何手寫

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

概述

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

分類

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

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

除了專用硬件和 Nginx 這種專業(yè)軟件提供負(fù)載均衡外,在代碼中直接實(shí)現(xiàn)也是種常見的方式。比如 Spring Cloud 體系中的 Ribbon 組件提供了輪詢、隨機(jī)、根據(jù)響應(yīng)時(shí)間加權(quán)幾種負(fù)載策略,比如使用 Memcached 集群時(shí)通常會(huì)在 client 中采用 hash 取?;蛘咭恢滦怨硎箶?shù)據(jù)均勻分布。

常見算法

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

1. 隨機(jī)(random)

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

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

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

缺點(diǎn):不適用后端機(jī)器承載能力不一致的情況

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

各個(gè)節(jié)點(diǎn)帶有不同的權(quán)重,雖然隨機(jī)選擇但是期望不同權(quán)重的節(jié)點(diǎn)被選擇的幾率不一樣, 權(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; }

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

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

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

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

缺點(diǎn):不適用后端機(jī)器承載能力不一致的情況

3. 輪詢(Round Robin)

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

  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; }

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

優(yōu)點(diǎn):相對(duì)來說請(qǐng)求可以做到絕對(duì)平衡

缺點(diǎn):為了絕對(duì)平衡,需要保證 pos 修改時(shí)的互斥性,引入了同步鎖會(huì)帶來性能下降

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

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

 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)]]; }

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

優(yōu)點(diǎn):根據(jù)服務(wù)器當(dāng)前的請(qǐng)求處理情況,動(dòng)態(tài)分配

缺點(diǎn):算法實(shí)現(xiàn)相對(duì)復(fù)雜,需要監(jiān)控服務(wù)器請(qǐng)求連接數(shù)

5. 一致性哈希(Consistent Hash)

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

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

構(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 還有一個(gè)問題,就是節(jié)點(diǎn)的 hash 值不一定是均勻的分布在 hash 環(huán)上的,這樣就會(huì)導(dǎo)致部分節(jié)點(diǎn)上承受太多的請(qǐng)求。解決辦法是引入虛擬節(jié)點(diǎn):每個(gè)節(jié)點(diǎn)重復(fù) n 次,把這些虛擬節(jié)點(diǎn)的 hash 值(跟實(shí)際節(jié)點(diǎn)的 hash 值不一樣,也就是說需要在節(jié)點(diǎn)屬性中加點(diǎn)東西保證每個(gè)虛擬節(jié)點(diǎn)跟實(shí)際節(jié)點(diǎn)的 hash 值不一樣,互相之間也要不一樣)也加入到 hash 環(huán)中以此來保證分布更均勻。

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

 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(); }

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

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

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

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

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

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

你可能會(huì)喜歡:

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