十年網(wǎng)站開(kāi)發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無(wú)憂售后,網(wǎng)站問(wèn)題一站解決
遠(yuǎn)程過(guò)程調(diào)用 (RPC) 是一種協(xié)議,程序可使用這種協(xié)議向網(wǎng)絡(luò)中的另一臺(tái)計(jì)算機(jī)上的程序請(qǐng)求服務(wù)。由于使用 RPC 的程序不必了解支持通信的網(wǎng)絡(luò)協(xié)議的情況,因此 RPC 提高了程序的互操作性。在 RPC 中,發(fā)出請(qǐng)求的程序是客戶程序,而提供服務(wù)的程序是服務(wù)器。 \x0d\x0aRPC 中處理 TCP/IP 上的消息交換的部分存在一個(gè)缺陷。錯(cuò)誤地處理格式不正確的消息會(huì)導(dǎo)致出現(xiàn)錯(cuò)誤。這種特定的錯(cuò)誤會(huì)影響底層的 DCOM 接口,此接口偵聽(tīng) TCP/IP 端口 135。通過(guò)發(fā)送格式不正確的 RPC 消息,攻擊者可以使一臺(tái)計(jì)算機(jī)上的 RPC 服務(wù)出現(xiàn)問(wèn)題,進(jìn)而使任意代碼得以執(zhí)行。 \x0d\x0a遠(yuǎn)程過(guò)程調(diào)用 (RPC) 是 Windows 操作系統(tǒng)使用的一個(gè)協(xié)議。RPC 提供了一種進(jìn)程間通信機(jī)制,通過(guò)這一機(jī)制,在一臺(tái)計(jì)算機(jī)上運(yùn)行的程序可以順暢地執(zhí)行某個(gè)遠(yuǎn)程系統(tǒng)上的代碼。該協(xié)議本身是從 OSF(開(kāi)放式軟件基礎(chǔ))RPC 協(xié)議衍生出來(lái)的,只是增加了一些 Microsoft 特定的擴(kuò)展。 \x0d\x0a\x0d\x0aRPC 中處理通過(guò) TCP/IP 的消息交換的部分有一個(gè)漏洞。此問(wèn)題是由錯(cuò)誤地處理格式不正確的消息造成的。這種特定的漏洞影響分布式組件對(duì)象模型 (DCOM) 與 RPC 間的一個(gè)接口,此接口偵聽(tīng) TCP/IP 端口 135。此接口處理客戶端計(jì)算機(jī)向服務(wù)器發(fā)送的 DCOM 對(duì)象激活請(qǐng)求(例如通用命名約定 (UNC) 路徑)。 \x0d\x0a\x0d\x0a為利用此漏洞,攻擊者可能需要向遠(yuǎn)程計(jì)算機(jī)上的 135 端口發(fā)送特殊格式的請(qǐng)求。 \x0d\x0a\x0d\x0a減輕影響的因素: \x0d\x0a\x0d\x0a為利用此漏洞,攻擊者可能需要擁有向遠(yuǎn)程計(jì)算機(jī)上的 135 端口發(fā)送精心編造的請(qǐng)求的能力。對(duì)于 Intranet 環(huán)境,此端口通常是可以訪問(wèn)的;但對(duì)于通過(guò) Internet 相連的計(jì)算機(jī),防火墻通常會(huì)封堵 135 端口。如果沒(méi)有封堵該端口,或者在 Intranet 環(huán)境中,攻擊者就不需要有任何其他特權(quán)。 \x0d\x0a\x0d\x0a最佳做法是封堵所有實(shí)際上未使用的 TCP/IP 端口。因此,大多數(shù)連接到 Internet 的計(jì)算機(jī)應(yīng)當(dāng)封堵 135 端口。RPC over TCP 不適合在 Internet 這樣存在著危險(xiǎn)的環(huán)境中使用。像 RPC over HTTP 這樣更堅(jiān)實(shí)的協(xié)議適用于有潛在危險(xiǎn)的環(huán)境。 \x0d\x0a這是一個(gè)緩沖區(qū)溢出漏洞。成功利用此漏洞的攻擊者有可能獲得對(duì)遠(yuǎn)程計(jì)算機(jī)的完全控制。這可能使攻擊者能夠?qū)Ψ?wù)器隨意執(zhí)行操作,包括更改網(wǎng)頁(yè)、重新格式化硬盤或向本地管理員組添加新的用戶。 \x0d\x0a\x0d\x0a要發(fā)動(dòng)此類攻擊,攻擊者需要能夠向 RPC 服務(wù)發(fā)送一條格式不正確的消息,從而造成目標(biāo)計(jì)算機(jī)受制于人,攻擊者可以在它上面執(zhí)行任意代碼。 \x0d\x0a\x0d\x0a防范來(lái)自 Internet 的遠(yuǎn)程 RPC 攻擊的最佳方法是:將防火墻配置為封堵 135 端口。RPC over TCP 不適合在 Internet 這樣存在著危險(xiǎn)的環(huán)境中使用。 \x0d\x0a\x0d\x0a此漏洞是由于 Windows RPC 服務(wù)在某些情況下不能正確檢查消息輸入而造成的。如果攻擊者在 RPC 建立連接后發(fā)送某種類型的格式不正確的 RPC 消息,則會(huì)導(dǎo)致遠(yuǎn)程計(jì)算機(jī)上與 RPC 之間的基礎(chǔ)分布式組件對(duì)象模型 (DCOM) 接口出現(xiàn)問(wèn)題,進(jìn)而使任意代碼得以執(zhí)行。
創(chuàng)新互聯(lián)公司從2013年開(kāi)始,先為土默特右旗等服務(wù)建站,土默特右旗等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為土默特右旗企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。
作者 | Python編程時(shí)光
責(zé)編 | 胡巍巍
什么是RPC呢?百度百科給出的解釋是這樣的:“RPC(Remote Procedure Call Protocol)——遠(yuǎn)程過(guò)程調(diào)用協(xié)議,它是一種通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議”。
這個(gè)概念聽(tīng)起來(lái)還是比較抽象,沒(méi)關(guān)系,繼續(xù)往后看,后面概念性的東西,我會(huì)講得足夠清楚,讓你完全掌握 RPC 的基礎(chǔ)內(nèi)容。
在 OpenStack 里的進(jìn)程間通信方式主要有兩種,一種是基于HTTP協(xié)議的RESTFul API方式,另一種則是RPC調(diào)用。
那么這兩種方式在應(yīng)用場(chǎng)景上有何區(qū)別呢?
有使用經(jīng)驗(yàn)的人,就會(huì)知道:
首先,給你提兩個(gè)問(wèn)題,帶著這兩個(gè)問(wèn)題再往下看:
1、RPC 和 REST 區(qū)別是什么?2、為什么要采用RPC呢?
首先,第一個(gè)問(wèn)題:RPC 和 REST 區(qū)別是什么?
你一定會(huì)覺(jué)得這個(gè)問(wèn)題很奇怪,是的,包括我,但是你在網(wǎng)絡(luò)上一搜,會(huì)發(fā)現(xiàn)類似對(duì)比的文章比比皆是,我在想可能很多初學(xué)者由于基礎(chǔ)不牢固,才會(huì)將不相干的二者拿出來(lái)對(duì)比吧。既然是這樣,那為了讓你更加了解陌生的RPC,就從你熟悉得不能再熟悉的 REST 入手吧。
01、所屬類別不同
REST,是Representational State Transfer 的簡(jiǎn)寫,中文描述表述性狀態(tài)傳遞(是指某個(gè)瞬間狀態(tài)的資源數(shù)據(jù)的快照,包括資源數(shù)據(jù)的內(nèi)容、表述格式(XML、JSON)等信息。)
REST 是一種軟件架構(gòu)風(fēng)格。這種風(fēng)格的典型應(yīng)用,就是HTTP。其因?yàn)楹?jiǎn)單、擴(kuò)展性強(qiáng)的特點(diǎn)而廣受開(kāi)發(fā)者的青睞。
而RPC 呢,是 Remote Procedure Call Protocol 的簡(jiǎn)寫,中文描述是遠(yuǎn)程過(guò)程調(diào)用,它可以實(shí)現(xiàn)客戶端像調(diào)用本地服務(wù)(方法)一樣調(diào)用服務(wù)器的服務(wù)(方法)。
而 RPC 可以基于 TCP/UDP,也可以基于 HTTP 協(xié)議進(jìn)行傳輸?shù)?,按理說(shuō)它和REST不是一個(gè)層面意義上的東西,不應(yīng)該放在一起討論,但是誰(shuí)讓REST這么流行呢,它是目前最流行的一套互聯(lián)網(wǎng)應(yīng)用程序的API設(shè)計(jì)標(biāo)準(zhǔn),某種意義下,我們說(shuō) REST 可以其實(shí)就是指代 HTTP 協(xié)議。
02、使用方式不同
03、面向?qū)ο蟛煌?/p>
從設(shè)計(jì)上來(lái)看,RPC,所謂的遠(yuǎn)程過(guò)程調(diào)用 ,是面向方法的 ,REST:所謂的 Representational state transfer ,是面向資源的,除此之外,還有一種叫做 SOA,所謂的面向服務(wù)的架構(gòu),它是面向消息的,這個(gè)接觸不多,就不多說(shuō)了。
04、序列化協(xié)議不同
接口調(diào)用通常包含兩個(gè)部分,序列化和通信協(xié)議。
通信協(xié)議,上面已經(jīng)提及了,REST 是 基于 HTTP 協(xié)議,而 RPC 可以基于 TCP/UDP,也可以基于 HTTP 協(xié)議進(jìn)行傳輸?shù)摹?/p>
常見(jiàn)的序列化協(xié)議,有:json、xml、hession、protobuf、thrift、text、bytes等,REST 通常使用的是 JSON或者XML,而 RPC 使用的是 JSON-RPC,或者 XML-RPC。
通過(guò)以上幾點(diǎn),我們知道了 REST 和 RPC 之間有很明顯的差異。
然后第二個(gè)問(wèn)題:為什么要采用RPC呢?
那到底為何要使用 RPC,單純的依靠RESTful API不可以嗎?為什么要搞這么多復(fù)雜的協(xié)議,渣渣表示真的學(xué)不過(guò)來(lái)了。
關(guān)于這一點(diǎn),以下幾點(diǎn)僅是我的個(gè)人猜想,僅供交流哈:
說(shuō)了這么多,我們?cè)撊绾芜x擇這兩者呢?我總結(jié)了如下兩點(diǎn),供你參考:
“遠(yuǎn)程調(diào)用”意思就是:被調(diào)用方法的具體實(shí)現(xiàn)不在程序運(yùn)行本地,而是在別的某個(gè)地方(分布到各個(gè)服務(wù)器),調(diào)用者只想要函數(shù)運(yùn)算的結(jié)果,卻不需要實(shí)現(xiàn)函數(shù)的具體細(xì)節(jié)。
光說(shuō)不練嘴把式,接下來(lái),我將分別用三種不同的方式全面地讓你搞明白 rpc 遠(yuǎn)程調(diào)用是如何實(shí)現(xiàn)的。
01、基于 xml-rpc
Python實(shí)現(xiàn) rpc,可以使用標(biāo)準(zhǔn)庫(kù)里的 SimpleXMLRPCServer,它是基于XML-RPC 協(xié)議的。
有了這個(gè)模塊,開(kāi)啟一個(gè) rpc server,就變得相當(dāng)簡(jiǎn)單了。執(zhí)行以下代碼:
有了 rpc server,接下來(lái)就是 rpc client,由于我們上面使用的是 XML-RPC,所以 rpc clinet 需要使用xmlrpclib 這個(gè)庫(kù)。
然后,我們通過(guò) server_proxy 對(duì)象就可以遠(yuǎn)程調(diào)用之前的rpc server的函數(shù)了。
SimpleXMLRPCServer是一個(gè)單線程的服務(wù)器。這意味著,如果幾個(gè)客戶端同時(shí)發(fā)出多個(gè)請(qǐng)求,其它的請(qǐng)求就必須等待第一個(gè)請(qǐng)求完成以后才能繼續(xù)。
若非要使用 SimpleXMLRPCServer 實(shí)現(xiàn)多線程并發(fā),其實(shí)也不難。只要將代碼改成如下即可。
02、基于json-rpc
SimpleXMLRPCServer 是基于 xml-rpc 實(shí)現(xiàn)的遠(yuǎn)程調(diào)用,上面我們也提到 除了 xml-rpc 之外,還有 json-rpc 協(xié)議。
那 python 如何實(shí)現(xiàn)基于 json-rpc 協(xié)議呢?
答案是很多,很多web框架其自身都自己實(shí)現(xiàn)了json-rpc,但我們要獨(dú)立這些框架之外,要尋求一種較為干凈的解決方案,我查找到的選擇有兩種
第一種是 jsonrpclib
第二種是 python-jsonrpc
先來(lái)看第一種 jsonrpclib
它與 Python 標(biāo)準(zhǔn)庫(kù)的 SimpleXMLRPCServer 很類似(因?yàn)樗念惷徒凶?SimpleJSONRPCServer ,不明真相的人真以為它們是親兄弟)?;蛟S可以說(shuō),jsonrpclib 就是仿照 SimpleXMLRPCServer 標(biāo)準(zhǔn)庫(kù)來(lái)進(jìn)行編寫的。
它的導(dǎo)入與 SimpleXMLRPCServer 略有不同,因?yàn)镾impleJSONRPCServer分布在jsonrpclib庫(kù)中。
服務(wù)端
客戶端
再來(lái)看第二種python-jsonrpc,寫起來(lái)貌似有些復(fù)雜。
服務(wù)端
客戶端
調(diào)用過(guò)程如下
還記得上面我提到過(guò)的 zabbix API,因?yàn)槲矣薪佑|過(guò),所以也拎出來(lái)講講。zabbix API 也是基于 json-rpc 2.0協(xié)議實(shí)現(xiàn)的。
因?yàn)閮?nèi)容較多,這里只帶大家打個(gè),zabbix 是如何調(diào)用的:直接指明要調(diào)用 zabbix server 的哪個(gè)方法,要傳給這個(gè)方法的參數(shù)有哪些。
03、基于 zerorpc
以上介紹的兩種rpc遠(yuǎn)程調(diào)用方式,如果你足夠細(xì)心,可以發(fā)現(xiàn)他們都是http+rpc 兩種協(xié)議結(jié)合實(shí)現(xiàn)的。
接下來(lái),我們要介紹的這種(zerorpc),就不再使用走 http 了。
zerorpc 這個(gè)第三方庫(kù),它是基于TCP協(xié)議、 ZeroMQ 和 MessagePack的,速度相對(duì)快,響應(yīng)時(shí)間短,并發(fā)高。zerorpc 和 pyjsonrpc 一樣,需要額外安裝,雖然SimpleXMLRPCServer不需要額外安裝,但是SimpleXMLRPCServer性能相對(duì)差一些。
調(diào)用過(guò)程如下
客戶端除了可以使用zerorpc框架實(shí)現(xiàn)代碼調(diào)用之外,它還支持使用“命令行”的方式調(diào)用。
客戶端可以使用命令行,那服務(wù)端是不是也可以呢?
是的,通過(guò) Github 上的文檔幾個(gè) demo 可以體驗(yàn)到這個(gè)第三方庫(kù)做真的是優(yōu)秀。
比如我們可以用下面這個(gè)命令,創(chuàng)建一個(gè)rpc server,后面這個(gè) time Python 標(biāo)準(zhǔn)庫(kù)中的 time 模塊,zerorpc 會(huì)將 time 注冊(cè)綁定以供client調(diào)用。
經(jīng)過(guò)了上面的學(xué)習(xí),我們已經(jīng)學(xué)會(huì)了如何使用多種方式實(shí)現(xiàn)rpc遠(yuǎn)程調(diào)用。
通過(guò)對(duì)比,zerorpc 可以說(shuō)是脫穎而出,一支獨(dú)秀。
為此,我也做了一番思考:
OpenStack 組件繁多,在一個(gè)較大的集群內(nèi)部每個(gè)組件內(nèi)部通過(guò)rpc通信頻繁,如果都采用rpc直連調(diào)用的方式,連接數(shù)會(huì)非常地多,開(kāi)銷大,若有些 server 是單線程的模式,超時(shí)會(huì)非常的嚴(yán)重。
OpenStack 是復(fù)雜的分布式集群架構(gòu),會(huì)有多個(gè) rpc server 同時(shí)工作,假設(shè)有 server01,server02,server03 三個(gè)server,當(dāng) rpc client 要發(fā)出rpc請(qǐng)求時(shí),發(fā)給哪個(gè)好呢?這是問(wèn)題一。
你可能會(huì)說(shuō)輪循或者隨機(jī),這樣對(duì)大家都公平。這樣的話還會(huì)引出另一個(gè)問(wèn)題,倘若請(qǐng)求剛好發(fā)到server01,而server01剛好不湊巧,可能由于機(jī)器或者其他因?yàn)閷?dǎo)致服務(wù)沒(méi)在工作,那這個(gè)rpc消息可就直接失敗了呀。要知道做為一個(gè)集群,高可用是基本要求,如果出現(xiàn)剛剛那樣的情況其實(shí)是很尷尬的。這是問(wèn)題二。
集群有可能根據(jù)實(shí)際需要擴(kuò)充節(jié)點(diǎn)數(shù)量,如果使用直接調(diào)用,耦合度太高,不利于部署和生產(chǎn)。這是問(wèn)題三。
引入消息中間件,可以很好的解決這些問(wèn)題。
解決問(wèn)題一:消息只有一份,接收者由AMQP的負(fù)載算法決定,默認(rèn)為在所有Receiver中均勻發(fā)送(round robin)。
解決問(wèn)題二:有了消息中間件做緩沖站,client 可以任性隨意的發(fā),server 都掛掉了?沒(méi)有關(guān)系,等 server 正常工作后,自己來(lái)消息中間件取就行了。
解決問(wèn)題三:無(wú)論有多少節(jié)點(diǎn),它們只要認(rèn)識(shí)消息中間件這一個(gè)中介就足夠了。
既然講到了消息隊(duì)列,如果你之前沒(méi)有接觸過(guò)這塊內(nèi)容,最好花幾分鐘的時(shí)間跟我好好過(guò)下關(guān)于消息隊(duì)列的幾個(gè)基礎(chǔ)概念。
首先,RPC只是定義了一個(gè)通信接口,其底層的實(shí)現(xiàn)可以各不相同,可以是 socket,也可以是今天要講的 AMQP。
AMQP(Advanced Message Queuing Protocol)是一種基于隊(duì)列的可靠消息服務(wù)協(xié)議,作為一種通信協(xié)議,AMQP同樣存在多個(gè)實(shí)現(xiàn),如Apache Qpid,RabbitMQ等。
以下是 AMQP 中的幾個(gè)必知的概念:
Publisher:消息發(fā)布者
Queue:用來(lái)保存消息的存儲(chǔ)空間,消息沒(méi)有被receiver前,保存在隊(duì)列中。
Exchange:用來(lái)接收Publisher發(fā)出的消息,根據(jù)Routing key 轉(zhuǎn)發(fā)消息到對(duì)應(yīng)的Message Queue中,至于轉(zhuǎn)到哪個(gè)隊(duì)列里,這個(gè)路由算法又由exchange type決定的。
Exchange type:主要四種描述exchange的類型。
direct:消息路由到滿足此條件的隊(duì)列中(queue,可以有多個(gè)):routing key = binding key
topic:消息路由到滿足此條件的隊(duì)列中(queue,可以有多個(gè)):routing key 匹配 binding pattern. binding pattern是類似正則表達(dá)式的字符串,可以滿足復(fù)雜的路由條件。
fanout:消息路由到多有綁定到該exchange的隊(duì)列中。
binding :binding是用來(lái)描述exchange和queue之間的關(guān)系的概念,一個(gè)exchang可以綁定多個(gè)隊(duì)列,這些關(guān)系由binding建立。前面說(shuō)的binding key /binding pattern也是在binding中給出。
為了讓你明白這幾者的關(guān)系,我畫了一張模型圖。
關(guān)于AMQP,有幾下幾點(diǎn)值得注意:
前面鋪墊了那么久,終于到了講真實(shí)應(yīng)用的場(chǎng)景。在生產(chǎn)中RPC是如何應(yīng)用的呢?
其他模型我不太清楚,在 OpenStack 中的應(yīng)用模型是這樣的
至于為什么要如此設(shè)計(jì),前面我已經(jīng)給出了自己的觀點(diǎn)。
接下來(lái),就是源碼解讀 OpenStack ,看看其是如何通過(guò)rpc進(jìn)行遠(yuǎn)程調(diào)用的。如若你對(duì)此沒(méi)有興趣(我知道很多人對(duì)此都沒(méi)有興趣,所以不浪費(fèi)大家時(shí)間),可以直接跳過(guò)這一節(jié),進(jìn)入下一節(jié)。
目前Openstack中有兩種RPC實(shí)現(xiàn),一種是在oslo messaging,一種是在openstack.common.rpc。
openstack.common.rpc是舊的實(shí)現(xiàn),oslo messaging是對(duì)openstack.common.rpc的重構(gòu)。openstack.common.rpc在每個(gè)項(xiàng)目中都存在一份拷貝,oslo messaging即將這些公共代碼抽取出來(lái),形成一個(gè)新的項(xiàng)目。oslo messaging也對(duì)RPC API 進(jìn)行了重新設(shè)計(jì),對(duì)多種 transport 做了進(jìn)一步封裝,底層也是用到了kombu這個(gè)AMQP庫(kù)。(注:Kombu 是Python中的messaging庫(kù)。Kombu旨在通過(guò)為AMQ協(xié)議提供慣用的高級(jí)接口,使Python中的消息傳遞盡可能簡(jiǎn)單,并為常見(jiàn)的消息傳遞問(wèn)題提供經(jīng)過(guò)驗(yàn)證和測(cè)試的解決方案。)
關(guān)于oslo_messaging庫(kù),主要提供了兩種獨(dú)立的API:
因?yàn)?notify 實(shí)現(xiàn)是太簡(jiǎn)單了,所以這里我就不多說(shuō)了,如果有人想要看這方面內(nèi)容,可以收藏我的博客() ,我會(huì)更新補(bǔ)充 notify 的內(nèi)容。
OpenStack RPC 模塊提供了 rpc.call,rpc.cast, rpc.fanout_cast 三種 RPC 調(diào)用方法,發(fā)送和接收 RPC 請(qǐng)求。
rpc.call 和 .rpc.cast 從實(shí)現(xiàn)代碼上看,他們的區(qū)別很小,就是call調(diào)用時(shí)候會(huì)帶有wait_for_reply=True參數(shù),而cast不帶。
要了解 rpc 的調(diào)用機(jī)制呢,首先要知道 oslo_messaging 的幾個(gè)概念主要方法有四個(gè):
transport:RPC功能的底層實(shí)現(xiàn)方法,這里是rabbitmq的消息隊(duì)列的訪問(wèn)路徑
transport 就是定義你如何訪連接消息中間件,比如你使用的是 Rabbitmq,那在 nova.conf中應(yīng)該有一行transport_url的配置,可以很清楚地看出指定了 rabbitmq 為消息中間件,并配置了連接rabbitmq的user,passwd,主機(jī),端口。
target用來(lái)表述 RPC 服務(wù)器監(jiān)聽(tīng)topic,server名稱和server監(jiān)聽(tīng)的exchange,是否廣播fanout。
rpc server 要獲取消息,需要定義target,就像一個(gè)門牌號(hào)一樣。
rpc client 要發(fā)送消息,也需要有target,說(shuō)明消息要發(fā)到哪去。
endpoints:是可供別人遠(yuǎn)程調(diào)用的對(duì)象
RPC服務(wù)器暴露出endpoint,每個(gè) endpoint 包涵一系列的可被遠(yuǎn)程客戶端通過(guò) transport 調(diào)用的方法。直觀理解,可以參考nova-conductor創(chuàng)建rpc server的代碼,這邊的endpoints就是 nova/manager.py:ConductorManager
dispatcher:分發(fā)器,這是 rpc server 才有的概念
只有通過(guò)它 server 端才知道接收到的rpc請(qǐng)求,要交給誰(shuí)處理,怎么處理?
在client端,是這樣指定要調(diào)用哪個(gè)方法的。
而在server端,是如何知道要執(zhí)行這個(gè)方法的呢?這就是dispatcher 要干的事,它從 endpoint 里找到這個(gè)方法,然后執(zhí)行,最后返回。
Serializer:在 python 對(duì)象和message(notification) 之間數(shù)據(jù)做序列化或是反序列化的基類。
主要方法有四個(gè):
每個(gè)notification listener都和一個(gè)executor綁定,來(lái)控制收到的notification如何分配。默認(rèn)情況下,使用的是blocking executor(具體特性參加executor一節(jié))
模仿是一種很高效的學(xué)習(xí)方法,我這里根據(jù) OpenStack 的調(diào)用方式,抽取出核心內(nèi)容,寫成一個(gè)簡(jiǎn)單的 demo,有對(duì) OpenStack 感興趣的可以了解一下,大部分人也可以直接跳過(guò)這章節(jié)。
注意以下代碼不能直接運(yùn)行,你還需要配置 rabbitmq 的連接方式,你可以寫在配置文件中,通過(guò) get_transport 從cfg.CONF 中讀取,也可以直接將其寫成url的格式做成參數(shù),傳給 get_transport 。而且還要nova或者其他openstack組件的環(huán)境中運(yùn)行(因?yàn)樾枰衏txt這個(gè)環(huán)境變量)
簡(jiǎn)單的 rpc client
簡(jiǎn)單的 rpc server
【End】
熱 文 推 薦
?Facebook 發(fā)幣 Libra;谷歌十億美金為窮人造房;第四代樹(shù)莓派 Raspberry Pi 4 發(fā)布 | 開(kāi)發(fā)者周刊
?WebRTC 將一統(tǒng)實(shí)時(shí)音視頻天下?
?小米崔寶秋:小米 AIoT 深度擁抱開(kāi)源
?華為在美研發(fā)機(jī)構(gòu) Futurewei 意欲分家?
?老司機(jī)教你如何寫出沒(méi)人敢維護(hù)的代碼!
?Python有哪些技術(shù)上的優(yōu)點(diǎn)?比其他語(yǔ)言好在哪兒?
?上不了北大“圖靈”、清華“姚班”,AI專業(yè)還能去哪上?
?公鏈?zhǔn)酚?| 從鴻蒙初辟到萬(wàn)物生長(zhǎng)的十年激蕩……
?邊緣計(jì)算容器化是否有必要?
?馬云曾經(jīng)偶像,終于把阿里留下的1400億敗光了!
你點(diǎn)的每個(gè)“在看”,我都認(rèn)真當(dāng)成了喜歡
切換到新語(yǔ)言始終是一大步,尤其是當(dāng)您的團(tuán)隊(duì)成員只有一個(gè)時(shí)有該語(yǔ)言的先前經(jīng)驗(yàn)?,F(xiàn)在,Stream 的主要編程語(yǔ)言從 Python 切換到了 Go。這篇文章將解釋stream決定放棄 Python 并轉(zhuǎn)向 Go 的一些原因。
Go 非???。性能類似于 Java 或 C++。對(duì)于用例,Go 通常比 Python 快 40 倍。
對(duì)于許多應(yīng)用程序來(lái)說(shuō),編程語(yǔ)言只是應(yīng)用程序和數(shù)據(jù)庫(kù)之間的粘合劑。語(yǔ)言本身的性能通常并不重要。然而,Stream 是一個(gè)API 提供商,為 700 家公司和超過(guò) 5 億最終用戶提供提要和聊天平臺(tái)。多年來(lái),我們一直在優(yōu)化 Cassandra、PostgreSQL、Redis 等,但最終,您會(huì)達(dá)到所使用語(yǔ)言的極限。Python 是一門很棒的語(yǔ)言,但對(duì)于序列化/反序列化、排名和聚合等用例,它的性能相當(dāng)緩慢。我們經(jīng)常遇到性能問(wèn)題,Cassandra 需要 1 毫秒來(lái)檢索數(shù)據(jù),而 Python 會(huì)花費(fèi)接下來(lái)的 10 毫秒將其轉(zhuǎn)換為對(duì)象。
看看我如何開(kāi)始 Go 教程中的一小段 Go 代碼。(這是一個(gè)很棒的教程,也是學(xué)習(xí) Go 的一個(gè)很好的起點(diǎn)。)
如果您是 Go 新手,那么在閱讀那個(gè)小代碼片段時(shí)不會(huì)有太多讓您感到驚訝的事情。它展示了多個(gè)賦值、數(shù)據(jù)結(jié)構(gòu)、指針、格式和一個(gè)內(nèi)置的 HTTP 庫(kù)。當(dāng)我第一次開(kāi)始編程時(shí),我一直喜歡使用 Python 更高級(jí)的功能。Python 允許您在編寫代碼時(shí)獲得相當(dāng)?shù)膭?chuàng)意。例如,您可以:
這些功能玩起來(lái)很有趣,但是,正如大多數(shù)程序員會(huì)同意的那樣,在閱讀別人的作品時(shí),它們通常會(huì)使代碼更難理解。Go 迫使你堅(jiān)持基礎(chǔ)。這使得閱讀任何人的代碼并立即了解發(fā)生了什么變得非常容易。 注意:當(dāng)然,它實(shí)際上有多“容易”取決于您的用例。如果你想創(chuàng)建一個(gè)基本的 CRUD API,我仍然推薦 Django + DRF或 Rails。
作為一門語(yǔ)言,Go 試圖讓事情變得簡(jiǎn)單。它沒(méi)有引入許多新概念。重點(diǎn)是創(chuàng)建一種非??焖偾乙子谑褂玫暮?jiǎn)單語(yǔ)言。它唯一具有創(chuàng)新性的領(lǐng)域是 goroutine 和通道。(100% 正確CSP的概念始于 1977 年,所以這項(xiàng)創(chuàng)新更多是對(duì)舊思想的一種新方法。)Goroutines 是 Go 的輕量級(jí)線程方法,通道是 goroutines 之間通信的首選方式。Goroutines 的創(chuàng)建非常便宜,并且只需要幾 KB 的額外內(nèi)存。因?yàn)?Goroutine 非常輕量,所以有可能同時(shí)運(yùn)行數(shù)百甚至數(shù)千個(gè)。您可以使用通道在 goroutine 之間進(jìn)行通信。Go 運(yùn)行時(shí)處理所有復(fù)雜性。goroutines 和基于通道的并發(fā)方法使得使用所有可用的 CPU 內(nèi)核和處理并發(fā) IO 變得非常容易——所有這些都不會(huì)使開(kāi)發(fā)復(fù)雜化。與 Python/Java 相比,在 goroutine 上運(yùn)行函數(shù)需要最少的樣板代碼。您只需在函數(shù)調(diào)用前加上關(guān)鍵字“go”:
Go 的并發(fā)方法很容易使用。與 Node 相比,這是一種有趣的方法,開(kāi)發(fā)人員必須密切關(guān)注異步代碼的處理方式。Go 中并發(fā)的另一個(gè)重要方面是競(jìng)爭(zhēng)檢測(cè)器。這樣可以很容易地確定異步代碼中是否存在任何競(jìng)爭(zhēng)條件。
我們目前用 Go 編寫的最大的微服務(wù)編譯需要 4 秒。與以編譯速度慢而聞名的 Java 和 C++ 等語(yǔ)言相比,Go 的快速編譯時(shí)間是一項(xiàng)重大的生產(chǎn)力勝利。我喜歡在程序編譯的時(shí)候摸魚(yú),但在我還記得代碼應(yīng)該做什么的同時(shí)完成事情會(huì)更好。
首先,讓我們從顯而易見(jiàn)的開(kāi)始:與 C++ 和 Java 等舊語(yǔ)言相比,Go 開(kāi)發(fā)人員的數(shù)量并不多。根據(jù)StackOverflow的數(shù)據(jù), 38% 的開(kāi)發(fā)人員知道 Java, 19.3% 的人知道 C++,只有 4.6% 的人知道 Go。GitHub 數(shù)據(jù)顯示了類似的趨勢(shì):Go 比 Erlang、Scala 和 Elixir 等語(yǔ)言使用更廣泛,但不如 Java 和 C++ 流行。幸運(yùn)的是,Go 是一種非常簡(jiǎn)單易學(xué)的語(yǔ)言。它提供了您需要的基本功能,僅此而已。它引入的新概念是“延遲”聲明和內(nèi)置的并發(fā)管理與“goroutines”和通道。(對(duì)于純粹主義者來(lái)說(shuō):Go 并不是第一種實(shí)現(xiàn)這些概念的語(yǔ)言,只是第一種使它們流行起來(lái)的語(yǔ)言。)任何加入團(tuán)隊(duì)的 Python、Elixir、C++、Scala 或 Java 開(kāi)發(fā)人員都可以在一個(gè)月內(nèi)在 Go 上發(fā)揮作用,因?yàn)樗暮?jiǎn)單性。與許多其他語(yǔ)言相比,我們發(fā)現(xiàn)組建 Go 開(kāi)發(fā)人員團(tuán)隊(duì)更容易。如果您在博爾德和阿姆斯特丹等競(jìng)爭(zhēng)激烈的生態(tài)系統(tǒng)中招聘人員,這是一項(xiàng)重要的優(yōu)勢(shì)。
對(duì)于我們這樣規(guī)模的團(tuán)隊(duì)(約 20 人)來(lái)說(shuō),生態(tài)系統(tǒng)很重要。如果您必須重新發(fā)明每一個(gè)小功能,您根本無(wú)法為您的客戶創(chuàng)造價(jià)值。Go 對(duì)我們使用的工具有很好的支持。實(shí)體庫(kù)已經(jīng)可用于 Redis、RabbitMQ、PostgreSQL、模板解析、任務(wù)調(diào)度、表達(dá)式解析和 RocksDB。與 Rust 或 Elixir 等其他較新的語(yǔ)言相比,Go 的生態(tài)系統(tǒng)是一個(gè)重大勝利。它當(dāng)然不如 Java、Python 或 Node 之類的語(yǔ)言好,但它很可靠,而且對(duì)于許多基本需求,你會(huì)發(fā)現(xiàn)已經(jīng)有高質(zhì)量的包可用。
Gofmt 是一個(gè)很棒的命令行實(shí)用程序,內(nèi)置在 Go 編譯器中,用于格式化代碼。就功能而言,它與 Python 的 autopep8 非常相似。我們大多數(shù)人并不真正喜歡爭(zhēng)論制表符與空格。格式的一致性很重要,但實(shí)際的格式標(biāo)準(zhǔn)并不那么重要。Gofmt 通過(guò)使用一種正式的方式來(lái)格式化您的代碼來(lái)避免所有這些討論。
Go 對(duì)協(xié)議緩沖區(qū)和 gRPC 具有一流的支持。這兩個(gè)工具非常適合構(gòu)建需要通過(guò) RPC 通信的微服務(wù)。您只需要編寫一個(gè)清單,在其中定義可以進(jìn)行的 RPC 調(diào)用以及它們采用的參數(shù)。然后從這個(gè)清單中自動(dòng)生成服務(wù)器和客戶端代碼。生成的代碼既快速又具有非常小的網(wǎng)絡(luò)占用空間并且易于使用。從同一個(gè)清單中,您甚至可以為許多不同的語(yǔ)言生成客戶端代碼,例如 C++、Java、Python 和 Ruby。因此,內(nèi)部流量不再有模棱兩可的 REST 端點(diǎn),您每次都必須編寫幾乎相同的客戶端和服務(wù)器代碼。.
Go 沒(méi)有像 Rails 用于 Ruby、Django 用于 Python 或 Laravel 用于 PHP 那樣的單一主導(dǎo)框架。這是 Go 社區(qū)內(nèi)激烈爭(zhēng)論的話題,因?yàn)樵S多人主張你不應(yīng)該一開(kāi)始就使用框架。我完全同意這對(duì)于某些用例是正確的。但是,如果有人想構(gòu)建一個(gè)簡(jiǎn)單的 CRUD API,他們將更容易使用 Django/DJRF、Rails Laravel 或Phoenix。對(duì)于 Stream 的用例,我們更喜歡不使用框架。然而,對(duì)于許多希望提供簡(jiǎn)單 CRUD API 的新項(xiàng)目來(lái)說(shuō),缺乏主導(dǎo)框架將是一個(gè)嚴(yán)重的劣勢(shì)。
Go 通過(guò)簡(jiǎn)單地從函數(shù)返回錯(cuò)誤并期望調(diào)用代碼來(lái)處理錯(cuò)誤(或?qū)⑵浞祷氐秸{(diào)用堆棧)來(lái)處理錯(cuò)誤。雖然這種方法有效,但很容易失去問(wèn)題的范圍,以確保您可以向用戶提供有意義的錯(cuò)誤。錯(cuò)誤包通過(guò)允許您向錯(cuò)誤添加上下文和堆棧跟蹤來(lái)解決此問(wèn)題。另一個(gè)問(wèn)題是很容易忘記處理錯(cuò)誤。像 errcheck 和 megacheck 這樣的靜態(tài)分析工具可以方便地避免犯這些錯(cuò)誤。雖然這些變通辦法效果很好,但感覺(jué)不太對(duì)勁。您希望該語(yǔ)言支持正確的錯(cuò)誤處理。
Go 的包管理絕不是完美的。默認(rèn)情況下,它無(wú)法指定特定版本的依賴項(xiàng),也無(wú)法創(chuàng)建可重現(xiàn)的構(gòu)建。Python、Node 和 Ruby 都有更好的包管理系統(tǒng)。但是,使用正確的工具,Go 的包管理工作得很好。您可以使用Dep來(lái)管理您的依賴項(xiàng),以允許指定和固定版本。除此之外,我們還貢獻(xiàn)了一個(gè)名為的開(kāi)源工具VirtualGo,它可以更輕松地處理用 Go 編寫的多個(gè)項(xiàng)目。
我們進(jìn)行的一個(gè)有趣的實(shí)驗(yàn)是在 Python 中使用我們的排名提要功能并在 Go 中重寫它??纯催@個(gè)排名方法的例子:
Python 和 Go 代碼都需要執(zhí)行以下操作來(lái)支持這種排名方法:
開(kāi)發(fā) Python 版本的排名代碼大約花了 3 天時(shí)間。這包括編寫代碼、單元測(cè)試和文檔。接下來(lái),我們花了大約 2 周的時(shí)間優(yōu)化代碼。其中一項(xiàng)優(yōu)化是將分?jǐn)?shù)表達(dá)式 (simple_gauss(time)*popularity) 轉(zhuǎn)換為抽象語(yǔ)法樹(shù). 我們還實(shí)現(xiàn)了緩存邏輯,可以在未來(lái)的特定時(shí)間預(yù)先計(jì)算分?jǐn)?shù)。相比之下,開(kāi)發(fā)此代碼的 Go 版本大約需要 4 天時(shí)間。性能不需要任何進(jìn)一步的優(yōu)化。因此,雖然 Python 的最初開(kāi)發(fā)速度更快,但基于 Go 的版本最終需要我們團(tuán)隊(duì)的工作量大大減少。另外一個(gè)好處是,Go 代碼的執(zhí)行速度比我們高度優(yōu)化的 Python 代碼快大約 40 倍?,F(xiàn)在,這只是我們通過(guò)切換到 Go 體驗(yàn)到的性能提升的一個(gè)示例。
與 Python 相比,我們系統(tǒng)的其他一些組件在 Go 中構(gòu)建所需的時(shí)間要多得多。作為一個(gè)總體趨勢(shì),我們看到 開(kāi)發(fā) Go 代碼需要更多的努力。但是,我們花更少的時(shí)間 優(yōu)化 代碼以提高性能。
我們?cè)u(píng)估的另一種語(yǔ)言是Elixir.。Elixir 建立在 Erlang 虛擬機(jī)之上。這是一種迷人的語(yǔ)言,我們之所以考慮它,是因?yàn)槲覀兊囊幻麍F(tuán)隊(duì)成員在 Erlang 方面擁有豐富的經(jīng)驗(yàn)。對(duì)于我們的用例,我們注意到 Go 的原始性能要好得多。Go 和 Elixir 都可以很好地服務(wù)數(shù)千個(gè)并發(fā)請(qǐng)求。但是,如果您查看單個(gè)請(qǐng)求的性能,Go 對(duì)于我們的用例來(lái)說(shuō)要快得多。我們選擇 Go 而不是 Elixir 的另一個(gè)原因是生態(tài)系統(tǒng)。對(duì)于我們需要的組件,Go 有更成熟的庫(kù),而在許多情況下,Elixir 庫(kù)還沒(méi)有準(zhǔn)備好用于生產(chǎn)環(huán)境。培訓(xùn)/尋找開(kāi)發(fā)人員使用 Elixir 也更加困難。這些原因使天平向 Go 傾斜。Elixir 的 Phoenix 框架看起來(lái)很棒,絕對(duì)值得一看。
Go 是一種非常高性能的語(yǔ)言,對(duì)并發(fā)有很好的支持。它幾乎與 C++ 和 Java 等語(yǔ)言一樣快。雖然與 Python 或 Ruby 相比,使用 Go 構(gòu)建東西確實(shí)需要更多時(shí)間,但您將節(jié)省大量用于優(yōu)化代碼的時(shí)間。我們?cè)赟tream有一個(gè)小型開(kāi)發(fā)團(tuán)隊(duì),為超過(guò) 5 億最終用戶提供動(dòng)力和聊天。Go 結(jié)合了 強(qiáng)大的生態(tài)系統(tǒng) 、新開(kāi)發(fā)人員的 輕松入門、快速的性能 、對(duì)并發(fā)的 可靠支持和高效的編程環(huán)境 ,使其成為一個(gè)不錯(cuò)的選擇。Stream 仍然在我們的儀表板、站點(diǎn)和機(jī)器學(xué)習(xí)中利用 Python 來(lái)提供個(gè)性化的訂閱源. 我們不會(huì)很快與 Python 說(shuō)再見(jiàn),但今后所有性能密集型代碼都將使用 Go 編寫。我們新的聊天 API也完全用 Go 編寫。
智能合約調(diào)用是實(shí)現(xiàn)一個(gè) DApp 的關(guān)鍵,一個(gè)完整的 DApp 包括前端、后端、智能合約及區(qū)塊 鏈系統(tǒng),智能合約的調(diào)用是連接區(qū)塊鏈與前后端的關(guān)鍵。
我們先來(lái)了解一下智能合約調(diào)用的基礎(chǔ)原理。智能合約運(yùn)行在以太坊節(jié)點(diǎn)的 EVM 中。因此要 想調(diào)用合約必須要訪問(wèn)某個(gè)節(jié)點(diǎn)。
以后端程序?yàn)槔?,后端服?wù)若想連接節(jié)點(diǎn)有兩種可能,一種是雙 方在同一主機(jī),此時(shí)后端連接節(jié)點(diǎn)可以采用 本地 IPC(Inter-Process Communication,進(jìn) 程間通信)機(jī)制,也可以采用 RPC(Remote Procedure Call,遠(yuǎn)程過(guò)程調(diào)用)機(jī)制;另 一種情況是雙方不在同一臺(tái)主機(jī),此時(shí)只能采用 RPC 機(jī)制進(jìn)行通信。
提到 RPC, 讀者應(yīng)該對(duì) Geth 啟動(dòng)參數(shù)有點(diǎn)印象,Geth 啟動(dòng)時(shí)可以選擇開(kāi)啟 RPC 服務(wù),對(duì)應(yīng)的 默認(rèn)服務(wù)端口是 8545。。
接著,我們來(lái)了解一下智能合約運(yùn)行的過(guò)程。
智能合約的運(yùn)行過(guò)程是后端服務(wù)連接某節(jié)點(diǎn),將 智能合約的調(diào)用(交易)發(fā)送給節(jié)點(diǎn),節(jié)點(diǎn)在驗(yàn)證了交易的合法性后進(jìn)行全網(wǎng)廣播,被礦工打包到 區(qū)塊中代表此交易得到確認(rèn),至此交易才算完成。
就像數(shù)據(jù)庫(kù)一樣,每個(gè)區(qū)塊鏈平臺(tái)都會(huì)提供主流 開(kāi)發(fā)語(yǔ)言的 SDK(Software Development Kit,軟件開(kāi)發(fā)工具包),由于 Geth 本身就是用 Go 語(yǔ)言 編寫的,因此若想使用 Go 語(yǔ)言連接節(jié)點(diǎn)、發(fā)交易,直接在工程內(nèi)導(dǎo)入 go-ethereum(Geth 源碼) 包就可以了,剩下的問(wèn)題就是流程和 API 的事情了。
總結(jié)一下,智能合約被調(diào)用的兩個(gè)關(guān)鍵點(diǎn)是節(jié)點(diǎn)和 SDK。
由于 IPC 要求后端與節(jié)點(diǎn)必須在同一主機(jī),所以很多時(shí)候開(kāi)發(fā)者都會(huì)采用 RPC 模式。除了 RPC,以太坊也為開(kāi)發(fā)者提供了 json- rpc 接口,本文就不展開(kāi)討論了。
接下來(lái)介紹如何使用 Go 語(yǔ)言,借助 go-ethereum 源碼庫(kù)來(lái)實(shí)現(xiàn)智能合約的調(diào)用。這是有固定 步驟的,我們先來(lái)說(shuō)一下總體步驟,以下面的合約為例。
步驟 01:編譯合約,獲取合約 ABI(Application Binary Interface,應(yīng)用二進(jìn)制接口)。 單擊【ABI】按鈕拷貝合約 ABI 信息,將其粘貼到文件 calldemo.abi 中(可使用 Go 語(yǔ)言IDE 創(chuàng)建該文件,文件名可自定義,后綴最好使用 abi)。
最好能將 calldemo.abi 單獨(dú)保存在一個(gè)目錄下,輸入“l(fā)s”命令只能看到 calldemo.abi 文件,參 考效果如下:
步驟 02:獲得合約地址。注意要將合約部署到 Geth 節(jié)點(diǎn)。因此 Environment 選擇為 Web3 Provider。
在【Environment】選項(xiàng)框中選擇“Web3 Provider”,然后單擊【Deploy】按鈕。
部署后,獲得合約地址為:0xa09209c28AEf59a4653b905792a9a910E78E7407。
步驟 03:利用 abigen 工具(Geth 工具包內(nèi)的可執(zhí)行程序)編譯智能合約為 Go 代碼。abigen 工具的作用是將 abi 文件轉(zhuǎn)換為 Go 代碼,命令如下:
其中各參數(shù)的含義如下。 (1)abi:是指定傳入的 abi 文件。 (2)type:是指定輸出文件中的基本結(jié)構(gòu)類型。 (3)pkg:指定輸出文件 package 名稱。 (4)out:指定輸出文件名。 執(zhí)行后,將在代碼目錄下看到 funcdemo.go 文件,讀者可以打開(kāi)該文件欣賞一下,注意不要修改它。
步驟 04:創(chuàng)建 main.go,填入如下代碼。 注意代碼中 HexToAddress 函數(shù)內(nèi)要傳入該合約部署后的地址,此地址在步驟 01 中獲得。
步驟 04:設(shè)置 go mod,以便工程自動(dòng)識(shí)別。
前面有所提及,若要使用 Go 語(yǔ)言調(diào)用智能合約,需要下載 go-ethereum 工程,可以使用下面 的指令:
該指令會(huì)自動(dòng)將 go-ethereum 下載到“$GOPATH/src/github.com/ethereum/go-ethereum”,這樣還算 不錯(cuò)。不過(guò),Go 語(yǔ)言自 1.11 版本后,增加了 module 管理工程的模式。只要設(shè)置好了 go mod,下載 依賴工程的事情就不必關(guān)心了。
接下來(lái)設(shè)置 module 生效和 GOPROXY,命令如下:
在項(xiàng)目工程內(nèi),執(zhí)行初始化,calldemo 可以自定義名稱。
步驟 05:運(yùn)行代碼。執(zhí)行代碼,將看到下面的效果,以及最終輸出的 2020。
上述輸出信息中,可以看到 Go 語(yǔ)言會(huì)自動(dòng)下載依賴文件,這就是 go mod 的神奇之處??吹?2020,相信讀者也知道運(yùn)行結(jié)果是正確的了。
RPC是遠(yuǎn)程過(guò)程調(diào)用(Remote Procedure Call)的縮寫形式。SAP系統(tǒng)RPC調(diào)用的原理其實(shí)很簡(jiǎn)單,有一些類似于三層構(gòu)架的C/S系統(tǒng),第三方的客戶程序通過(guò)接口調(diào)用SAP內(nèi)部的標(biāo)準(zhǔn)或自定義函數(shù),獲得函數(shù)返回的數(shù)據(jù)進(jìn)行處理后顯示或打印。
進(jìn)程間通信(IPC)在多任務(wù)操作系統(tǒng)或聯(lián)網(wǎng)的計(jì)算機(jī)之間運(yùn)行的程序和進(jìn)程所用的通信技術(shù)。有兩種類型的進(jìn)程間通信(IPC)。
本地過(guò)程調(diào)用(LPC)LPC用在多任務(wù)操作系統(tǒng)中,使得同時(shí)運(yùn)行的任務(wù)能互相會(huì)話。這些任務(wù)共享內(nèi)存空間使任務(wù)同步和互相發(fā)送信息。遠(yuǎn)程過(guò)程調(diào)用(RPC)RPC類似于LPC,只是在網(wǎng)上工作。RPC開(kāi)始是出現(xiàn)在Sun微系統(tǒng)公司和HP公司的運(yùn)行UNⅨ操作系統(tǒng)的計(jì)算機(jī)中。
擴(kuò)展資料
通過(guò)IPC和RPC,程序能利用其它程序或計(jì)算機(jī)處理的進(jìn)程。客戶機(jī)/服務(wù)器模式計(jì)算把遠(yuǎn)程過(guò)程調(diào)用與其它技術(shù)(如消息傳遞)一道,作為系統(tǒng)間通信的一種機(jī)制??蛻魴C(jī)執(zhí)行自己的任務(wù),但靠服務(wù)器提供后端文件服務(wù)。
RPC為客戶機(jī)提供向后端服務(wù)器申請(qǐng)服務(wù)的通信機(jī)制,如圖R-4所示。如果你把客戶機(jī)/服務(wù)器應(yīng)用程序想作是一個(gè)分離的程序,服務(wù)器能運(yùn)行數(shù)據(jù)訪問(wèn)部分,因?yàn)樗x數(shù)據(jù)最近,客戶機(jī)能運(yùn)行數(shù)據(jù)表示和與用戶交互的前端部分。這樣,遠(yuǎn)程過(guò)程調(diào)用可看作是把分割的程序通過(guò)網(wǎng)絡(luò)重組的部件。LPC有時(shí)也稱耦合(Coupling)機(jī)制。
用這種方式分割程序,當(dāng)用戶要訪問(wèn)數(shù)據(jù)時(shí)就無(wú)需每次拷貝整個(gè)數(shù)據(jù)庫(kù)或它的大部分程序到用戶系統(tǒng)。其實(shí),服務(wù)器只處理請(qǐng)求,甚至只執(zhí)行一些數(shù)據(jù)計(jì)算,把得出的結(jié)果再發(fā)送給用戶。因?yàn)楫?dāng)數(shù)據(jù)存放在一個(gè)地方時(shí),數(shù)據(jù)庫(kù)同步很容易實(shí)現(xiàn),所以多個(gè)用戶可同時(shí)訪問(wèn)相同的數(shù)據(jù)。
分布式計(jì)算環(huán)境是由一個(gè)通信系統(tǒng)——網(wǎng)絡(luò)連接的計(jì)算機(jī)集群。很容易把這個(gè)網(wǎng)絡(luò)看成一個(gè)計(jì)算平臺(tái),若是對(duì)等方式,其中任何一臺(tái)計(jì)算機(jī)都能成為客戶機(jī)或服務(wù)器。
一些處理任務(wù)可被分成獨(dú)立運(yùn)行程序在不同的網(wǎng)絡(luò)計(jì)算機(jī)上并行處理,而獨(dú)立的程序被交給最適合這個(gè)任務(wù)的計(jì)算機(jī)處理。這種策略可利用計(jì)算機(jī)空閑資源,提高網(wǎng)絡(luò)的效益。一個(gè)典型的企業(yè)網(wǎng)包括許多運(yùn)行著不同操作系統(tǒng)的異構(gòu)計(jì)算機(jī)系統(tǒng)。
直接調(diào)用so的函數(shù)cgo應(yīng)該繞不開(kāi)吧,我寫過(guò)一個(gè)銀行的應(yīng)用程序調(diào)用其特色業(yè)務(wù)接口,因?yàn)榻涌谥恢С謈和java,我就封裝了一個(gè)c的so,然后用cgo調(diào)用后寫了一個(gè)RPC供遠(yuǎn)程的go語(yǔ)言調(diào)用,因?yàn)镽PC只負(fù)責(zé)信息交互不負(fù)責(zé)業(yè)務(wù)邏輯,所以寫了不到百行,以后基本不用再改。記住雖然go語(yǔ)言自帶gc,但cgo還是要手工釋放內(nèi)存哦。