天天看點

Go語言微服務實戰之micro微服務架構

之前的文章我們大緻了解了微服務,同時我們還準備好了一台搭載CentOS系統的雲伺服器,這篇文章我們正式開始微服務的實踐之旅。

一提到微服務,首先想到的就是Spring Cloud,阿裡的Dubbo等。與go語言相比,java的一個巨大優勢就是生态系統非常成熟,有很多成熟的商業級架構可供使用,go相對而言比較新,是以生态上還不如java那麼完善,但是這并不妨礙我們學習微服務,在github上已經有一些開源的go微服務架構可以使用,比如go micro,go kit,go chassis等,這裡我們選擇go micro,在寫這篇文章的時候,這個開源微服務架構在github上已經有多達12.9K的Star數,一個微服務架構該有的東西基本上全都具備了,是入門微服務非常不錯的一個開源項目。

1、認識micro微服務架構

如果想深入學習,最好的方法是先蕩一份源碼研究,go micro的首頁:

https://github.com/micro/go-micro

初學者可以先不急着一上來就去挖原理,先學會如何使用,然後在循序漸進,建議初學者先點開下面的連結仔細看一遍文檔:

https://micro.mu/docs/framework.html

micro滿足分布式系統開發的核心需求,在設計上采用插件化的方式,一些核心功能諸如消息中間件、服務注冊及發現等都是可插拔的,micro提供預設實作,但是開發者可以根據自己的需求随意替換。

我們來看看micro的主要特點:

(1) 服務發現:micro支援自動化的服務發現和域名解析。服務發現在微服務開發中處于核心地位,正如我們在第一篇文章所說,當微服務獨立部署在不同機器上的時候,服務A想要和服務B通信就必須要知道服務B所在的機器。micro提供了基于mDNS的服務發現的預設實作,當然你可以使用其他插件甚至自己編寫插件來滿足自己的需求。

(2) 負載均衡:通常一個商業級的應用,因為使用者量較大,一些核心服務往往會部署在多台機器上,這就涉及到負載均衡的問題,大量的請求不能落地到某一台機器上,而是用某種負載均衡政策分攤到所有的機器上去。micro提供了基于随機哈希的負載均衡政策,當發現某台機器有問題時會選擇另外一台機器進行重試。

(3) RPC:micro對同步通信進行了抽象,用戶端到服務端的請求會被自動解析并做負載均衡,預設采用gRPC做為RPC通道。

(4) 異步消息:micro支援消息的釋出-訂閱,這個也是可插拔的,你可以用Kafka,RabbitMQ等任何你熟悉的消息中間件發送異步消息。

(5) 插件化:諸如服務發現、負載均衡、消息中間件等這些分布式系統開發中的核心元件,micro都做了抽象,可以根據自己的需求實作接口去替換,當然社群也已經有很多現成的插件供開發者使用。

2、Hello,Micro

這一節,我們就用經典的Hello world的方式來看看如何編寫一個最簡單的微服務。

2.1 開發環境

我們假定讀者已經是go語言的開發者,這個系列的文章我們不會介紹go文法相關的知識。我們以GoLand IDE為例。

go版本1.14,GoLand版本2020.1.2

首先,建立一個工程,建好之後在GoLand中開啟go module,并且添加環境變量:GOPROXY = https://goproxy.cn,在Mac上可以通過Preferences -> Go Modules來設定:

Go語言微服務實戰之micro微服務架構

2.2 初始化子產品

我們在工程中建立一個子產品micro,建立一個檔案夾micro,然後指令行:

go mod init micro
           

然後我們會在項目根目錄下看到一個go.mod的檔案檔案。

2.3 編寫協定檔案

micro是基于google protobuf的,是以我們需要先編寫.proto的協定檔案:

syntax = "proto3";

package pb;

// 定義微服務對外提供的接口
service Greeter {

    rpc Hello(Request) returns (Response) {}
}

// 請求
message Request {
    string name = 1;
}

// 響應
message Response {
    string msg = 1;
}
           

是不是很簡單,你的服務想提供什麼能力,就用接口定義出來(包括參數等),我們在項目中建立一個proto目錄,将協定檔案放在這裡,目錄結構如下,其中pbfile目錄存放.proto,pb目錄則儲存生成的代碼:

Go語言微服務實戰之micro微服務架構

接下來我們需要根據這份.proto協定生成代碼,為了生成micro特定的代碼,需要先在開發機上安裝protobuf以及一些相關工具:

brew install protobuf
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
go get github.com/micro/micro/v2/cmd/[email protected]
           

所有必須的工具都安裝好之後,在指令行敲入指令來生成代碼: 

