grpc套路(四)php通過grpc呼叫golang的grpc介面服務

huxiaobai_001發表於2020-08-22

如果看到這篇文章你還搞不明白為什麼不直接使用 http, 而要搞 rpc?那麼請看我的另一篇部落格:
什麼是rpc? 你會徹底搞明白為啥這個?為啥那個?如果還不懂那我也沒辦法了!

我們開發過程當中可能不僅涉及到一門語言,比如php java golang 在同一個專案當中都運用了,當然這可能是個非常大的專案,但是考慮到專案的可維護性三者同時出現的可能性還是比較低的,但是涉及到大型專案比如涉及到微服務架構,難免會有多門語言共存的情況發生,我們考慮是php+golang的混編模式,因為畢竟php有php的短板golang有golang的長處當然java更有java的特色!所以今天空穴來潮臨時打了雞血一樣的寫了這麼篇稿子!

首先提個醒,grpc章節的文章都是連貫性的,不可能你看這一篇文章就能搞明白什麼是rpc grpc,所以建議從本章節的第一篇文章讀起!

現在php流行的框架很多,我們就選擇國內使用人數最多的thinkphp5.0框架來演示

第一步:

把你在golang裡面的proto字尾的檔案原模原樣的拿過來 放到extend目錄下 至於為什麼放到extend目錄下下邊我們會解釋的

grpc套路(四)php通過grpc呼叫golang的grpc介面服務
解釋一下: 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通過grpc呼叫golang的grpc介面服務

紅線標註的就是新生成的類檔案!
我們第四部沒有安裝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 協議》,轉載必須註明作者和本文連結
胡軍

相關文章