go語言grpc框架實戰-01-客戶端和服務端雙向認證,藉助grpc-gateway支援grpc和http服務
建立proto中間檔案
-
protobuf(protocol buffer)特點
效能高、壓縮好、傳輸快、維護方便,一些第三方rpc庫都會支援protobuf -
下載protobuf
go get google.golang.org/protobuf
注意:如果先下載grpc會預設下載protobufgo get google.golang.org/grpc
-
安裝protoc編譯器,將proto檔案編譯成指定語言的程式碼檔案(通用編譯器)
下載網址
protoc-3.20.1-win64.zip -
下載解壓後將protoc.exe所在的bin目錄新增到系統環境變數當中去
E:\protoc\bin
-
安裝protobuf的編譯器外掛protoc-gen-go,等下我們執行protoc命令時就會自動呼叫這個外掛生成go程式碼
go install google.golang.org/protobuf/cmd/protoc-gen-go
-
安裝goland的proto外掛(goland 2022.1預設安裝了grpc和proto的支援)
-
建立中間檔案 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
- 檔案目錄
建立grpc服務並執行
- 原Prod.proto檔案增加一個服務
service ProdService{ // 獲取商品庫存服務
rpc GetProdStock(ProdRequest) returns (ProdResponse);
}
- 生成支援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
-
重新生成Prod.pb.go檔案
protoc --go_out=plugins=grpc:services .\pbfiles\Prod.proto -I .\pbfiles\
-
自行實現GetProdStock服務介面,在services目錄建立檔案:ProdService.go
package services
import (
"context"
)
type ProdService struct {
UnimplementedProdServiceServer
}
func (ProdService) GetProdStock(context.Context, *ProdRequest) (*ProdResponse, error) {
return new(ProdResponse), nil
}
- 根目錄建立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介面)
- 安裝
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
- 修改我們的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}"
};
}
}
-
將相關的proto檔案拷貝到我們的本地,如圖
-
執行protoc命令,重新生成Prod.pb.go檔案
protoc --go_out=plugins=grpc:services .\pbfiles\Prod.proto -I .\pbfiles\
-
生成Prod.pb.gw.go檔案
protoc --grpc-gateway_out=logtostderr=true:services .\pbfiles\Prod.proto -I .\pbfiles\
-
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)
}
- 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介面