grpc-gateway:grpc轉換為http協議對外提供服務

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

我所在公司的項目是採用基於Restful的微服務架構,隨著微服務之間的溝通越來越頻繁,就希望可以做成用rpc來做內部的通訊,對外依然用Restful。於是就想到了google的grpc。

使用grpc的優點很多,二進位的資料可以加快傳輸速度,基於http2的多工可以減少服務之間的串連次數,和函數一樣的調用方式也有效提升了開發效率。

不過使用grpc也會面臨一個問題,我們的微服務對外一定是要提供Restful介面的,如果內部調用使用grpc,在某些情況下要同時提供一個功能的兩套API介面,這樣就不僅降低了開發效率,也增加了調試的複雜度。於是就想著有沒有一個轉換機制,讓Restful和gprc可以相互轉化。

在網上看到一個解決方案,https://github.com/grpc-ecosystem/grpc-gateway,簡單的說就是有一個閘道伺服器負責轉化和代理轉寄。

如:

安裝

首先要安裝ProtocolBuffers 3.0及以上版本。

mkdir tmpcd tmpgit clone https://github.com/google/protobufcd protobuf./autogen.sh./configuremakemake checksudo make install

然後使用go get擷取grpc-gateway。

go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gatewaygo get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swaggergo get -u github.com/golang/protobuf/protoc-gen-go

這裡最好把編譯產生的二進位檔案的目錄放在$PATH中,可以把$GOPATH/bin放入$PATH中。

樣本

本樣本是基於我的上一篇部落格《google的grpc在glang中的使用》中的樣本,如果有必要請先瞭解上一篇部落格。

範例程式碼擷取地址:https://github.com/andyidea/go-example。

代碼檔案結構如下

└── src    └── grpc-helloworld-gateway        ├── gateway        │   └── main.go        ├── greeter_server        │   └── main.go        └── helloworld            ├── helloworld.pb.go            ├── helloworld.pb.gw.go            └── helloworld.proto

我們還是先看一下協議檔案。helloworld.proto有一些變動,引入了google官方的api相關的擴充,為grpc的http轉換提供了支援。

具體改動如下:

syntax = "proto3";option java_multiple_files = true;option java_package = "io.grpc.examples.helloworld";option java_outer_classname = "HelloWorldProto";package helloworld;import "google/api/annotations.proto";// The greeting service definition.service Greeter {  // Sends a greeting  rpc SayHello (HelloRequest) returns (HelloReply) {        option (google.api.http) = {        post: "/v1/example/echo"        body: "*"    };  }}// The request message containing the user's name.message HelloRequest {  string name = 1;}// The response message containing the greetingsmessage HelloReply {  string message = 1;}

和之前的proto檔案比較,新的檔案增了

import "google/api/annotations.proto";

option (google.api.http) = {        post: "/v1/example/echo"        body: "*"

這裡增加了對http的擴充配置。

然後編譯proto檔案,產生對應的go檔案

cd src/grpc-helloworld-gatewayprotoc -I/usr/local/include -I. \-I$GOPATH/src \-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \--go_out=Mgoogle/api/annotations.proto=github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api,plugins=grpc:. \helloworld/helloworld.proto 

這裡產生了helloworld/helloworld.pb.go檔案。

helloworld.pb.go是server服務需要的,下一步我們需要使用protoc產生gateway需要的go檔案。

cd src/grpc-helloworld-gatewayprotoc -I/usr/local/include -I. \-I$GOPATH/src  -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \--swagger_out=logtostderr=true:. \helloworld/helloworld.proto

這裡產生了helloworld/helloworld.pb.gw.go檔案。這個檔案就是gateway用來的協議檔案,用來做grpc和http的協議轉換。

協議檔案處理完畢,就需要寫gateway代碼了。

gateway代碼如下:

package mainimport (    "flag"    "net/http"    "github.com/golang/glog"    "github.com/grpc-ecosystem/grpc-gateway/runtime"    "golang.org/x/net/context"    "google.golang.org/grpc"    gw "grpc-helloworld-gateway/helloworld")var (    echoEndpoint = flag.String("echo_endpoint", "localhost:50051", "endpoint of YourService"))func run() error {    ctx := context.Background()    ctx, cancel := context.WithCancel(ctx)    defer cancel()    mux := runtime.NewServeMux()    opts := []grpc.DialOption{grpc.WithInsecure()}    err := gw.RegisterGreeterHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts)    if err != nil {        return err    }    return http.ListenAndServe(":8080", mux)}func main() {    flag.Parse()    defer glog.Flush()    if err := run(); err != nil {        glog.Fatal(err)    }}

首先echoEndpoint儲存了需要串連的server資訊,然後將這些資訊和建立的server用gw.go中的RegisterGreeterHandlerFromEndpoint進行一個註冊和綁定,這時低層就會串連echoEndpoint提供的遠程server地址,這樣gateway就作為用戶端和遠程server建立了串連,之後用http啟動建立的server,gateway就作為伺服器端對外提供http的服務了。

代碼到此就完成了,我們測試一下。

先啟動greeter_server服務,再啟動gateway,這時gatway串連上greeter_server後,對外建立http的監聽。

然後我們用curl發送http請求

curl -X POST -k http://localhost:8080/v1/example/echo -d '{"name": " world"}{"message":"Hello  world"}

流程如下:curl用post向gateway發送請求,gateway作為proxy將請求轉化一下通過grpc轉寄給greeter_server,greeter_server通過grpc返回結果,gateway收到結果後,轉化成json返回給前端。

這樣,就通過grpc-gateway完成了從http json到內部grpc的轉化過程。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.