如果看到這篇文章你還搞不明白為什麼不直接使用 http, 而要搞 rpc?那麼請看我的另一篇部落格:
什麼是rpc? 你會徹底搞明白為啥這個?為啥那個?如果還不懂那我也沒辦法了!
我們開發過程當中可能不僅涉及到一門語言,比如php java golang 在同一個專案當中都運用了,當然這可能是個非常大的專案,但是考慮到專案的可維護性三者同時出現的可能性還是比較低的,但是涉及到大型專案比如涉及到微服務架構,難免會有多門語言共存的情況發生,我們考慮是php+golang的混編模式,因為畢竟php有php的短板golang有golang的長處當然java更有java的特色!所以今天空穴來潮臨時打了雞血一樣的寫了這麼篇稿子!
首先提個醒,grpc章節的文章都是連貫性的,不可能你看這一篇文章就能搞明白什麼是rpc grpc,所以建議從本章節的第一篇文章讀起!
現在php流行的框架很多,我們就選擇國內使用人數最多的thinkphp5.0框架來演示
第一步:
把你在golang裡面的proto字尾的檔案原模原樣的拿過來 放到extend目錄下 至於為什麼放到extend目錄下下邊我們會解釋的
解釋一下: package pdfiles.user 那麼就會在User.proto檔案所在的位置生成Pdfiles/User目錄裡面存放存根檔案!
第二步:
composer.json檔案當中的require當中放入:
"require": {
"grpc/grpc": "v1.30.0",
"google/protobuf": "^v3.13.0"
},
"autoload":{
"psr-4":{
"GPBMetadata\\":"GPBMetadata/",
"Hello\\":"Hello/"
}
},
需要說明的是 “google/protobuf”: “^v3.13.0”不是必須的,可以去掉,這個是為了你在沒有安裝php的protobuf擴充套件情況下,也能正常執行,這種執行方式相對效率較低。
然後執行
composer install
或者
composer update
第三步:
a.安裝php的grpc擴充套件
用pecl方式安裝
pecl install grpc
找到php.ini 加上
extension = "grpc.so"
cli模式下以及fpm模式下兩種 找對php.ini php-m以及phpinfo()都能看到grpc才算成功哈!之前的博文當中講過如何安裝php擴充套件這裡不再廢話!
b.安裝 protobuf 及其 php 擴充套件(上邊我們通過composer安裝了已經 這裡再廢話一下如何在linux下安裝)
執行命令:
pecl install protobuf
找到php.ini檔案新增上
extension=protobuf.so
重啟服務即可 直接重啟nginx就完事 不放心那就重啟一遍php-fpm程式
第四步:
安裝 grpc_php_plugin 外掛
這一步非必須哈!
並且非常耗時 我就沒搞!
第五步:
因為前邊博文當中講過windows下安裝protoc編譯工具 並且配置到了環境變數當中 所以這裡你就可以直接執行命令:
進入到 extend目錄 找到User.proto檔案 然後執行:
protoc --php_out=plugins=grpc:. User.proto
這個時候你就會發現
紅線標註的就是新生成的類檔案!
我們第四部沒有安裝grpc_php_plugin 外掛所以生成的pdfiles/user裡面沒有UserClient檔案所以撒我們自己得新建立一個
第六步:
<?php
/**
* Created by PhpStorm.
* User: 胡軍
* Date: 2020/8/22
* Time: 13:43
*/
//名稱空間一定要對 保持和RequestUser.php裡面的一致即可!
namespace Pdfiles\User;
//必須繼承 \Grpc\BaseStub
class UserClient extends \Grpc\BaseStub{
//建構函式必須有哦
public function __construct($hostname, array $opts, $channel = null)
{
parent::__construct($hostname, $opts, $channel);
}
//為什麼是userList() 還記得你的proto檔案裡面的service嗎?
//service UserService{
// rpc UserList(RequestUser) returns (ResponseUser){};
//}
//如果rpc GetUsers(RequestUser1) returns (ResponseUser1){};
//那麼這裡你也要實現GetUsers()方法
//第一個引數是請求體 依賴注入進去就行啊 第二個是引數 第三個是其他引數 一把不傳入
public function userList(\Pdfiles\User\RequestUser $argument,$metadata=[],$options=[]){
//簡單模式
return $this->_simpleRequest(
//這裡找到golang那邊生成的.pd.go檔案裡面的FullMethod的值原模原樣填寫過來即可!
'/pdfiles.user.UserService/UserList',
//傳入的請求體
$argument,
//第一個表示用什麼解析 之類是 ResponseUser類來解析 名稱空間路徑要寫對啊! decode就是解析嘍
['\Pdfiles\User\ResponseUser','decode'],
//引數
$metadata,
//引數
$options
);
}
}
連結檔案就建立完成了!
第七步:
呼叫就完事了:
public function index2(){
//第二個引數固定寫法 是一種認證
$userClient = new \Pdfiles\User\UserClient("10.10.16.52:8084",[
'credentials' => \Grpc\ChannelCredentials::createInsecure()
]);
//請求體
$requestUser = new \Pdfiles\User\RequestUser();
$requestUser->setName("huxiaobai");//設定要傳遞的引數的值
$requestUser->setMobile("15275411187");//設定要傳遞的引數的值
//呼叫userList()方法請求體過去並等待響應
$request = $userClient->userList($requestUser)->wait();
//返回體和狀態
//狀態: code = 0表示連結成功了
//stdClass Object ( [metadata] => Array ( ) [code] => 0 [details] => )
list($response,$status) = $request;
//用返回體調取getUser()函式獲取返回值
$ret = $response->getUser();
foreach ($ret as $k=>$user){
echo $user->getName();
}
}
整個過程就完事了!
還是想說一句並不是所有的系統和系統之間資料的讀取用grpc就好 http也有http協議的好處 前邊我們都講過 是不是用還是自己考慮好哦!
原始碼:git@codehub.devcloud.huaweicloud.com:golang00004/php_go_grpc.git 付費!
本作品採用《CC 協議》,轉載必須註明作者和本文連結