Go語言micro之快速搭建微服務


背景

go-micro給我們提供了一個非常便捷的方式來快速搭建微服務,而且並不需要提前系統了解micro,下面用一個簡單的示例來快速實現一個服務。

創建Proto文件

因為我們要做微服務,那么就一定有服務端和客戶端,這兩個端通過什么格式進行內容傳輸,就涉及到了序列化,比較主流的序列化協議就是JSON和Protobuf,因為Protobuf是以二進制傳輸的,體積比較小,所以傳輸速度也相對較快,今天就以protobuf來進行演示。

下面使用Proto3的語法在protos目錄創建文件greeter.proto,該文件定義一個名為Greeter的服務,以及對應的入參和出參。

syntax = "proto3";
package protos;

service Greeter {
    rpc Hello (Request) returns (Response) {
    };
}

message Request {
    string name = 1;
}

message Response {
    string greeting = 2;
}

生成Go文件

生成Go文件之前,要先確保本機安裝了protobuf,如果在終端輸入protoc沒有打印出幫助文檔,那么就是未安裝。

$ protoc
Usage: protoc [OPTION] PROTO_FILES
Parse PROTO_FILES and generate output based on the options given:
  -IPATH, --proto_path=PATH   Specify the directory in which to search for
                              imports.  May be specified multiple times;
                              directories will be searched in order.  If not
                              ……

可以通過官方文檔提示的命令進行安裝。

go get github.com/micro/protoc-gen-micro/v2

安裝成功之后,通過protoc命令將greeter.proto文件生成出對應的Go文件。

protoc --proto_path=./protos --micro_out=./protos --go_out=./protos ./protos/greeter.proto
  • --proto_path是greeter.proto文件所在的路徑

  • --micro_out是生成.go文件的所在目錄,該文件被用於創建服務

  • --go_out是生成.go文件的所在目錄,該文件被用於做數據序列化傳輸

可以根據需求自定義輸出目錄,我這邊輸出到了protos目錄,現在可以看到protos目錄中生成了兩個文件。

greeter.pb.go
greeter.pb.micro.go

實現服務

因為剛才已經通過protobuf定義了服務的接口,所以接下來需要實現對應的服務。

第一步,實現定義的服務接口

在生成的greeter.pb.micro.go文件中,可以看到我們greeter.proto文件中一個名為GreeterHandler的接口。

type GreeterHandler interface {
	Hello(context.Context, *Request, *Response) error
}

我們需要先實現該接口,接下來創建server.go文件,定義結構體Greeter,並實現Hello方法。

type Greeter struct {
}

func (g *Greeter) Hello(context context.Context, req *protos.Request, rsp *protos.Response) error {
	rsp.Greeting = "Hello " + req.Name
	return nil
}

Hello方法的后兩個參數剛好就是我們前面所生成的greeter.bp.go文件中定義的Request和Response結構體。在方法內部,將請求參數的Name前面拼接上了Hello字符串,並且賦值給了Response的Greeting變量。

第二步,初始化服務

我們創建一個名為greeter的服務。

func main() {
	service := micro.NewService(
		micro.Name("greeter"),
	)
	service.Init()
}

調用micro.NewService方法來創建一個新的服務,該方法的參數是可變參數,可以通過micro中的一系列方法來設置服務的參數,本次示例中只配置服務的名稱,記得在創建完服務后執行service.Init方法來初始化,micro版本建議使用v2。

第三步,注冊服務到handler

func main() {
	service := micro.NewService(
		micro.Name("greeter"),
	)
	service.Init()
	err := protos.RegisterGreeterHandler(service.Server(), new(Greeter))
	if err != nil {
		fmt.Println(err)
	}
}

第四步,將服務跑起來

	if err := service.Run(); err != nil {
		fmt.Println(err)
	}

完整代碼如下

package main

import (
	"context"
	"fmt"

	"github.com/micro/go-micro/v2"
)

type Greeter struct {
}

func (g *Greeter) Hello(context context.Context, req *Request, rsp *Response) error {
	rsp.Greeting = "Hello " + req.Name
	return nil
}

func main() {
	service := micro.NewService(
		micro.Name("greeter"),
	)
	service.Init()

	err := protos.RegisterGreeterHandler(service.Server(), new(Greeter))
	if err != nil {
		fmt.Println(err)
	}

	if err := service.Run(); err != nil {
		fmt.Println(err)
	}
}

現在將服務端跑起來。

$ go run server.go
2020-03-27 11:28:20 Starting [service] greeter
2020-03-27 11:28:20 Server [grpc] Listening on [::]:63763
2020-03-27 11:28:20 Registry [mdns] Registering node: greeter-8afc1183-a159-4473-a567-c13b83d1d75c

實現客戶端

創建client.go文件

func main() {
	service := micro.NewService(micro.Name("greeter.client"))
	service.Init()

	greeter := protos.NewGreeterService("greeter", service.Client())
	rsp, err := greeter.Hello(context.TODO(), &protos.Request{Name: "pingye"})
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(rsp.Greeting)
}

執行客戶端文件,輸出Hello pingye,執行成功。

$ go run client.go
Hello pingye

服務注冊到了哪里?

在啟動服務端的時候從終端輸出的信息可以看出,有一個名為greeter的服務注冊到了Registry

2020-03-27 11:28:20 Starting [service] greeter
2020-03-27 11:28:20 Server [grpc] Listening on [::]:63763
2020-03-27 11:28:20 Registry [mdns] Registering node: greeter-8afc1183-a159-4473-a567-c13b83d1d75c

Registry是go-micro的注冊模塊,作用是將服務注冊到某個介質,以方便客戶端使用。注冊模塊默認支持cache、consul、etcd、k8s、mdns、memory等多種介質,默認使用的是mdns。

var (
	DefaultRegistry = NewRegistry()

	// Not found error when GetService is called
	ErrNotFound = errors.New("service not found")
	// Watcher stopped error when watcher is stopped
	ErrWatcherStopped = errors.New("watcher stopped")
)

mdns主要用於在沒有傳統DNS服務器的情況下,在局域網中實現主機之間的發現與通訊,它遵從DNS協議。

Go語言組件示例開源庫,歡迎star
https://github.com/EnochZg/golang-examples


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM