欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

go-micro開發(fā)RPC服務(wù)以及運行原理介紹

 更新時間:2022年07月04日 10:00:13   作者:波斯馬  
這篇文章介紹了go-micro開發(fā)RPC服務(wù)的方法及其運行原理,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

go-micro是一個知名的golang微服務(wù)框架,最新版本是v4,這篇文章將介紹go-micro v4開發(fā)RPC服務(wù)的方法及其運作原理。

基本概念

go-micro有幾個重要的概念,后邊開發(fā)RPC服務(wù)和介紹其運行原理的時候會用到,這里先熟悉下:

  • Service:代表一個go-micro應(yīng)用程序,Service中包括:Server、Client、Broker、Transport、Registry、Config、Store、Cache等程序運行所需的各個模塊。
  • Server:代表一個go-micro服務(wù)器,主要函數(shù)包括:Start、Stop、Handle、Subscribe。默認創(chuàng)建的Server是 rpcServer。
  • Broker:用于處理異步消息,主要的函數(shù)包括:Connect、Publish、Subscribe。默認的Broker是httpBroker。
  • Router:用于消息處理的路由,內(nèi)部包括兩種路由方式:RPC服務(wù)映射serviceMap和消息訂閱器subscribers。
  • Codec:用于消息的編解碼,主要函數(shù)包括:Marshal、Unmarshal默認的Codec是json.Marshaler,是基于jsonpb的。RPC服務(wù)是根據(jù)請求頭中的Content-Type自動創(chuàng)建的。
  • Registry:用于服務(wù)發(fā)現(xiàn),主要函數(shù)包括:Register、Deregister、GetService、ListServices、Watch。默認的Registry是mdns。
  • Selector: 用于從同一個服務(wù)的多個實例之中選擇一個,支持緩存,有隨機和輪詢兩種策略。
  • Transport:用于同步通信,主要函數(shù)包括:Dial、Listen。它的底層基于Socket的send、recv語義,有多種實現(xiàn),包括http、grpc、quic等。默認的Transport是httpTransport。

開發(fā)RPC服務(wù)

RPC全稱是Remote Procedure Call,翻譯過來是就是:遠程過程調(diào)用,中心思想是:像調(diào)用本地函數(shù)一樣調(diào)用遠程函數(shù)。常見的Dubbo、Spring Cloud都可以稱為RPC框架,還有最近很流行的gRPC。

使用go-micro創(chuàng)建一個RPC服務(wù)很簡單,共分三步走:

1、編寫proto協(xié)議文件

這個服務(wù)提供的功能很簡單,名字為Hello,提供一個方法名字為Say,需要傳入一個字符串Name,然后返回一個字符串Message。這個文件我命名為 hello.proto,放到了項目中的 proto 文件夾中。

syntax = "proto3";

option go_package="/proto";

package Business;

service Hello {
  rpc Say (SayRequest) returns (SayResponse);
}

message SayResponse {
  string Message = 1;
}

message SayRequest {
  string Name = 1;
}

2、生成go-micro服務(wù)端代理

需要首先安裝protoc和兩個代碼生成插件。

protoc下載地址:https://github.com/protocolbuffers/protobuf/releases,保存到GO PATH/bin目錄中。同時建議將 GOPATH/bin 添加到環(huán)境變量 PATH 中,方便直接執(zhí)行相關(guān)命令。

兩個插件直接通過命令即可安裝:

go install google.golang.org/protobuf/cmd/protoc-gen-go
go install go-micro.dev/v4/cmd/protoc-gen-micro@v4

然后在項目的目錄下執(zhí)行命令:

protoc --go_out=. --go_opt=paths=source_relative --micro_out=. --micro_opt=paths=source_relative proto/hello.proto

然后會在proto文件夾中生成兩個文件:hello.pb.go 和 hello.pb.micro.go 。

下個步驟中就要使用它們來創(chuàng)建RPC服務(wù)。

3、編寫go-micro服務(wù)

這里先把代碼貼出來,然后再做一個簡要說明:

