1. 程式人生 > 其它 >go語言grpc框架實戰-01-客戶端和服務端雙向認證,藉助grpc-gateway支援grpc和http服務

go語言grpc框架實戰-01-客戶端和服務端雙向認證,藉助grpc-gateway支援grpc和http服務

建立proto中間檔案

  1. protobuf(protocol buffer)特點
    效能高、壓縮好、傳輸快、維護方便,一些第三方rpc庫都會支援protobuf

  2. 下載protobuf
    go get google.golang.org/protobuf
    注意:如果先下載grpc會預設下載protobuf
    go get google.golang.org/grpc

  3. 安裝protoc編譯器,將proto檔案編譯成指定語言的程式碼檔案(通用編譯器)
    下載網址
    protoc-3.20.1-win64.zip

  4. 下載解壓後將protoc.exe所在的bin目錄新增到系統環境變數當中去
    E:\protoc\bin

  5. 安裝protobuf的編譯器外掛protoc-gen-go,等下我們執行protoc命令時就會自動呼叫這個外掛生成go程式碼
    go install google.golang.org/protobuf/cmd/protoc-gen-go

  6. 安裝goland的proto外掛(goland 2022.1預設安裝了grpc和proto的支援)

  7. 建立中間檔案 hello.proto

syntax="proto3";  // 使用的proto 3的版本
package services;  // 生成go檔案的包名
option go_package="../services";  // 指定生成go檔案所在當前檔案的路徑

message ProdRequest{
  int32 prod_id = 1;  // 傳入的商品id
}
message ProdResponse{
  int32 prod_stock = 1;  // 商品庫存
}
  • 執行命令生成Prod.pb.go檔案
    protoc --go_out=services .\pbfiles\Prod.proto
  1. 檔案目錄

建立grpc服務並執行

  1. 原Prod.proto檔案增加一個服務
service ProdService{  // 獲取商品庫存服務
  rpc GetProdStock(ProdRequest) returns (ProdResponse);
}
  1. 生成支援grpc的Prod.pb.go檔案還需要下載安裝一個外掛protoc-gen-go-grpc.exe
go get google.golang.org/grpc/cmd/protoc-gen-go-grpc
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
  1. 重新生成Prod.pb.go檔案
    protoc --go_out=plugins=grpc:services .\pbfiles\Prod.proto -I .\pbfiles\

  2. 自行實現GetProdStock服務介面,在services目錄建立檔案:ProdService.go

package services

import (
	"context"
)

type ProdService struct {
	UnimplementedProdServiceServer
}

func (ProdService) GetProdStock(context.Context, *ProdRequest) (*ProdResponse, error) {
	return new(ProdResponse), nil
}
  1. 根目錄建立server.go檔案
package main

import (
	"google.golang.org/grpc"
	"grpc_test/services"
	"net"
)

func main() {
	// NewServer 建立一個未註冊服務且尚未開始接受請求的 gRPC 伺服器。
	rpcServer := grpc.NewServer()

	// 將當前產品服務註冊到grpc服務當中去
	services.RegisterProdServiceServer(rpcServer, new(services.ProdService))

	// 監聽套接字
	listener, _ := net.Listen("tcp", ":8080")

	// grpc伺服器通過傳入的監聽套接字接收請求,開始基於http2.0提供服務
	rpcServer.Serve(listener)
}

自簽證書,服務加入證書驗證

使用自籤ca server client證書和雙向認證

客戶端和服務端各自使用各自的證書,同時使用ca證書進行驗籤
參考文件

雙向認證下rpc-gateway的使用(同時提供rpc和http介面)

  1. 安裝
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go get github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
go mod tidy
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway
go install 
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
  1. 修改我們的Prod.proto檔案,增加http介面支援
syntax = "proto3";  // 使用的proto 3的版本
package services;  // 生成go檔案的包名
option go_package = "../services";  // 指定生成go檔案所在當前檔案的路徑

import "google/api/annotations.proto";  // 新增加的

message ProdRequest{
  int32 prod_id = 1;  // 傳入的商品id
}
message ProdResponse{
  int32 prod_stock = 1;  // 商品庫存
}

service ProdService{// 獲取商品庫存服務
  rpc GetProdStock(ProdRequest) returns (ProdResponse) {
    option (google.api.http) = {  // 新增加的
      get : "/v1/prod/{prod_id}"
    };
  }
}

  1. 將相關的proto檔案拷貝到我們的本地,如圖

  2. 執行protoc命令,重新生成Prod.pb.go檔案
    protoc --go_out=plugins=grpc:services .\pbfiles\Prod.proto -I .\pbfiles\

  3. 生成Prod.pb.gw.go檔案
    protoc --grpc-gateway_out=logtostderr=true:services .\pbfiles\Prod.proto -I .\pbfiles\

  4. server.go程式碼提供grpc服務

點選檢視程式碼
package main

import (
	"google.golang.org/grpc"
	"grpc_test/helper"
	"grpc_test/services"
	"net"
)

func main() {
	creds := helper.GetServerCreds()

	// NewServer 建立一個未註冊服務且尚未開始接受請求的 gRPC 伺服器。
	rpcServer := grpc.NewServer(grpc.Creds(creds))

	// 將當前產品服務註冊到grpc服務當中去
	services.RegisterProdServiceServer(rpcServer, new(services.ProdService))

	// 監聽套接字
	listener, _ := net.Listen("tcp", ":8080")
	//// grpc伺服器接收請求,開始提供服務
	rpcServer.Serve(listener)

}

  1. httpserver.go程式碼提供http服務
點選檢視程式碼
package main

import (
	"context"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	"google.golang.org/grpc"
	"grpc_test/helper"
	"grpc_test/services"
	"log"
	"net/http"
)

func main() {
	gwmux := runtime.NewServeMux()
	opts := []grpc.DialOption{grpc.WithTransportCredentials(helper.GetClientCreds())}
	// endpoint: 是grpc伺服器的地址
	err := services.RegisterProdServiceHandlerFromEndpoint(context.Background(), gwmux, "127.0.0.1:8080", opts)
	if err != nil {
		log.Fatal(err.Error())
	}

	httpServer := http.Server{Addr: "127.0.0.1:8081", Handler: gwmux}
	httpServer.ListenAndServe()
}

瀏覽器訪問試試吧:http://127.0.0.1:8081/v1/prod/38
同時grpc客戶端訪問也可以,至此,藉助grpc-gateway完成了同時提供grpc和http介面