mac下grpc(golang server + php client)實(shí)踐

目前微服務(wù)這么流行,RPC框架也是百花齊放,本文講述一下mac下grpc的開發(fā)環(huán)境搭建,其中server端使用golang,客戶端使用php。

服務(wù)端

golang grpc安裝

這里列出了一個(gè)參考,由于grpc在github上的文件目錄有改動(dòng),所以直接按官方的安裝,會(huì)出404資源無法找到的問題。
需要先在本地安裝golang+grpc。具體可參考:golang安裝grpc
操作完之后,在終端運(yùn)行:protoc --version,能看到版本信息
同時(shí),protoc-gen-go命令應(yīng)該也已經(jīng)被安裝

查看protoc版本信息

php grpc客戶端

擴(kuò)展有幾個(gè),推薦使用官方的
當(dāng)然,另外一個(gè)也相當(dāng)不錯(cuò),datto的protobuf擴(kuò)展。使用datto的這個(gè)的時(shí)候,我用perl根據(jù)其文檔安裝失敗,既然官方的ok了,也就懶得再去折騰了。
官方的具體的安裝流程,剛剛給的github的網(wǎng)址上有詳細(xì)的說明,根據(jù)步驟走,就ok了。
安裝完之后,為了在nginx下使用,應(yīng)該裝grpc這個(gè)擴(kuò)展:

php的grpc擴(kuò)展安裝成功查看

開始Demo

官方給了一個(gè)helloworld.proto的demo,咱們按樣子,增加一個(gè),目錄結(jié)構(gòu)如下:
demo目錄結(jié)構(gòu)

app和meta,放的是protoc編譯之后的服務(wù)端的go的源碼。
grpc,將protoc編譯成PHP所需要的工具及源碼(即:grpc_php_plugin)
phpClient,是protoc編譯出來的php的源碼,下面的vendor文件夾是composer加載的grpc/grpc的php客戶端的連接服務(wù)端的源碼

上源碼

先建立文件夾:mkdir grpc_demo

meta.proto的源碼

syntax = "proto3";

package meta;

service Agent {
  rpc GetInfo (MetaRequest) returns (MetaResponse);
}

message MetaRequest {
  string appId = 1;
}

message MetaResponse {
  string appId = 1;
  string title = 2;
  string name = 3;
  string logo = 4;
}

編譯成golang文件:

protoc --go_out=plugins=grpc:./meta ./meta.proto

編譯成php文件:

protoc --proto_path=./ \
       --php_out=phpClient/meta \
       --grpc_out=phpClient/meta \
       --plugin=protoc-gen-grpc=./grpc/bins/opt/grpc_php_plugin \
       meta.proto

編寫main.go文件:(此處把helloworld.proto這個(gè)demo也加進(jìn)來了)

package main

import (
    "log"
    "net"
    pb "grpc_demo/app"
    meta "grpc_demo/meta"
    "golang.org/x/net/context"
    "google.golang.org/grpc"
)

const (
    port = ":50051"
)

// server is used to implement helloworld.GreeterServer.
type server struct{}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello " + in.Name + "--from jacky_chen"}, nil
}

func (s *server) GetInfo(ctx context.Context, in *meta.MetaRequest) (*meta.MetaResponse, error) {
    return &meta.MetaResponse {
        AppId: in.AppId,
        Title: "my title",
        Name: "My Name",
        Logo: "https://xxx.com",
    }, nil
}
 
func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    meta.RegisterAgentServer(s, &server{})
    s.Serve(lis)
}

agent_client.php源碼:

<?php

require dirname(__FILE__).'/../vendor/autoload.php';

print_r(get_declared_classes());exit;

include_once dirname(__FILE__).'/Meta/AgentClient.php';
include_once dirname(__FILE__).'/Meta/MetaRequest.php';
include_once dirname(__FILE__).'/Meta/MetaResponse.php';
include_once dirname(__FILE__).'/GPBMetadata/Meta.php';
$appId = "123";
try {
    $client = new Meta\AgentClient('localhost:50051', [
        'credentials' => Grpc\ChannelCredentials::createInsecure(),
    ]);
    $request = new Meta\MetaRequest();
    $request->setAppId($appId);
    list($reply, $status) = $client->GetInfo($request)->wait();
    echo $reply->serializeToJsonString();
} catch (\Throwable | \Error | \Exception $e) {
    echo  "error : " . $e->getMessage();
}

運(yùn)行服務(wù)端:

go run main.go

運(yùn)行客戶端:

php 

結(jié)果如圖:


php調(diào)用go的rpc服務(wù)

由于php本身的原因(官方是基于php-fpm,非常駐內(nèi)存),所以grpc官方并沒有php的服務(wù)端。當(dāng)然,基于swoole開發(fā)的grpc的服務(wù)端在github上已經(jīng)有了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容