go微服務系列(四) - gRPC入門

1. 前言

以前學習的go的微服務之間仍是經過REST API的方式互相調用的,但既然要學習微服務,gRPC確定是一個繞不過去的須要學習的技術, 因此就開搞吧java

2. gRPC與Protobuf簡介

gRPC是一款語言中立平臺中立、開源的遠程過程調用系統git

即:gRPC客戶端和服務端能夠在多種環境中運行和交互,例如用java寫一個服務端,能夠用go語言寫客戶端調用github

微服務架構中,因爲每一個服務對應的代碼庫是獨立運行的,沒法直接調用,彼此間的通訊就是個大問題.golang

gRPC能夠實現將大的項目拆分爲多個小且獨立的業務模塊,也就是服務。各服務間使用高效的protobuf協議進行RPC調用,gRPC默認使用protocol buffers,這是google開源的一套成熟的結構數據序列化機制shell

固然也能夠使用其餘數據格式如JSONvim

能夠用proto files建立gRPC服務,用message類型來定義方法參數和返回類型bash

3. 安裝

  • 第一步:下載grpc通用編譯器

以下圖,解壓出來因平臺而異會是一個protoc或者protoc.exe架構

https://github.com/protocolbuffers/protobuf/releasestcp

  • 第二步:把下載的二進制文件路徑添加到環境變量中(爲了能全局訪問protoc)
    • 這裏覺得mac爲例子
# 打開存放環境變量的文件
vim ~/.bash_profile

# 添加以下,後面是路徑
alias protoc="/Users/emm/others/protoc-3.12.4-osx-x86_64/bin/protoc"

# 刷新環境變量
source ./.bash_profile
  • 第三步: 安裝go專用的protoc的生成器

go get github.com/golang/protobuf/protoc-gen-go函數

安裝後會在GOPATH目錄下生成可執行文件,protobuf的編譯器插件protoc-gen-go,等下執行protoc命令會自動調用這個插件

4. 中間文件演示

4.1 編寫中間文件

這裏新建一個pbfiles文件夾用於存放protoc文件

// 這個就是protobuf的中間文件

// 指定的當前proto語法的版本,有2和3
syntax = "proto3";

// 指定等會文件生成出來的package
package service;

// 定義request
message ProductRequest{
  int32 prod_id = 1; // 1表明順序
}

// 定義response
message ProductResponse{
  int32 prod_stock = 1; // 1表明順序
}

4.2 運行protoc命令編譯成go中間文件

而後運行如下的命令來生成.go結尾的文件

  • 下面的命令就是咱們剛剛下的protoc包以及protoc-gen-go插件的做用
# 編譯Product.proto以後輸出到service文件夾
protoc --go_out=../service Product.proto

以下就在service文件夾自動生成了一個go文件,而且它提示咱們不要去修改它

5. 建立gRPC服務端

5.1 新建Product.protoc

這個protoc文件比上面的多出了一個service的定義和裏面的一個方法的定義

// 這個就是protobuf的中間文件

// 指定的當前proto語法的版本,有2和3
syntax = "proto3";

// 指定等會文件生成出來的package
package service;

// 定義request model
message ProductRequest{
  int32 prod_id = 1; // 1表明順序
}

// 定義response model
message ProductResponse{
  int32 prod_stock = 1; // 1表明順序
}

// 定義服務主體
service ProdService{
  // 定義方法
  rpc GetProductStock(ProductRequest) returns(ProductResponse);
}

5.2 運行protoc命令

注意

  • 這裏的protoc命令和以前的命令相比有點不同
protoc --go_out=plugins=grpc:../service Product.proto

而後仍是會在service文件夾下生成一個.go的文件

有兩個比較須要注意的

  1. RegisterProdServiceServer

後面須要在server中調用這個來註冊

  1. ProdServiceServer的接口定義

咱們須要繼承這個接口,即實現它全部的方法

5.3 實現RegisterProdServiceServer接口

上面咱們在protoc文件中定義了一個ProdService中包含了一個GetProductStock的方法

這裏咱們要實現自動生成的go文件中的接口

package service

import "context"

type ProdService struct {
}

func (ps *ProdService) GetProductStock(ctx context.Context, request *ProductRequest) (*ProductResponse, error) {
	return &ProductResponse{ProdStock: request.ProdId}, nil
}

5.4 準備工做完成,建立main函數將服務端跑起來

前面的都是準備工做,這裏是真正把服務端跑起來的操做

下面是服務端代碼:

package main

import (
	"gomicro-quickstart/grpc_demo/service"
	"google.golang.org/grpc"
	"log"
	"net"
)

func main() {
	// 1. new一個grpc的server
	rpcServer := grpc.NewServer()

	// 2. 將剛剛咱們新建的ProdService註冊進去
	service.RegisterProdServiceServer(rpcServer, new(service.ProdService))

	// 3. 新建一個listener,以tcp方式監聽8082端口
	listener, err := net.Listen("tcp", ":8082")
	if err != nil {
		log.Fatal("服務監聽端口失敗", err)
	}

	// 4. 運行rpcServer,傳入listener
	_ = rpcServer.Serve(listener)
}

排坑

  • 若是碰見相似undefined: grpc.SupportPackageIsVersion6undefined: grpc.ClientConnInterface的錯誤,能夠修改go.mod將grpc版本改到1.27.0


6. 建立gRPC客戶端

  • 新建一個grpc_client文件夾存放客戶端相關的
  • 並在grpc_client文件夾下再新建一個service文件夾

6.1 拷貝Product.pb.go到客戶端service文件夾下

6.2 編寫client的main函數

package main

import (
	"context"
	"fmt"
	"gomicro-quickstart/grpc_client/service"
	"google.golang.org/grpc"
	"log"
)

func main() {
	// 1. 新建鏈接,端口是服務端開放的8082端口
	// 而且添加grpc.WithInsecure(),否則沒有證書會報錯
	conn, err := grpc.Dial(":8082", grpc.WithInsecure())
	if err != nil {
		log.Fatal(err)
	}

	// 退出時關閉連接
	defer conn.Close()

	// 2. 調用Product.pb.go中的NewProdServiceClient方法
	productServiceClient := service.NewProdServiceClient(conn)

	// 3. 直接像調用本地方法同樣調用GetProductStock方法
	resp, err := productServiceClient.GetProductStock(context.Background(), &service.ProductRequest{ProdId: 233})
	if err != nil {
		log.Fatal("調用gRPC方法錯誤: ", err)
	}

	fmt.Println("調用gRPC方法成功,ProdStock = ", resp.ProdStock)
}

6.3 運行並顯示結果

  • 先把服務端運行起來
  • 再把客戶端運行起來

而後客戶端輸出正確的結果,第一個go的gRPC調用運行成功

相關文章
相關標籤/搜索