本發(fā)明涉及計算機網(wǎng)絡(luò)技術(shù)領(lǐng)域,具體涉及一種基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法、裝置及系統(tǒng)、服務(wù)器。
背景技術(shù):
服務(wù)發(fā)現(xiàn)組件記錄了(大規(guī)模)分布式系統(tǒng)中所有服務(wù)的信息,人們或者其它服務(wù)可以據(jù)此找到這些服務(wù)。DNS就是一個簡單的例子。當(dāng)然,復(fù)雜系統(tǒng)的服務(wù)發(fā)現(xiàn)組件要提供更多的功能,例如,服務(wù)元數(shù)據(jù)存儲、健康監(jiān)控、多種查詢和實時更新等。服務(wù)發(fā)現(xiàn)給當(dāng)前互聯(lián)網(wǎng)架構(gòu)的網(wǎng)絡(luò)公司帶來的好處就是零配置,不需要硬編碼網(wǎng)絡(luò)地址到應(yīng)用中,只需有服務(wù)的名字即可找到該服務(wù)的后端服務(wù)列表和網(wǎng)絡(luò)拓?fù)湫畔ⅰ?/p>
目前業(yè)界提供了多種服務(wù)發(fā)現(xiàn)的解決方案,但是目前公開的各種服務(wù)發(fā)現(xiàn)解決方案都沒有完美的解決所有問題。舉例來說,DNS,在小規(guī)模系統(tǒng)可以先使用DNS作為服務(wù)發(fā)現(xiàn)手段。一旦服務(wù)節(jié)點的啟動和銷毀變得更加動態(tài),DNS就會出現(xiàn)問題,因為DNS記錄傳播的速度可能跟不上服務(wù)節(jié)點變化的速度。常見的服務(wù)發(fā)現(xiàn)相關(guān)的解決方案還有類似dubbo這種基于某個編程語言的,但是這種基于特定語言的服務(wù)發(fā)現(xiàn)問題也是顯而易見的,因為大多數(shù)互聯(lián)網(wǎng)公司內(nèi)部使用的編程語言都不止一種,限定到語言級別則會將服務(wù)發(fā)現(xiàn)的能力大大降低。
技術(shù)實現(xiàn)要素:
鑒于上述問題,提出了本發(fā)明以便提供一種克服上述問題或者至少部分地解決上述問題的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法、裝置及系統(tǒng)、服務(wù)器。
根據(jù)本發(fā)明的一個方面,提供了一種基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法,包括:
監(jiān)聽并獲取消息隊列中記錄的服務(wù)名稱;其中,所述服務(wù)名稱是客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中未查詢到所述服務(wù)的服務(wù)提供者信息而寫入到消息隊列中;
根據(jù)所述服務(wù)名稱,從服務(wù)注冊組件處獲取所述服務(wù)的服務(wù)提供者信息;
將所述服務(wù)的服務(wù)提供者信息寫入共享內(nèi)存中,以供客戶端從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
根據(jù)本發(fā)明的另一方面,提供了一種基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)裝置,包括:
監(jiān)聽模塊,適于監(jiān)聽并獲取消息隊列中記錄的服務(wù)名稱;其中,所述服務(wù)名稱是客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中未查詢到所述服務(wù)的服務(wù)提供者信息而寫入到消息隊列中;
獲取模塊,適于根據(jù)所述服務(wù)名稱,從服務(wù)注冊組件處獲取所述服務(wù)的服務(wù)提供者信息;
寫入模塊,適于將所述服務(wù)的服務(wù)提供者信息寫入共享內(nèi)存中,以供客戶端從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
根據(jù)本發(fā)明的另一方面,提供了一種基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)系統(tǒng),包括:上述基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)裝置、共享內(nèi)存、客戶端以及服務(wù)注冊組件;
所述客戶端適于:在接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中查詢到所述服務(wù)的服務(wù)提供者信息,若未查詢到,則將服務(wù)名稱寫入到消息隊列中;若查詢到,則從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
根據(jù)本發(fā)明的又一方面,提供了一種服務(wù)器,包括:處理器、存儲器、通信接口和通信總線,所述處理器、所述存儲器和所述通信接口通過所述通信總線完成相互間的通信;
所述存儲器用于存放至少一可執(zhí)行指令,所述可執(zhí)行指令使所述處理器執(zhí)行上述基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法對應(yīng)的操作。
根據(jù)本發(fā)明的再一方面,提供了一種計算機存儲介質(zhì),所述存儲介質(zhì)中存儲有至少一可執(zhí)行指令,所述可執(zhí)行指令使所述處理器執(zhí)行如上述基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法對應(yīng)的操作。
根據(jù)本發(fā)明提供的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法、裝置及系統(tǒng)、服務(wù)器,在客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,首先在共享內(nèi)存中查詢服務(wù)的服務(wù)提供者信息,若查詢到,則直接在共享內(nèi)存中讀取服務(wù)提供者信息;若未查詢到,則通過網(wǎng)絡(luò)去服務(wù)注冊組件中獲取服務(wù)提供者信息。利用本方案,達(dá)到了應(yīng)用層在獲取服務(wù)列表配置信息時和獲取本地內(nèi)存讀寫一樣的性能,減少了網(wǎng)絡(luò)延遲,提升了讀取速度,這種與后端分布式集群通信產(chǎn)生共享內(nèi)存并提供客戶端供應(yīng)用使用的方式,避免了客戶端和分布式集群之間用長連接方式進(jìn)行對接而導(dǎo)致的資源占用過多、服務(wù)注冊組件處理效率低下的問題。
上述說明僅是本發(fā)明技術(shù)方案的概述,為了能夠更清楚了解本發(fā)明的技術(shù)手段,而可依照說明書的內(nèi)容予以實施,并且為了讓本發(fā)明的上述和其它目的、特征和優(yōu)點能夠更明顯易懂,以下特舉本發(fā)明的具體實施方式。
附圖說明
通過閱讀下文優(yōu)選實施方式的詳細(xì)描述,各種其他的優(yōu)點和益處對于本領(lǐng)域普通技術(shù)人員將變得清楚明了。附圖僅用于示出優(yōu)選實施方式的目的,而并不認(rèn)為是對本發(fā)明的限制。而且在整個附圖中,用相同的參考符號表示相同的部件。在附圖中:
圖1示出了根據(jù)本發(fā)明一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法的流程圖;
圖2示出了本發(fā)明一個實施例中服務(wù)發(fā)現(xiàn)數(shù)據(jù)結(jié)構(gòu)存儲模型的示意圖;
圖3示出了根據(jù)本發(fā)明另一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法的流程圖;
圖4示出了實現(xiàn)本發(fā)明一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法的系統(tǒng)架構(gòu)示意圖;
圖5示出了本發(fā)明一個實施例中agent內(nèi)部線程模型的示意圖;
圖6示出了本發(fā)明一個實施例中各個語言接入共享內(nèi)存進(jìn)行通信的示意圖;
圖7示出了根據(jù)本發(fā)明一個實施例的服務(wù)發(fā)現(xiàn)協(xié)議的分層模型示意圖;
圖8示出了根據(jù)本發(fā)明一個實施例的服務(wù)注冊集群中服務(wù)健康檢查的架構(gòu)示意圖;
圖9示出了根據(jù)本發(fā)明一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)裝置的功能框圖;
圖10示出了根據(jù)本發(fā)明一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)系統(tǒng)的功能框圖;
圖11示出了根據(jù)本發(fā)明實施例六的一種服務(wù)器的結(jié)構(gòu)示意圖。
具體實施方式
下面將參照附圖更詳細(xì)地描述本公開的示例性實施例。雖然附圖中顯示了本公開的示例性實施例,然而應(yīng)當(dāng)理解,可以以各種形式實現(xiàn)本公開而不應(yīng)被這里闡述的實施例所限制。相反,提供這些實施例是為了能夠更透徹地理解本公開,并且能夠?qū)⒈竟_的范圍完整的傳達(dá)給本領(lǐng)域的技術(shù)人員。
在對本發(fā)明的技術(shù)方案進(jìn)行介紹之前,首先對本發(fā)明實施例中所涉及的技術(shù)術(shù)語進(jìn)行簡單介紹:
服務(wù)發(fā)現(xiàn):當(dāng)某個服務(wù)添加的服務(wù)集群中時,該服務(wù)所暴露的調(diào)用地址能夠被其使用方自動感知到并進(jìn)行調(diào)用。
共享內(nèi)存(SHM):在多處理器的計算機系統(tǒng)中,可以被不同中央處理器(CPU)訪問的大容量內(nèi)存。
進(jìn)程間通信(IPC):一組編程接口,讓程序員能夠協(xié)調(diào)不同的進(jìn)程,使之能在一個操作系統(tǒng)里同時運行,并相互傳遞、交換信息。
負(fù)載均衡(LB):建立在網(wǎng)絡(luò)結(jié)構(gòu)之上,能夠?qū)⒄埱蠓謹(jǐn)偟蕉鄠€操作單元上進(jìn)行執(zhí)行,例如Web服務(wù)器、FTP服務(wù)器、企業(yè)關(guān)鍵應(yīng)用服務(wù)器和其它關(guān)鍵任務(wù)服務(wù)器等,從而共同完成工作任務(wù)。常見的負(fù)載均衡軟件有HAPROXY,nginx,LVS等。
服務(wù)注冊組件:一個通用的分布式組件,該組件通常通過的分布式算法進(jìn)行實現(xiàn),主要用于保障分布式復(fù)雜網(wǎng)絡(luò)環(huán)境,多個服務(wù)器針對某個服務(wù)的事務(wù)性,一致性,可靠性。這種服務(wù)注冊組件常見的開源實現(xiàn)有zookeeper,etcd,consul等。
本發(fā)明的發(fā)明人在研究現(xiàn)有技術(shù)的過程中,發(fā)現(xiàn)現(xiàn)有技術(shù)提供的服務(wù)發(fā)現(xiàn)解決方案存在以下未解決的難題,并對這些難題未解決的原因進(jìn)行了具體分析。
難題一,應(yīng)用層在獲取服務(wù)列表配置信息時不能保證和獲取本地內(nèi)存讀寫一樣的性能,之所以說保持內(nèi)存讀寫級別的性能是個難題,主要有以下幾個原因?qū)е拢?/p>
(1)當(dāng)客戶端獲取在服務(wù)注冊組件所注冊的服務(wù)時,如果每個客戶端都走長連接,由于應(yīng)用數(shù)量和應(yīng)用進(jìn)程數(shù)不可控,會導(dǎo)致長連接過多致使服務(wù)注冊組件處理效率低下,資源占用過多;
(2)當(dāng)客戶端獲取在服務(wù)注冊組件所注冊的服務(wù)時,如果每個客戶端走短連接,那么獲取服務(wù)注冊組件的服務(wù)本身就需要有個網(wǎng)絡(luò)層1到5ms的開銷,使得服務(wù)性能低下;
(3)常見的分布式組件應(yīng)用設(shè)計上大多考慮更多的是分布式一致性和可靠性問題,對分布式服務(wù)本身提供的高性能方面有先天性不足。舉例來說,當(dāng)分布式組件集群中有一個或者多個節(jié)點宕機時,這時分布式組件集群為了保證可靠性和重新選舉策略,一般都會有相當(dāng)大的開銷,這時該分布式組件的寫入和讀取性能有較大的損失。
難題二,跨語言的通用性服務(wù)發(fā)現(xiàn)實現(xiàn)困難,其難以實現(xiàn)的主要原因由以下幾個方面:
(1)不是所有的編程語言都支持長連接的方式進(jìn)行實時通信;
(2)不是所有的語言對分布式組件比如zookeeper,etcd等都有完善的API支持;
(3)實現(xiàn)某個特定語言的客戶端對分布式組件(比如:zookeeper)的使用已經(jīng)非常困難,要實現(xiàn)各個語言保持一致的使用方式的使用更是難上加難。
難題三,基于統(tǒng)一模型的服務(wù)發(fā)現(xiàn)技術(shù)需要兼容服務(wù)端的服務(wù)發(fā)現(xiàn)機制和客戶端的服務(wù)發(fā)現(xiàn)機制。
傳統(tǒng)的服務(wù)發(fā)現(xiàn)的架構(gòu)模式要么是服務(wù)端服務(wù)發(fā)現(xiàn),要么是客戶端服務(wù)發(fā)現(xiàn),兩個方案各有優(yōu)缺點,在實際生產(chǎn)環(huán)境的應(yīng)用上,往往需要兼容服務(wù)端的服務(wù)發(fā)現(xiàn)和客戶端的服務(wù)發(fā)現(xiàn)。常見的服務(wù)端服務(wù)發(fā)現(xiàn)的架構(gòu)模式一般都是將服務(wù)動態(tài)注冊到一個LB(load balancer,負(fù)載均衡)上,然后客戶端的調(diào)用從LB獲取服務(wù)。常見的客戶端服務(wù)發(fā)現(xiàn)的架構(gòu)模式是在客戶端綁定一個負(fù)載均衡邏輯塊,該負(fù)載均衡邏輯塊負(fù)責(zé)和服務(wù)注冊中心通訊獲取服務(wù)列表然后通過負(fù)載均衡算法進(jìn)行返回。
為了克服以上至少一個難題,本發(fā)明提供了一種基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法。下面通過幾個具體的實施例對本發(fā)明的具體實現(xiàn)方案進(jìn)行詳細(xì)介紹。
實施例一
圖1示出了根據(jù)本發(fā)明一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法的流程圖。如圖1所示,該方法包括如下步驟:
步驟S101,監(jiān)聽并獲取消息隊列中記錄的服務(wù)名稱;其中,服務(wù)名稱是客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中未查詢到服務(wù)的服務(wù)提供者信息而寫入到消息隊列中。
步驟S102,根據(jù)服務(wù)名稱,從服務(wù)注冊組件處獲取服務(wù)的服務(wù)提供者信息。
步驟S103,將服務(wù)的服務(wù)提供者信息寫入共享內(nèi)存中,以供客戶端從共享內(nèi)存中讀取服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
本發(fā)明實施例中,服務(wù)注冊組件用來存儲服務(wù)節(jié)點相關(guān)的元數(shù)據(jù)。在服務(wù)注冊系統(tǒng)中,存在監(jiān)聽單元,負(fù)責(zé)監(jiān)聽新加入的服務(wù)提供者,將服務(wù)提供者進(jìn)行抽象為服務(wù)注冊節(jié)點,并獲取服務(wù)注冊節(jié)點的元數(shù)據(jù)(包含主機端口,名稱等),調(diào)用接口將服務(wù)注冊節(jié)點的元數(shù)據(jù)寫入到服務(wù)注冊組件中。常見的服務(wù)注冊節(jié)點的數(shù)據(jù)存儲模型都是樹形結(jié)構(gòu),針對該種類型的數(shù)據(jù)結(jié)構(gòu)設(shè)計的服務(wù)發(fā)現(xiàn)存儲模型如圖2所示。
namespace:名字空間(即服務(wù)名稱),每個服務(wù)都會有一個namespace與之對應(yīng)。每個namespace又會有兩個子節(jié)點providers和consumers;
providers:服務(wù)提供者,用于通過名字空間獲取;服務(wù)提供者信息包含提供服務(wù)的各個主機的主機端口;
consumers:服務(wù)消費者,用于記錄使用該服務(wù)的節(jié)點信息,服務(wù)消費者信息包含使用服務(wù)的各個主機的主機端口。
為了保障應(yīng)用層在獲取服務(wù)列表配置信息時能和獲取本地內(nèi)存讀寫一樣的性能,并且在服務(wù)注冊組件中服務(wù)列表變更時能夠同步實時的感知到服務(wù)的變更信息,本發(fā)明的解決方案提供一個共享內(nèi)存和agent,該agent負(fù)責(zé)和服務(wù)注冊組件進(jìn)行通信并保證服務(wù)注冊組件內(nèi)的變更能夠?qū)崟r通知到該agent,然后該agent產(chǎn)生共享內(nèi)存供其他應(yīng)用使用。
在上述步驟S101中,客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中查詢服務(wù)的服務(wù)提供者(providers)信息,若未查詢到,則將服務(wù)名稱(namespace)寫入agent的消息隊列中。agent實時監(jiān)聽和獲取消息隊列中記錄的服務(wù)名稱。
在上述步驟S102中,若agent監(jiān)聽到消息隊列中存在服務(wù)名稱,則從中提取出服務(wù)名稱,從服務(wù)注冊組件處獲取服務(wù)的服務(wù)提供者信息。
在上述步驟S103中,agent將服務(wù)的服務(wù)提供者信息寫入共享內(nèi)存中,以供客戶端從共享內(nèi)存中讀取服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
由于linux跨進(jìn)程通信中基于共享內(nèi)存的方式具有高性能,可靠性的特點因此本方案通過將與服務(wù)注冊組件進(jìn)行網(wǎng)絡(luò)通信的模塊移交到agent中,然后讓agent產(chǎn)生共享內(nèi)存供其他客戶端使用,利用這種方式,避免了客戶端本身和服務(wù)注冊組件進(jìn)行通信的網(wǎng)絡(luò)開銷,也使得客戶端本身幾乎沒有額外的性能開銷。
實施例二
圖3示出了根據(jù)本發(fā)明另一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法的流程圖,圖4示出了實現(xiàn)本發(fā)明一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法的系統(tǒng)架構(gòu)示意圖,圖5示出了本發(fā)明一個實施例中agent內(nèi)部線程模型的示意圖。下面結(jié)合圖3、圖4和圖5對本發(fā)明實施例二的詳細(xì)步驟進(jìn)行介紹。
如圖3所示,該方法包括如下步驟:
步驟S200,服務(wù)注冊步驟。
服務(wù)注冊一般都會有服務(wù)注冊組件用來存儲服務(wù)節(jié)點相關(guān)的元數(shù)據(jù)。如圖2所示,常見的服務(wù)注冊節(jié)點的數(shù)據(jù)存儲模型都是樹形結(jié)構(gòu)。從使用方角度來講服務(wù)自身的注冊邏輯應(yīng)當(dāng)盡可能的簡單,最好簡單到一步即可完成,但是又考慮到服務(wù)注冊本身并不是任何應(yīng)用均可以隨意注冊,其自身還需要有權(quán)限管理和授權(quán)機制,因此本發(fā)明實施例抽象出一個API層專門用于服務(wù)注冊到服務(wù)注冊組件上,該API層實現(xiàn)的API主要基于以上樹形結(jié)構(gòu)的服務(wù)注冊組件元信息進(jìn)行開發(fā),API概要如下:
1,獲取namespace列表接口
GET/zkapi/v1/namespace
2,創(chuàng)建namespace接口
POST/zkapi/v1/{namespace}
data={"name":"namespace"}邏輯上會創(chuàng)建namespace節(jié)點以及其子節(jié)點providers和consumers
3,刪除namespace接口
DEL/zkapi/v1/{namespace}
4,獲取某個namespace下提供的服務(wù)列表和服務(wù)策略
GET/zkapi/v1/{namespace}/providers
5,添加或更新一個服務(wù)提供者到某個namespace
POST/zkapi/v1/{namespace}/providers/{service_name}
data={"host":"192.168.56.32","port":"4455"}
6,刪除某個namespace下的一個服務(wù)提供者
DEL/zkapi/v1/{namespace}/providers/{service_name}
7,獲取某個namespace下消費者的列表
GET/zkapi/v1/{namespace}/consumers
8,刪除某個namespace下的消費者
DEL/zkapi/v1/{namespace}/consumers/{consumer_name}
9,添加消費者到某個namespace下
POST/zkapi/v1/{namespace}/consumers/{service_name}
data={"service_value":"ip:port"}
10,修改某個namespace下providers節(jié)點值屬性
POST/zkapi/v1/{namespace}/providers
data={"load_banlance":"RR","on_faile":"url"}
步驟S201,生成動態(tài)鏈接庫向利用不同編程語言實現(xiàn)的客戶端提供統(tǒng)一的共享內(nèi)存查詢接口。
為了解決跨語言的通用性服務(wù)發(fā)現(xiàn)實現(xiàn)困難的難題,本實施例提供的解決方案是不再在各個語言內(nèi)部進(jìn)行服務(wù)注冊組件的實現(xiàn),而是使用統(tǒng)一的編程語言,如C++編程語言對服務(wù)注冊組件API進(jìn)行調(diào)用和服務(wù)發(fā)現(xiàn)邏輯的封裝,用C++生成動態(tài)鏈接庫的方式來對外提供統(tǒng)一的服務(wù)發(fā)現(xiàn)的API。圖6示出了本發(fā)明一個實施例中各個語言接入共享內(nèi)存進(jìn)行通信的示意圖。如圖6所示,服務(wù)發(fā)現(xiàn)策略實現(xiàn)的各個語言接入主要支持:Java,Python,php,C/C++,lua等,還可支持shell,go等語言。各個語言接入共享內(nèi)存主要通過動態(tài)鏈接庫(.so文件)來和共享內(nèi)存進(jìn)行通信,各個語言通過封裝動態(tài)鏈接庫和服務(wù)發(fā)現(xiàn)邏輯提供的服務(wù)發(fā)現(xiàn)的接口只有一個即:get_service,接口參數(shù)為namespace和algorithm,該函數(shù)根據(jù)algorithm參數(shù)對namespace下的providers進(jìn)行篩選從而返回一個provider出來給應(yīng)用層使用。
步驟S202,客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中查詢該服務(wù)的服務(wù)提供者信息,若查詢到,則執(zhí)行步驟S207;若未查詢到,則執(zhí)行步驟S203。
客戶端在接收到應(yīng)用層訪問服務(wù)的請求之后,首先在共享內(nèi)存中查詢該服務(wù)的providers信息,若共享內(nèi)存中預(yù)先存儲有該服務(wù)的providers信息,則可直接讀取。若共享內(nèi)存中沒有存儲該服務(wù)的providers信息,繼續(xù)執(zhí)行步驟S203。
本實施例主要是利用服務(wù)注冊集群中的節(jié)點變更通知特性監(jiān)聽節(jié)點事件的發(fā)生,從而進(jìn)行共享內(nèi)存中節(jié)點的增刪改查,盡量保證共享內(nèi)存中節(jié)點信息與服務(wù)注冊組件中的節(jié)點信息一致。具體地,監(jiān)聽服務(wù)注冊組件中的內(nèi)容變更,將這些變更情況同步到共享內(nèi)存中。
步驟S203,將該服務(wù)的服務(wù)名稱寫入到消息隊列中。
步驟S204,代理agent監(jiān)聽并獲取消息隊列中記錄的服務(wù)名稱。
步驟S205,根據(jù)服務(wù)名稱,從服務(wù)注冊組件處獲取該服務(wù)的服務(wù)提供者信息。
步驟S206,將該服務(wù)的服務(wù)提供者信息寫入共享內(nèi)存中。
代理agent內(nèi)部主要使用4個線程保證服務(wù)穩(wěn)定可靠,如圖5所示,主線程啟動后,從消息隊列中獲取待查詢的服務(wù)名稱,然后從服務(wù)注冊組件處獲取該服務(wù)的服務(wù)提供者信息,并更新到共享內(nèi)存中。如果更新共享內(nèi)存成功,主線程還會將查詢到的數(shù)據(jù)發(fā)送到另一隊列中用于一些額外的操作。
消息線程負(fù)責(zé)從消息隊列里取服務(wù)名稱。因為系統(tǒng)的消息隊列大小有限制,若隊列內(nèi)的數(shù)據(jù)未及時取走,則可能因為客戶端在短時間內(nèi)大量寫入服務(wù)名稱而將隊列填滿,之后的服務(wù)名稱將無法再寫入,造成錯誤。而agent獲得服務(wù)名稱后,需要通過網(wǎng)絡(luò)去服務(wù)注冊組件上取得服務(wù)提供者信息,相對較慢(10ms左右),因此很可能發(fā)生隊列的積壓填滿。為了避免出現(xiàn)這種問題,agent監(jiān)聽消息隊列中記錄的服務(wù)名稱,將消息隊列中記錄的服務(wù)名稱讀到內(nèi)存中,并及時清除消息隊列中記錄的服務(wù)名稱,防止填滿隊列。主線程從內(nèi)存里獲得需要讀取的服務(wù)名稱,再去服務(wù)注冊組件上取值。
輔助線程負(fù)責(zé)每隔預(yù)定時間掃描共享內(nèi)存中的服務(wù)提供者信息;將共享內(nèi)存中的服務(wù)提供者信息與服務(wù)注冊組件中的服務(wù)提供者信息進(jìn)行比對;若比對不一致,則根據(jù)服務(wù)注冊組件中的服務(wù)提供者信息更新共享內(nèi)存中的服務(wù)提供者信息。
因為服務(wù)注冊組件的watcher機制不能設(shè)置為持久監(jiān)視,而是一次性的,也就是說,一個事件被觸發(fā)一次后,該watcher就被自動銷毀,如果要繼續(xù)監(jiān)視下次事件,只能重新注冊watcher。所以本發(fā)明采取的策略是事件發(fā)生后,第一時間先重新注冊watcher,再執(zhí)行具體的處理邏輯,盡量減少上個watcher銷毀與下個watcher注冊的時間間隔。盡管如此,這二者仍然不是事務(wù)性操作,因此仍有極小概率會丟失事件。為了防止這種情況發(fā)生,本發(fā)明會每隔30-60分鐘掃描共享內(nèi)存里的所有節(jié)點,并與服務(wù)注冊組件上的最新值比較,若有差異則更新到最新值,并為可能遺漏監(jiān)視的節(jié)點重新注冊watcher。
觸發(fā)線程實際上是一個多功能線程,主要是數(shù)據(jù)在共享內(nèi)存更新完成后需要執(zhí)行的額外操作,當(dāng)前主要操作有備份(dump),執(zhí)行腳本以及信息反饋。
步驟S207,客戶端從共享內(nèi)存中讀取該服務(wù)的服務(wù)提供者信息。
從圖4所示的系統(tǒng)架構(gòu)圖上可以看出,agent與客戶端并沒有直接的通訊,二者的交互的一個渠道是共享內(nèi)存。共享內(nèi)存的作用在于,客戶端可能會多次讀取相同的配置項(其值可能并不會每次都改變),如果沒有在本機存儲這些配置項,那么就必然需要每次通過網(wǎng)絡(luò)去服務(wù)注冊組件服務(wù)端讀取(相同的值),一是存在網(wǎng)絡(luò)延遲,二是服務(wù)注冊組件本身性能并不高,不適合大量的頻繁讀操作。之所以選用共享內(nèi)存這種存儲方式,是看中了其性能優(yōu)勢,節(jié)點信息在共享內(nèi)存里以哈希表的形式存儲,因此查詢時間是常數(shù)級,實際測試一次讀取耗時在16us左右,完全可以滿足用戶對低延遲的要求。
agent與客戶端交互的另一個渠道是消息隊列??蛻舳私邮盏綉?yīng)用層訪問服務(wù)的請求之后,先去共享內(nèi)存里檢索,若找到則直接返回,若未找到,則將該服務(wù)的名稱寫入消息隊列。而agent時刻監(jiān)視消息隊列中是否有數(shù)據(jù),一旦有數(shù)據(jù)被寫入,agent即讀出數(shù)據(jù)(服務(wù)名),再根據(jù)服務(wù)名去服務(wù)注冊組件把服務(wù)提供者信息讀取回來,并寫入共享內(nèi)存??蛻舳藭却钡焦蚕韮?nèi)存里出現(xiàn)所要讀取的服務(wù)提供者信息,然后讀出服務(wù)提供者信息并返回。
步驟S208,根據(jù)讀取的服務(wù)的服務(wù)提供者信息計算MD5值,將計算得到的MD5值與共享內(nèi)存中存儲的MD5值進(jìn)行比對是否一致,若是,則執(zhí)行步驟S209;否則,執(zhí)行步驟S207。
由于涉及到多個進(jìn)程(agent和客戶端進(jìn)程)對共享內(nèi)存的同時讀寫,所以需要避免沖突。共享內(nèi)存里同時存儲服務(wù)提供者信息與其MD5值,客戶端會把二者一次全讀出,然后根據(jù)讀取的服務(wù)提供者信息計算MD5值,校驗MD5值是否正確,若不正確則會重新讀取,這就避免了agent尚未寫入完整的服務(wù)提供者信息被客戶端讀走,也消除了鎖爭用,進(jìn)一步提升性能。
步驟S209,客戶端將該服務(wù)的服務(wù)提供者信息返回給應(yīng)用層。
另外,針對基于統(tǒng)一模型的服務(wù)發(fā)現(xiàn)技術(shù)需要兼容服務(wù)端的服務(wù)發(fā)現(xiàn)機制和客戶端的服務(wù)發(fā)現(xiàn)機制的問題,該問題主要集中在一套服務(wù)發(fā)現(xiàn)協(xié)議如何保證服務(wù)端的服務(wù)發(fā)現(xiàn)和客戶端的服務(wù)發(fā)現(xiàn)擁有相同的特性。常見的服務(wù)發(fā)現(xiàn)組件有Nginx,Haproxy,LVS等,其中Nginx工作在網(wǎng)絡(luò)協(xié)議的第七層(應(yīng)用層),Haproxy既可以工作在4層又可以工作在七層,LVS只能工作在4層。從高性能、可靠性、易用性、可擴展性上,經(jīng)對比發(fā)現(xiàn)Nginx在實現(xiàn)負(fù)載均衡的策略上較其他幾個有更好的應(yīng)用場景。
圖7示出了根據(jù)本發(fā)明一個實施例的服務(wù)發(fā)現(xiàn)協(xié)議的分層模型示意圖,如圖7所示,本發(fā)明基于Nginx開發(fā)了一個LB擴展模塊,使得nginx層可以通過該LB擴展模塊來動態(tài)獲取上游(upstream)的配置,從而解決了服務(wù)端的服務(wù)發(fā)現(xiàn)問題。本發(fā)明使用nginx做反向代理來提供服務(wù),nginx代理的服務(wù)需要能夠自動注冊到nginx中,避免了因修改nginx的配置文件而重啟nginx。
客戶端的解決方案相對服務(wù)端來說沒有依賴某個特定LB的場景,其實現(xiàn)也就比較簡單,因為幾乎所有的語言都支持linux環(huán)境下跨進(jìn)程通信(IPC)機制,因此只要幫助各個語言實現(xiàn)一個從共享內(nèi)存中獲取服務(wù)信息的API的客戶端即可,又由于本發(fā)明基于C++開發(fā)和服務(wù)注冊組件通信時生成了動態(tài)鏈接庫,因此只要該編程語言支持動態(tài)語言的接口即能快速實現(xiàn)其客戶端讀取服務(wù)的列表。
根據(jù)本發(fā)明上述實施例提供的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法,在客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,首先在共享內(nèi)存中查詢服務(wù)的服務(wù)提供者信息,若查詢到,則直接在共享內(nèi)存中讀取服務(wù)提供者信息;若未查詢到,則通過網(wǎng)絡(luò)去服務(wù)注冊組件中獲取服務(wù)提供者信息。利用本方法,達(dá)到了應(yīng)用層在獲取服務(wù)列表配置信息時和獲取本地內(nèi)存讀寫一樣的性能,減少了網(wǎng)絡(luò)延遲,提升了讀取速度,這種與后端分布式集群通信產(chǎn)生共享內(nèi)存并提供client供應(yīng)用使用的方式,避免了客戶端和分布式集群之間用長連接方式進(jìn)行對接而導(dǎo)致的資源占用過多、服務(wù)注冊組件處理效率低下的問題。另外,本方法通過生成動態(tài)鏈接庫向利用不同編程語言實現(xiàn)的客戶端提供統(tǒng)一的共享內(nèi)存查詢接口,解決了跨語言的通用性服務(wù)發(fā)現(xiàn)實現(xiàn)困難的問題。本發(fā)明基于Nginx開發(fā)了一個擴展模塊,使得nginx層可以通過該擴展模塊來動態(tài)獲取upstream的配置,從而解決了服務(wù)端的服務(wù)發(fā)現(xiàn)問題,又由于本發(fā)明基于C++開發(fā)和服務(wù)注冊組件通信時生成了動態(tài)鏈接庫,因此只要該編程語言支持動態(tài)語言的接口即能快速實現(xiàn)其客戶端讀取服務(wù)的列表,因而最終實現(xiàn)了兼容服務(wù)端的服務(wù)發(fā)現(xiàn)機制和客戶端的服務(wù)發(fā)現(xiàn)機制。
本發(fā)明實施例還提供了一種服務(wù)注冊集群中服務(wù)健康檢查的方法,其中服務(wù)健康檢查的作用主要是針對不健康的服務(wù)節(jié)點(服務(wù)提供者和/或服務(wù)消費者)進(jìn)行動態(tài)的摘除,以提升服務(wù)注冊集群的穩(wěn)定性和可靠性。該方法中,分布式健康檢查策略設(shè)計為主從(master-slave)架構(gòu)。
圖8示出了根據(jù)本發(fā)明一個實施例的服務(wù)注冊集群中服務(wù)健康檢查的架構(gòu)示意圖。如圖8所示,以服務(wù)注冊集群利用zookeeper技術(shù)實現(xiàn)為例,master選舉靠zookeeper來維系,主要涉及如下內(nèi)容:
1.所有健康檢查服務(wù)啟動后都將自己做為臨時節(jié)點注冊到zookeeper中;
2.所有的節(jié)點都監(jiān)聽zookeeper路徑/arch_group/healthcheck/election,當(dāng)有變更時表示需要重新選舉master;
3.master節(jié)點負(fù)責(zé)任務(wù)分配和健康檢查,具體分配方式是添加一個任務(wù)給自己,并將其他無關(guān)任務(wù)移除;
4.master的任務(wù)負(fù)責(zé)按照周期輪詢所有的providers,然后將這些providers的健康檢查分配給其他的健康檢查節(jié)點;
5.分配給其他節(jié)點的策略是發(fā)送一個HTTP請求讓slave節(jié)點添加一個健康檢查的任務(wù)。
slave節(jié)點需要執(zhí)行健康檢查任務(wù),主要涉及如下內(nèi)容:
1.slave節(jié)點除了監(jiān)聽master選舉外默認(rèn)啟動后什么都不做;
2.slave節(jié)點當(dāng)收到master節(jié)點發(fā)過來的添加任務(wù)的請求后開始執(zhí)行健康檢查任務(wù)。
有節(jié)點掛掉后策略:
1.由于所有的節(jié)點都監(jiān)聽了zookeeper的master選舉節(jié)點,當(dāng)有節(jié)點變更時集群所有節(jié)點都有感知;
2.當(dāng)感知到master節(jié)點掛掉后,重新選舉master,然后執(zhí)行master的任務(wù);
3.當(dāng)感知到slave節(jié)點掛掉后,master節(jié)點不再分配任務(wù)給該掛掉的slave節(jié)點。
實施例三
圖9示出了根據(jù)本發(fā)明一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)裝置的功能框圖。如圖9所示,該裝置包括:監(jiān)聽模塊301,獲取模塊302,寫入模塊303。
監(jiān)聽模塊301,適于監(jiān)聽并獲取消息隊列中記錄的服務(wù)名稱;其中,服務(wù)名稱是客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中未查詢到所述服務(wù)的服務(wù)提供者信息而寫入到消息隊列中。
獲取模塊302,適于根據(jù)所述服務(wù)名稱,從服務(wù)注冊組件處獲取所述服務(wù)的服務(wù)提供者信息;
寫入模塊303,適于將所述服務(wù)的服務(wù)提供者信息寫入共享內(nèi)存中,以供客戶端從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
監(jiān)聽模塊301進(jìn)一步適于:監(jiān)聽消息隊列中記錄的服務(wù)名稱;將消息隊列中記錄的服務(wù)名稱讀到內(nèi)存中,并及時清除消息隊列中記錄的服務(wù)名稱;從內(nèi)存中獲取所述服務(wù)名稱。
監(jiān)聽模塊301負(fù)責(zé)從消息隊列里取服務(wù)名稱。因為系統(tǒng)的消息隊列大小有限制,若隊列內(nèi)的數(shù)據(jù)未及時取走,則可能因為客戶端在短時間內(nèi)大量寫入服務(wù)名稱而將隊列填滿,之后的服務(wù)名稱將無法再寫入,造成錯誤。而本裝置獲得服務(wù)名稱后,需要通過網(wǎng)絡(luò)去服務(wù)注冊組件上取得服務(wù)提供者信息,相對較慢(10ms左右),因此很可能發(fā)生隊列的積壓填滿。為了避免出現(xiàn)這種問題,監(jiān)聽模塊301監(jiān)聽消息隊列中記錄的服務(wù)名稱,將消息隊列中記錄的服務(wù)名稱讀到內(nèi)存中,并及時清除消息隊列中記錄的服務(wù)名稱,防止填滿隊列。獲取模塊302從內(nèi)存里獲得需要讀取的服務(wù)名稱,再去服務(wù)注冊組件上取值。
進(jìn)一步的,該裝置還可包括:掃描模塊304,比對模塊305,更新模塊306。
掃描模塊304,適于每隔預(yù)定時間掃描共享內(nèi)存中的服務(wù)提供者信息;
比對模塊305,適于將共享內(nèi)存中的服務(wù)提供者信息與服務(wù)注冊組件中的服務(wù)提供者信息進(jìn)行比對;
更新模塊306,適于若比對不一致,則根據(jù)服務(wù)注冊組件中的服務(wù)提供者信息更新共享內(nèi)存中的服務(wù)提供者信息。
因為服務(wù)注冊組件的watcher機制不能設(shè)置為持久監(jiān)視,而是一次性的,也就是說,一個事件被觸發(fā)一次后,該watcher就被自動銷毀,如果要繼續(xù)監(jiān)視下次事件,只能重新注冊watcher。所以本發(fā)明采取的策略是事件發(fā)生后,第一時間先重新注冊watcher,再執(zhí)行具體的處理邏輯,盡量減少上個watcher銷毀與下個watcher注冊的時間間隔。盡管如此,這二者仍然不是事務(wù)性操作,因此仍有極小概率會丟失事件。為了防止這種情況發(fā)生,掃描模塊304會每隔30-60分鐘掃描共享內(nèi)存里的所有節(jié)點,比對模塊305將其與服務(wù)注冊組件上的最新值比較,若有差異則由更新模塊306更新到最新值,并為可能遺漏監(jiān)視的節(jié)點重新注冊watcher。
進(jìn)一步的,該裝置還可包括:生成模塊307,適于生成動態(tài)鏈接庫向利用不同編程語言實現(xiàn)的客戶端提供統(tǒng)一的共享內(nèi)存查詢接口。
為了解決跨語言的通用性服務(wù)發(fā)現(xiàn)實現(xiàn)困難的難題,本裝置提供的解決方案是不再在各個語言內(nèi)部進(jìn)行服務(wù)注冊組件的實現(xiàn),而是使用統(tǒng)一的編程語言,如C++編程語言對服務(wù)注冊組件API進(jìn)行調(diào)用和服務(wù)發(fā)現(xiàn)邏輯的封裝,用C++生成動態(tài)鏈接庫的方式來對外提供統(tǒng)一的服務(wù)發(fā)現(xiàn)的API。如圖6所示,服務(wù)發(fā)現(xiàn)策略實現(xiàn)的各個語言接入主要支持:Java,Python,php,C/C++,lua等,還可支持shell,go等語言。各個語言接入共享內(nèi)存主要通過動態(tài)鏈接庫來和共享內(nèi)存進(jìn)行通信,各個語言通過封裝動態(tài)鏈接庫和服務(wù)發(fā)現(xiàn)邏輯提供的服務(wù)發(fā)現(xiàn)的接口只有一個即:get_service,接口參數(shù)為namespace和algorithm,該函數(shù)根據(jù)algorithm參數(shù)對namespace下的providers進(jìn)行篩選從而返回一個provider出來給應(yīng)用層使用。
實施例四
圖10示出了根據(jù)本發(fā)明一個實施例的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)系統(tǒng)的功能框圖。如圖10所示,該系統(tǒng)包括:上述實施例描述的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)裝置401、共享內(nèi)存402、客戶端403以及服務(wù)注冊組件404。
客戶端403適于:在接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中查詢到所述服務(wù)的服務(wù)提供者信息,若未查詢到,則將服務(wù)名稱寫入到消息隊列中;若查詢到,則從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
客戶端404還適于:根據(jù)讀取的所述服務(wù)的服務(wù)提供者信息計算MD5值,將計算得到的MD5值與共享內(nèi)存中存儲的MD5值進(jìn)行比對,若比對不一致,則重新從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息。
從圖4所示的系統(tǒng)架構(gòu)圖上可以看出,裝置401與客戶端403并沒有直接的通訊,二者的交互的一個渠道是共享內(nèi)存402。共享內(nèi)存402的作用在于,客戶端403可能會多次讀取相同的配置項(其值可能并不會每次都改變),如果沒有在本機存儲這些配置項,那么就必然需要每次通過網(wǎng)絡(luò)去服務(wù)注冊組件404服務(wù)端讀取(相同的值),一是存在網(wǎng)絡(luò)延遲,二是服務(wù)注冊組件404本身性能并不高,不適合大量的頻繁讀操作。之所以選用共享內(nèi)存402這種存儲方式,是看中了其性能優(yōu)勢,節(jié)點信息在共享內(nèi)存402里以哈希表的形式存儲,因此查詢時間是常數(shù)級,實際測試一次讀取耗時在16us左右,完全可以滿足用戶對低延遲的要求。
裝置401與客戶端403交互的另一個渠道是消息隊列??蛻舳?03接收到應(yīng)用層訪問服務(wù)的請求之后,先去共享內(nèi)存402里檢索,若找到則直接返回,若未找到,則將該服務(wù)的名稱寫入消息隊列。而裝置401時刻監(jiān)視消息隊列中是否有數(shù)據(jù),一旦有數(shù)據(jù)被寫入,裝置401即讀出數(shù)據(jù)(服務(wù)名),再根據(jù)服務(wù)名去服務(wù)注冊組件404把服務(wù)提供者信息讀取回來,并寫入共享內(nèi)存402??蛻舳?03會等待直到共享內(nèi)存402里出現(xiàn)所要讀取的服務(wù)提供者信息,然后讀出服務(wù)提供者信息并返回。
由于涉及到多個進(jìn)程(裝置和客戶端進(jìn)程)對共享內(nèi)存402的同時讀寫,所以需要避免沖突。共享內(nèi)存402里同時存儲服務(wù)提供者信息與其MD5值,客戶端403會把二者一次全讀出,然后根據(jù)讀取的服務(wù)提供者信息計算MD5值,校驗MD5值是否正確,若不正確則會重新讀取,這就避免了裝置401尚未寫入完整的服務(wù)提供者信息被客戶端403讀走,也消除了鎖爭用,進(jìn)一步提升性能。
進(jìn)一步的,如圖7所示,本系統(tǒng)基于Nginx開發(fā)了一個LB擴展模塊,與客戶端和共享內(nèi)存通信連接,使客戶端通過LB擴展模塊與共享內(nèi)存進(jìn)行通信。具體地,使得nginx層可以通過該LB擴展模塊來動態(tài)獲取上游(upstream)的配置,從而解決了服務(wù)端的服務(wù)發(fā)現(xiàn)問題。
客戶端的解決方案相對服務(wù)端來說沒有依賴某個特定LB的場景,其實現(xiàn)也就比較簡單,因為幾乎所有的語言都支持linux環(huán)境下跨進(jìn)程通信(IPC)機制,因此只要幫助各個語言實現(xiàn)一個從共享內(nèi)存中獲取服務(wù)信息的API的客戶端即可,又由于本發(fā)明基于C++開發(fā)和服務(wù)注冊組件通信時生成了動態(tài)鏈接庫,因此只要該編程語言支持動態(tài)語言的接口即能快速實現(xiàn)其客戶端讀取服務(wù)的列表。
根據(jù)本發(fā)明上述實施例提供的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)裝置及系統(tǒng),在客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,首先在共享內(nèi)存中查詢服務(wù)的服務(wù)提供者信息,若查詢到,則直接在共享內(nèi)存中讀取服務(wù)提供者信息;若未查詢到,則通過網(wǎng)絡(luò)去服務(wù)注冊組件中獲取服務(wù)提供者信息。利用本裝置及系統(tǒng),達(dá)到了應(yīng)用層在獲取服務(wù)列表配置信息時和獲取本地內(nèi)存讀寫一樣的性能,減少了網(wǎng)絡(luò)延遲,提升了讀取速度,這種與后端分布式集群通信產(chǎn)生共享內(nèi)存并提供client供應(yīng)用使用的方式,避免了客戶端和分布式集群之間用長連接方式進(jìn)行對接而導(dǎo)致的資源占用過多、服務(wù)注冊組件處理效率低下的問題。另外,本裝置及系統(tǒng)通過生成動態(tài)鏈接庫向利用不同編程語言實現(xiàn)的客戶端提供統(tǒng)一的共享內(nèi)存查詢接口,解決了跨語言的通用性服務(wù)發(fā)現(xiàn)實現(xiàn)困難的問題。本系統(tǒng)基于Nginx開發(fā)了一個擴展模塊,使得nginx層可以通過該擴展模塊來動態(tài)獲取upstream的配置,從而解決了服務(wù)端的服務(wù)發(fā)現(xiàn)問題,又由于本發(fā)明基于C++開發(fā)和服務(wù)注冊組件通信時生成了動態(tài)鏈接庫,因此只要該編程語言支持動態(tài)語言的接口即能快速實現(xiàn)其客戶端讀取服務(wù)的列表,因而最終實現(xiàn)了兼容服務(wù)端的服務(wù)發(fā)現(xiàn)機制和客戶端的服務(wù)發(fā)現(xiàn)機制。
實施例五
本申請實施例五提供了一種非易失性計算機存儲介質(zhì),所述計算機存儲介質(zhì)存儲有至少一可執(zhí)行指令,該計算機可執(zhí)行指令可執(zhí)行上述任意方法實施例中的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法。
實施例六
圖11示出了根據(jù)本發(fā)明實施例六的一種服務(wù)器的結(jié)構(gòu)示意圖,本發(fā)明具體實施例并不對服務(wù)器的具體實現(xiàn)做限定。
如圖11所示,該服務(wù)器可以包括:處理器(processor)602、通信接口(Communications Interface)604、存儲器(memory)606、以及通信總線608。
其中:
處理器602、通信接口604、以及存儲器606通過通信總線608完成相互間的通信。
通信接口604,用于與其它設(shè)備比如客戶端或其它服務(wù)器等的網(wǎng)元通信。
處理器602,用于執(zhí)行程序610,具體可以執(zhí)行上述基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法實施例中的相關(guān)步驟。
具體地,程序610可以包括程序代碼,該程序代碼包括計算機操作指令。
處理器602可能是中央處理器CPU,或者是特定集成電路ASIC(Application Specific Integrated Circuit),或者是被配置成實施本發(fā)明實施例的一個或多個集成電路。服務(wù)器包括的一個或多個處理器,可以是同一類型的處理器,如一個或多個CPU;也可以是不同類型的處理器,如一個或多個CPU以及一個或多個ASIC。
存儲器606,用于存放程序610。存儲器606可能包含高速RAM存儲器,也可能還包括非易失性存儲器(non-volatile memory),例如至少一個磁盤存儲器。
程序610具體可以用于使得處理器602執(zhí)行以下操作:監(jiān)聽并獲取消息隊列中記錄的服務(wù)名稱;其中,所述服務(wù)名稱是客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中未查詢到所述服務(wù)的服務(wù)提供者信息而寫入到消息隊列中;根據(jù)所述服務(wù)名稱,從服務(wù)注冊組件處獲取所述服務(wù)的服務(wù)提供者信息;將所述服務(wù)的服務(wù)提供者信息寫入共享內(nèi)存中,以供客戶端從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
在一種可選的實施方式中,客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中查詢到所述服務(wù)的服務(wù)提供者信息,從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
在一種可選的實施方式中,程序610用于使得處理器602監(jiān)聽消息隊列中記錄的服務(wù)名稱;將消息隊列中記錄的服務(wù)名稱讀到內(nèi)存中,并及時清除消息隊列中記錄的服務(wù)名稱;從內(nèi)存中獲取所述服務(wù)名稱。
在一種可選的實施方式中,程序610用于使得處理器602每隔預(yù)定時間掃描共享內(nèi)存中的服務(wù)提供者信息;將共享內(nèi)存中的服務(wù)提供者信息與服務(wù)注冊組件中的服務(wù)提供者信息進(jìn)行比對;若比對不一致,則根據(jù)服務(wù)注冊組件中的服務(wù)提供者信息更新共享內(nèi)存中的服務(wù)提供者信息。
在一種可選的實施方式中,所述共享內(nèi)存中存儲有服務(wù)提供者信息及其MD5值;程序610用于使得處理器602根據(jù)讀取的所述服務(wù)的服務(wù)提供者信息計算MD5值,將計算得到的MD5值與共享內(nèi)存中存儲的MD5值進(jìn)行比對,若比對不一致,則重新從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息。
在一種可選的實施方式中,程序610用于使得處理器602生成動態(tài)鏈接庫向利用不同編程語言實現(xiàn)的客戶端提供統(tǒng)一的共享內(nèi)存查詢接口。
綜上,本發(fā)明實施例提供的上述解決方案達(dá)到了如下技術(shù)效果:
1.以客戶端最小侵入性的方式實現(xiàn)客戶端層服務(wù)發(fā)現(xiàn);
2.獲取服務(wù)列表實現(xiàn)了超高的性能和原生讀取內(nèi)存幾乎無差異;
3.客戶端層服務(wù)發(fā)現(xiàn)和服務(wù)端層LB都實現(xiàn)了使用統(tǒng)一接口的服務(wù)發(fā)現(xiàn)方式;
4.服務(wù)端層LB的服務(wù)發(fā)現(xiàn)使得后端服務(wù)動態(tài)擴容/縮容更獨立,無需通知依賴方服務(wù)變更,配置維護成本更低;
5.客戶端層服務(wù)發(fā)現(xiàn)使得客戶端有了自主負(fù)載均衡策略,客戶端對后端服務(wù)的選擇有了更大的自主空間,當(dāng)后端服務(wù)出現(xiàn)阻塞卡頓時,客戶端可以根據(jù)自己的重試策略來解決;
6.獨立的分布式服務(wù)健康檢查方案來實現(xiàn)服務(wù)節(jié)點的摘除策略;
7.與后端分布式集群通信產(chǎn)生共享內(nèi)存并提供client供應(yīng)用使用的方式,避免了客戶端和分布式集群之間用長連接方式進(jìn)行對接而導(dǎo)致的資源占用過多、服務(wù)注冊組件處理效率低下的問題;
8.統(tǒng)一通過REST(Representational State Transfer,表述性狀態(tài)傳遞)風(fēng)格的API提供對后端分布式集群進(jìn)行修改和刪除操作,使得節(jié)點變更前后能夠得到統(tǒng)一的控制。
在此提供的算法和顯示不與任何特定計算機、虛擬系統(tǒng)或者其它設(shè)備固有相關(guān)。各種通用系統(tǒng)也可以與基于在此的示教一起使用。根據(jù)上面的描述,構(gòu)造這類系統(tǒng)所要求的結(jié)構(gòu)是顯而易見的。此外,本發(fā)明也不針對任何特定編程語言。應(yīng)當(dāng)明白,可以利用各種編程語言實現(xiàn)在此描述的本發(fā)明的內(nèi)容,并且上面對特定語言所做的描述是為了披露本發(fā)明的最佳實施方式。
在此處所提供的說明書中,說明了大量具體細(xì)節(jié)。然而,能夠理解,本發(fā)明的實施例可以在沒有這些具體細(xì)節(jié)的情況下實踐。在一些實例中,并未詳細(xì)示出公知的方法、結(jié)構(gòu)和技術(shù),以便不模糊對本說明書的理解。
類似地,應(yīng)當(dāng)理解,為了精簡本公開并幫助理解各個發(fā)明方面中的一個或多個,在上面對本發(fā)明的示例性實施例的描述中,本發(fā)明的各個特征有時被一起分組到單個實施例、圖、或者對其的描述中。然而,并不應(yīng)將該公開的方法解釋成反映如下意圖:即所要求保護的本發(fā)明要求比在每個權(quán)利要求中所明確記載的特征更多的特征。更確切地說,如下面的權(quán)利要求書所反映的那樣,發(fā)明方面在于少于前面公開的單個實施例的所有特征。因此,遵循具體實施方式的權(quán)利要求書由此明確地并入該具體實施方式,其中每個權(quán)利要求本身都作為本發(fā)明的單獨實施例。
本領(lǐng)域那些技術(shù)人員可以理解,可以對實施例中的設(shè)備中的模塊進(jìn)行自適應(yīng)性地改變并且把它們設(shè)置在與該實施例不同的一個或多個設(shè)備中??梢园褜嵤├械哪K或單元或組件組合成一個模塊或單元或組件,以及此外可以把它們分成多個子模塊或子單元或子組件。除了這樣的特征和/或過程或者單元中的至少一些是相互排斥之外,可以采用任何組合對本說明書(包括伴隨的權(quán)利要求、摘要和附圖)中公開的所有特征以及如此公開的任何方法或者設(shè)備的所有過程或單元進(jìn)行組合。除非另外明確陳述,本說明書(包括伴隨的權(quán)利要求、摘要和附圖)中公開的每個特征可以由提供相同、等同或相似目的的替代特征來代替。
此外,本領(lǐng)域的技術(shù)人員能夠理解,盡管在此所述的一些實施例包括其它實施例中所包括的某些特征而不是其它特征,但是不同實施例的特征的組合意味著處于本發(fā)明的范圍之內(nèi)并且形成不同的實施例。例如,在下面的權(quán)利要求書中,所要求保護的實施例的任意之一都可以以任意的組合方式來使用。
應(yīng)該注意的是上述實施例對本發(fā)明進(jìn)行說明而不是對本發(fā)明進(jìn)行限制,并且本領(lǐng)域技術(shù)人員在不脫離所附權(quán)利要求的范圍的情況下可設(shè)計出替換實施例。在權(quán)利要求中,不應(yīng)將位于括號之間的任何參考符號構(gòu)造成對權(quán)利要求的限制。單詞“包含”不排除存在未列在權(quán)利要求中的元件或步驟。位于元件之前的單詞“一”或“一個”不排除存在多個這樣的元件。本發(fā)明可以借助于包括有若干不同元件的硬件以及借助于適當(dāng)編程的計算機來實現(xiàn)。在列舉了若干裝置的單元權(quán)利要求中,這些裝置中的若干個可以是通過同一個硬件項來具體體現(xiàn)。單詞第一、第二、以及第三等的使用不表示任何順序??蓪⑦@些單詞解釋為名稱。
本發(fā)明公開了:A1、一種基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法,包括:
監(jiān)聽并獲取消息隊列中記錄的服務(wù)名稱;其中,所述服務(wù)名稱是客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中未查詢到所述服務(wù)的服務(wù)提供者信息而寫入到消息隊列中;
根據(jù)所述服務(wù)名稱,從服務(wù)注冊組件處獲取所述服務(wù)的服務(wù)提供者信息;
將所述服務(wù)的服務(wù)提供者信息寫入共享內(nèi)存中,以供客戶端從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
A2、根據(jù)A1所述的方法,其中,所述方法還包括:客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中查詢到所述服務(wù)的服務(wù)提供者信息,從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
A3、根據(jù)A1所述的方法,其中,所述監(jiān)聽并獲取消息隊列中記錄的服務(wù)名稱進(jìn)一步包括:
監(jiān)聽消息隊列中記錄的服務(wù)名稱;
將消息隊列中記錄的服務(wù)名稱讀到內(nèi)存中,并及時清除消息隊列中記錄的服務(wù)名稱;
從內(nèi)存中獲取所述服務(wù)名稱。
A4、根據(jù)A1所述的方法,其中,所述方法還包括:
每隔預(yù)定時間掃描共享內(nèi)存中的服務(wù)提供者信息;
將共享內(nèi)存中的服務(wù)提供者信息與服務(wù)注冊組件中的服務(wù)提供者信息進(jìn)行比對;
若比對不一致,則根據(jù)服務(wù)注冊組件中的服務(wù)提供者信息更新共享內(nèi)存中的服務(wù)提供者信息。
A5、根據(jù)A1或A2所述的方法,其中,所述共享內(nèi)存中存儲有服務(wù)提供者信息及其MD5值;
在客戶端從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息之后,所述方法還包括:根據(jù)讀取的所述服務(wù)的服務(wù)提供者信息計算MD5值,將計算得到的MD5值與共享內(nèi)存中存儲的MD5值進(jìn)行比對,若比對不一致,則重新從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息。
A6、根據(jù)A1所述的方法,其中,所述方法還包括:生成動態(tài)鏈接庫向利用不同編程語言實現(xiàn)的客戶端提供統(tǒng)一的共享內(nèi)存查詢接口。
本發(fā)明還公開了:B7、一種基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)裝置,包括:
監(jiān)聽模塊,適于監(jiān)聽并獲取消息隊列中記錄的服務(wù)名稱;其中,所述服務(wù)名稱是客戶端接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中未查詢到所述服務(wù)的服務(wù)提供者信息而寫入到消息隊列中;
獲取模塊,適于根據(jù)所述服務(wù)名稱,從服務(wù)注冊組件處獲取所述服務(wù)的服務(wù)提供者信息;
寫入模塊,適于將所述服務(wù)的服務(wù)提供者信息寫入共享內(nèi)存中,以供客戶端從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
B8、根據(jù)B7所述的裝置,其中,所述監(jiān)聽模塊進(jìn)一步適于:
監(jiān)聽消息隊列中記錄的服務(wù)名稱;
將消息隊列中記錄的服務(wù)名稱讀到內(nèi)存中,并及時清除消息隊列中記錄的服務(wù)名稱;
從內(nèi)存中獲取所述服務(wù)名稱。
B9、根據(jù)B7所述的裝置,其中,所述裝置還包括:
掃描模塊,適于每隔預(yù)定時間掃描共享內(nèi)存中的服務(wù)提供者信息;
比對模塊,適于將共享內(nèi)存中的服務(wù)提供者信息與服務(wù)注冊組件中的服務(wù)提供者信息進(jìn)行比對;
更新模塊,適于若比對不一致,則根據(jù)服務(wù)注冊組件中的服務(wù)提供者信息更新共享內(nèi)存中的服務(wù)提供者信息。
B10、根據(jù)B7所述的裝置,其中,所述裝置還包括:生成模塊,適于生成動態(tài)鏈接庫向利用不同編程語言實現(xiàn)的客戶端提供統(tǒng)一的共享內(nèi)存查詢接口。
本發(fā)明還公開了:C11、一種基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)系統(tǒng),包括:B7-B10任一項所述的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)裝置、共享內(nèi)存、客戶端以及服務(wù)注冊組件;
所述客戶端適于:在接收到應(yīng)用層訪問服務(wù)的請求之后,在共享內(nèi)存中查詢到所述服務(wù)的服務(wù)提供者信息,若未查詢到,則將服務(wù)名稱寫入到消息隊列中;若查詢到,則從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息并返回給應(yīng)用層。
C12、根據(jù)C11所述的系統(tǒng),其中,所述客戶端還適于:根據(jù)讀取的所述服務(wù)的服務(wù)提供者信息計算MD5值,將計算得到的MD5值與共享內(nèi)存中存儲的MD5值進(jìn)行比對,若比對不一致,則重新從共享內(nèi)存中讀取所述服務(wù)的服務(wù)提供者信息。
C13、根據(jù)C11所述的系統(tǒng),其中,還包括:LB擴展模塊,與客戶端和共享內(nèi)存通信連接,使客戶端通過LB擴展模塊與共享內(nèi)存進(jìn)行通信。
本發(fā)明還公開了:D14、一種服務(wù)器,包括:處理器、存儲器、通信接口和通信總線,所述處理器、所述存儲器和所述通信接口通過所述通信總線完成相互間的通信;
所述存儲器用于存放至少一可執(zhí)行指令,所述可執(zhí)行指令使所述處理器執(zhí)行如A1-A6中任一項所述的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法對應(yīng)的操作。
本發(fā)明還公開了:E15、一種計算機存儲介質(zhì),所述存儲介質(zhì)中存儲有至少一可執(zhí)行指令,所述可執(zhí)行指令使所述處理器執(zhí)行如A1-A6中任一項所述的基于共享內(nèi)存的服務(wù)發(fā)現(xiàn)方法對應(yīng)的操作。