protoc --proto_path=$GOPATH/src:./proto/pbfile --go_out=./proto/pb --micro_out=./proto/pb hello.proto
           

--proto_path指定了要在哪些目錄中尋找.proto協定檔案,--go_out和--micro_out指定了檔案的輸出目錄。

2.4 編寫微服務

終于到了手撕第一個微服務的時刻了,因為功能非常簡單,我們直接上代碼,相信大家都能秒懂實在不懂的也沒關系,複制到IDE裡先運作起來也可以。在項目中建立server/main目錄,在此目錄下建立main.go,把以下代碼複制進去:

package main

import (
	"context"
	"fmt"
	"github.com/micro/go-micro/v2"
	"micro/proto/pb"
)

type Greeter struct {}

func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error  {
	//把用戶端的請求回射給用戶端
	rsp.Msg = req.Name
	return nil
}

func main() {

	// 新建立一個服務,服務名為greeter,服務注冊中心會用這個名字來發現服務
	service := micro.NewService(
		micro.Name("greeter"),
	)

	// 初始化
	service.Init()

	// 注冊處理器
	pb.RegisterGreeterHandler(service.Server(), new(Greeter))

	// 啟動服務運作
	if err := service.Run(); err != nil {
		fmt.Println(err)
	}
}
           

總結一下主要的點:

(1) 定義結構體,實作協定檔案中定義的接口;

(2) 使用micro.NewService建立一個微服務,必須要指定一個服務名,如果一個系統有多個微服務,請注意不要重名,這個名字是用來做服務發現用的;

(3) 将我們實作了協定接口的結構體注冊到micro;

(4) 最後啟動服務運作;

現在,我們運作一下試試,在終端使用go run server/main/main.go運作程式,可以看到以下輸出:

Go語言微服務實戰之micro微服務架構

從控制台輸出的日志中可以看到服務使用grpc,在54836端口上監聽請求,同時可以看到我們在mdns上注冊了一個節點,這樣用戶端就能通過mdns發現我們的微服務并調用接口。此前我們說過micro的服務發現與注冊中心是可以通過插件化的方式替換的,在後續的文章中我們會用kubernetes做為服務注冊中心,替換micro預設的mdns。

2.5 編寫用戶端

最後我們寫個用戶端程式來調用上面的微服務,在項目中建立client/main目錄,在此目錄下建立main.go檔案,把以下代碼拷貝過去:

package main

import (
	"context"
	"fmt"
	"github.com/micro/go-micro/v2"
	"micro/proto/pb"
)

func main() {

	// 建立一個服務
	service := micro.NewService(micro.Name("greeter.client"))
	// 初始化
	service.Init()
	// 建立一個微服務的用戶端
	greeter := pb.NewGreeterService("greeter", service.Client())
	// 調用微服務
	rsp, err := greeter.Hello(context.TODO(), &pb.Request{Name: "Hello Micro"})
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(rsp.Msg)
}
           

同樣我們先建立并初始化一個用戶端服務,注意名字與服務端不同,然後調用服務接口,并在控制台列印服務的響應,在終端運作該程式,在控制台上看到以下輸出:

Go語言微服務實戰之micro微服務架構

如果你順利完成了這一步,那麼恭喜,你已經開發出了自己的第一個微服務,雖然它幾乎什麼也沒有做。

2.6 使用micro來運作微服務

前面我們在自己的開發機上本地編譯運作微服務,我們還可以用micro工具集來啟動微服務,micro有一套完備的工具集供我們使用,我們先安裝一下:

go install github.com/micro/micro/v2
           

安裝完成以後,我們來嘗試運作一下剛才的服務:

在終端運作:

micro server

然後,在打開一個終端,運作:

micro run server/main/

指定我們的微服務代碼所在的目錄即可,此時可以在終端看到以下輸出:

Go語言微服務實戰之micro微服務架構

我們用micro工具集一樣運作起了我們的微服務。

然後我們利用工具來檢視一下有哪些服務,在終端敲以下指令:

micro list services

輸出如下:

Go語言微服務實戰之micro微服務架構

可以看到預設已經啟動了不少的服務,我們的greeter服務位于最下面。

現在檢視一下這個服務的詳細資訊,在終端鍵入下面的指令:

micro get service greeter

看到以下輸出:

Go語言微服務實戰之micro微服務架構

詳細資訊一目了然。

最後咱們試着調用一下:

Go語言微服務實戰之micro微服務架構

這次我們得到了JSON格式的輸出。

3、總結

這篇文章我們實操了第一個微服務例子,并用不同的方式運作了它,完整的跑通這個簡單的示例後,相信你對微服務的認識又進了一步。

繼續閱讀