package main

import (
	"context"
	"fmt"
	"log"
	"rpchello/proto"

	"go-micro.dev/v4"
	"go-micro.dev/v4/server"
)

type Hello struct{}

func (s *Hello) Say(ctx context.Context, req *proto.SayRequest, rsp *proto.SayResponse) error {
	fmt.Println("request:", req.Name)
	rsp.Message = "Hello " + req.Name
	return nil
}

func main() {
	rpcServer := server.NewServer(
		server.Name("rpchello.service"),
		server.Address("0.0.0.0:8001"),
	)

	proto.RegisterHelloHandler(rpcServer, &Hello{})

	service := micro.NewService(
		micro.Server(rpcServer),
	)

	if err := service.Run(); err != nil {
		log.Fatal(err)
	}
}

上邊我們創(chuàng)建了一個 Hello 類型,然后給它綁定了一個名為Say的函數(shù)。這個是和proto協(xié)議對應(yīng)的,其實是實現(xiàn)了生成代碼 hello.pb.micro.go 中的HelloHandler接口:

type HelloHandler interface {
	Say(context.Context, *SayRequest, *SayResponse) error
}

然后main函數(shù)中是我們的重頭戲:先創(chuàng)建一個Server,默認情況下就是rpc Server,設(shè)置它的名字、監(jiān)聽地址等參數(shù);然后創(chuàng)建一個Service,并綁定剛剛創(chuàng)建的Server;然后使用生成的服務(wù)端代理函數(shù)將我們編寫的Hello服務(wù)注冊到Server中;最后開啟運行Service。

當(dāng)然只有一個服務(wù)端沒有什么意義,還得有客戶端來訪問它。這里也給一個例子:

package main

import (
	"bufio"
	"context"
	"fmt"
	"os"
	"rpchello/proto"

	"go-micro.dev/v4"
	"go-micro.dev/v4/client"
)

func main() {

	service := micro.NewService(
		micro.Client(client.NewClient()),
	)

	service.Init()
	client := proto.NewHelloService("rpchello.service", service.Client())

	rsp, err := client.Say(context.TODO(), &proto.SayRequest{Name: "BOSSMA"})
	if err != nil {
		fmt.Println(err)
	}

	fmt.Println(rsp)

	fmt.Println("Press Enter key to exit the program...")
	in := bufio.NewReader(os.Stdin)
	_, _, _ = in.ReadLine()
}

這里調(diào)用服務(wù)的時候沒有指定服務(wù)的地址和端口,因為內(nèi)部走了服務(wù)發(fā)現(xiàn),服務(wù)端會自動注冊服務(wù),客戶端會根據(jù)服務(wù)名稱查找到對應(yīng)的地址和端口。默認的服務(wù)發(fā)現(xiàn)機制使用的是mdns。

RPC服務(wù)的運行原理

這里從服務(wù)端的角度進行介紹,先來看一張圖:

請大家參考代碼從上往下看。

NewServer 時創(chuàng)建一個rpcServer,這個rpcServer還會創(chuàng)建一個httpTransport用于程序間網(wǎng)絡(luò)通信,并綁定到當(dāng)前rpcServer。

RegisterXXXHandler 時使用我們編寫的Handler創(chuàng)建一個內(nèi)部的service實例,然后注冊這個service實例到rpcServer內(nèi)部的router中,客戶端請求時會用到它。這里其實可以注冊任意一個帶方法的類型,并不一定要定義proto協(xié)議,定義它只是為了協(xié)作更方便。

Service.Run 時會調(diào)用rpcServer的Start方法,這個方法內(nèi)部會調(diào)用其綁定的httpTransport的Listen方法,然后在其創(chuàng)建的Listener上接收客戶端連接,接收方法Accept傳入了當(dāng)前rpcServer的連接處理方法:rpcServer.ServeConn,有連接到來時會調(diào)用它。

當(dāng)客戶端請求來臨時,客戶端連接被交給rpcServer的ServeConn方法,然后又調(diào)用到HandleEvent方法。

然后進入rpcServer內(nèi)部的router的函數(shù)ServeRequest中,通過分析請求消息,找到請求的服務(wù)名字和方法名字,在router中找到前面注冊過的service,通過servcie.call,再進入function.call,最終通過反射調(diào)用到我們編寫的Handler的業(yè)務(wù)方法。

有的同學(xué)可能會想,反射不是性能很低嗎?!反射性能低主要是查找方法和字段的時候,調(diào)用方法的性能并不低,而查找方法和字段等的操作已經(jīng)在RegisterXXXHandler的步驟中做了,并且緩存到了router中,所以性能并不受影響。

到此這篇關(guān)于go-micro開發(fā)RPC服務(wù)的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • golang string、int、int64 float 互相轉(zhuǎn)換方式

    golang string、int、int64 float 互相轉(zhuǎn)換方式

    這篇文章主要介紹了golang string、int、int64 float 互相轉(zhuǎn)換方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Golang獲取本地IP地址方法分享

    Golang獲取本地IP地址方法分享

    這篇文章主要給大家介紹了Golang 獲取本地 IP 地址方法,文中有詳細的代碼示例,對我們的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-07-07
  • golang使用正則表達式解析網(wǎng)頁

    golang使用正則表達式解析網(wǎng)頁

    這篇文章主要介紹了golang使用正則表達式解析網(wǎng)頁,需要的朋友可以參考下
    2015-03-03
  • 安裝GoLang環(huán)境和開發(fā)工具的圖文教程

    安裝GoLang環(huán)境和開發(fā)工具的圖文教程

    Go是一門由Google開發(fā)的編程語言,GoLand的安裝非常簡單,本文主要介紹了安裝GoLang環(huán)境和開發(fā)工具的圖文教程,具有一定的參考價值,感興趣的可以了解一下
    2023-09-09
  • golang flag簡單用法

    golang flag簡單用法

    本篇文章介紹了golang flag包的一個簡單的用法,希望通過一個簡單的實例,能讓大家了解它的用法,從中獲得啟發(fā)
    2018-09-09
  • golang環(huán)形隊列實現(xiàn)代碼示例

    golang環(huán)形隊列實現(xiàn)代碼示例

    這篇文章主要介紹了golang環(huán)形隊列實現(xiàn)代碼示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 詳解Go如何實現(xiàn)協(xié)程并發(fā)執(zhí)行

    詳解Go如何實現(xiàn)協(xié)程并發(fā)執(zhí)行

    線程是通過本地隊列,全局隊列或者偷其它線程的方式來獲取協(xié)程的,目前看來,線程運行完一個協(xié)程后再從隊列中獲取下一個協(xié)程執(zhí)行,還只是順序執(zhí)行協(xié)程的,而多個線程一起這么運行也能達到并發(fā)的效果,接下來就給給大家詳細介紹一下Go如何實現(xiàn)協(xié)程并發(fā)執(zhí)行
    2023-08-08
  • Golang當(dāng)中的定時器實例詳解

    Golang當(dāng)中的定時器實例詳解

    這篇文章主要給大家介紹了關(guān)于Golang當(dāng)中定時器的相關(guān)資料,定時器的實現(xiàn)大家應(yīng)該都遇到過,最近在學(xué)習(xí)golang,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • 詳解Go中Set的實現(xiàn)方式

    詳解Go中Set的實現(xiàn)方式

    這篇文章主要介紹了詳解Go中Set的實現(xiàn)方式,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 重學(xué)Go語言之基礎(chǔ)數(shù)據(jù)類型詳解

    重學(xué)Go語言之基礎(chǔ)數(shù)據(jù)類型詳解

    Go語言有非常強大的數(shù)據(jù)類型系統(tǒng),其支持的數(shù)據(jù)類型大體上可分為四類:基礎(chǔ)數(shù)據(jù)類型、引用數(shù)據(jù)類型、接口類型、復(fù)合類型。本文就來講講它們各自的用法吧
    2023-02-02

最新評論