自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

使用 Go 構(gòu)建分布式系統(tǒng):基于 gRPC 的主從節(jié)點(diǎn)架構(gòu)

開(kāi)發(fā) 前端
我們使用 Golang 構(gòu)建了一個(gè)基本的分布式系統(tǒng),該系統(tǒng)采用主從架構(gòu)并使用 gRPC 進(jìn)行高效通信。在實(shí)際場(chǎng)景中,您可以使用更復(fù)雜的任務(wù)分配、負(fù)載均衡和錯(cuò)誤處理來(lái)擴(kuò)展此模型,以處理生產(chǎn)級(jí)別的分布式任務(wù)。

在現(xiàn)代軟件開(kāi)發(fā)領(lǐng)域,分布式系統(tǒng)已經(jīng)變得至關(guān)重要。它們使服務(wù)能夠擴(kuò)展、處理大量數(shù)據(jù)并提供高可用性。本文將指導(dǎo)您使用 Golang 構(gòu)建一個(gè)簡(jiǎn)單的分布式系統(tǒng),該系統(tǒng)利用主節(jié)點(diǎn)和單個(gè)工作節(jié)點(diǎn),并使用 gRPC 協(xié)議進(jìn)行通信。

這種架構(gòu)非常適合數(shù)據(jù)處理、并行計(jì)算和大規(guī)模處理工作負(fù)載等分布式任務(wù)。我們將介紹如何設(shè)置主從結(jié)構(gòu)、建立基于 gRPC 的通信,以及實(shí)現(xiàn)簡(jiǎn)單的任務(wù)分配和執(zhí)行流程。

系統(tǒng)概述

我們的分布式系統(tǒng)包含以下組件:

  • 主節(jié)點(diǎn): 控制器節(jié)點(diǎn),負(fù)責(zé)將任務(wù)分配給工作節(jié)點(diǎn)。它跟蹤可用的工作節(jié)點(diǎn)、監(jiān)控任務(wù)狀態(tài)并管理任務(wù)分配。
  • 工作節(jié)點(diǎn): 執(zhí)行器節(jié)點(diǎn),接收來(lái)自主節(jié)點(diǎn)的任務(wù),執(zhí)行計(jì)算并返回結(jié)果。
  • gRPC 協(xié)議: gRPC(Google Remote Procedure Call)用于主節(jié)點(diǎn)和工作節(jié)點(diǎn)之間的通信,實(shí)現(xiàn)高效、高性能的通信。

前提條件

  • 系統(tǒng)上已安裝 Go 1.13+。
  • 用于生成 gRPC 代碼的 Protobuf 編譯器 (protoc)。
  • gRPC-Go 和 Protobuf 庫(kù)。
go install google.golang.org/grpc
go install google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/protobuf/cmd/protoc-gen-go-grpc

設(shè)置 gRPC 服務(wù)定義

創(chuàng)建基于 gRPC 的分布式系統(tǒng)的第一步是在 .proto 文件中定義 gRPC 服務(wù)和消息。此文件概述了用于通信的服務(wù)、RPC 方法和消息結(jié)構(gòu)。

1. 在 Proto 文件中定義 gRPC 服務(wù)

創(chuàng)建一個(gè)名為 node.proto 的文件,內(nèi)容如下:

syntax = "proto3";
package core;
option go_package = ".;core";

message Request {
    string action = 1;
}

message Response {
    string data = 1;
}

service NodeService {
    rpc ReportStatus(Request) returns (Response){};
    rpc AssignTask(Request) returns (stream Response){};
}

2. 從 Proto 文件生成 gRPC 代碼

使用 protoc 為我們的 gRPC 服務(wù)生成 Go 代碼:

mkdir core
protoc --go_out=./core --go-grpc_out=./core node.proto

實(shí)現(xiàn) gRPC 服務(wù)端代碼

我們?cè)O(shè)置了一個(gè) gRPC 服務(wù)器來(lái)報(bào)告狀態(tài),并通過(guò)命令通道持續(xù)發(fā)送客戶端任務(wù)。它使用 Go 的并發(fā)特性來(lái)處理實(shí)時(shí)命令通知。

package core

import "context"

type NodeServiceGrpcServer struct {
 UnimplementedNodeServiceServer
 CmdChannel chan string
}

func (n NodeServiceGrpcServer) ReportStatus(ctx context.Context, request *Request) (*Response, error) {
 return &Response{Data: "ok"}, nil
}

func (n NodeServiceGrpcServer) AssignTask(request *Request, server NodeService_AssignTaskServer) error {
 for {
  select {
  case cmd := <-n.CmdChannel:
   if err := server.Send(&Response{Data: cmd}); err != nil {
    return err
   }
  }
 }
}

var server *NodeServiceGrpcServer

func GetNodeServiceGrpcServer() *NodeServiceGrpcServer {
 if server == nil {
  server = &NodeServiceGrpcServer{
   CmdChannel: make(chan string),
  }
 }
 return server
}

實(shí)現(xiàn)主節(jié)點(diǎn)

主節(jié)點(diǎn)負(fù)責(zé)將任務(wù)分配給工作節(jié)點(diǎn)。它通過(guò) gRPC 連接到工作節(jié)點(diǎn),并使用 AssignTask 方法分配任務(wù)。

現(xiàn)在,讓我們?cè)诿麨?node.go 的文件中實(shí)現(xiàn)主節(jié)點(diǎn):我們使用 API 框架 gin 創(chuàng)建一個(gè)簡(jiǎn)單的 API 服務(wù),該服務(wù)允許對(duì) /tasks 的 POST 請(qǐng)求將命令發(fā)送到通道 CmdChannel 并傳遞給 NodeServiceGrpcServer。

package core

import (
 "net"
 "net/http"

 "github.com/gin-gonic/gin"
 "google.golang.org/grpc"
)

type MasterNode struct {
 api     *gin.Engine
 ln      net.Listener
 svr     *grpc.Server
 nodeSvr *NodeServiceGrpcServer
}

func (n *MasterNode) Init() (err error) {
 n.ln, err = net.Listen("tcp", ":50051")
 if err != nil {
  return err
 }
 n.svr = grpc.NewServer()
 n.nodeSvr = GetNodeServiceGrpcServer()
 RegisterNodeServiceServer(node.svr, n.nodeSvr)
 n.api = gin.Default()
 n.api.POST("/tasks", func(c *gin.Context) {
  var payload struct {
   Cmd string `json:"cmd"`
  }
  if err := c.ShouldBindBodyWithJSON(&payload); err != nil {
   c.AbortWithStatus(http.StatusBadRequest)
   return
  }
  n.nodeSvr.CmdChannel <- payload.Cmd
  c.AbortWithStatusJSON(200, http.StatusOK)
 })
 return nil
}

func (n *MasterNode) Start() {
 go n.svr.Serve(n.ln)
 _ = n.api.Run(":9092")
 n.svr.Stop()
}

var node *MasterNode

func GetMasterNode() *MasterNode {
 if node == nil {
  node = &MasterNode{}
  if err := node.Init(); err != nil {
   panic(err)
  }
 }
 return node
}

實(shí)現(xiàn)工作節(jié)點(diǎn)

工作節(jié)點(diǎn)的職責(zé)是從主節(jié)點(diǎn)接收任務(wù)、處理任務(wù)并返回結(jié)果。

現(xiàn)在,讓我們?cè)诿麨?worker_node.go 的文件中實(shí)現(xiàn)工作服務(wù)器:工作節(jié)點(diǎn)通過(guò)獲取的流從服務(wù)器(主節(jié)點(diǎn))連續(xù)接收數(shù)據(jù)并執(zhí)行命令。

package core

import (
 "context"
 "fmt"
 "os/exec"
 "strings"

 "google.golang.org/grpc"
)

type WokerNode struct {
 conn *grpc.ClientConn
 c    NodeServiceClient
}

func (n *WokerNode) Init() (err error) {
 n.conn, err = grpc.Dial("localhost:50051", grpc.WithInsecure())
 if err != nil {
  return err
 }
 n.c = NewNodeServiceClient(n.conn)
 return nil
}

func (n *WokerNode) Start() {
 fmt.Println("worker node started")
 _, _ = n.c.ReportStatus(context.Background(), &Request{})
 stream, _ := n.c.AssignTask(context.Background(), &Request{})
 for {
  res, err := stream.Recv()
  if err != nil {
   return
  }
  fmt.Print("received command: ", res.Data)
  parts := strings.Split(res.Data, " ")
  if err := exec.Command(parts[0], parts[1:]...).Run(); err != nil {
   fmt.Println(err)
  }
 }
}

var workerNode *WokerNode

func GetWorkerNode() *WokerNode {
 if workerNode == nil {
  workerNode = &WokerNode{}
  if err := workerNode.Init(); err != nil {
   panic(err)
  }
 }
 return workerNode
}

整合主從節(jié)點(diǎn)

我們創(chuàng)建一個(gè) main.go,它位于 core 文件夾之外。main 函數(shù)接受一個(gè)參數(shù),并將其與 switch 語(yǔ)句進(jìn)行比較,以確定是運(yùn)行主節(jié)點(diǎn)還是工作節(jié)點(diǎn)。

package main

import (
 "go-master-worker-node/core"
 "os"
)

func main() {
 nodeType := os.Args[1]
 switch nodeType {
 case "master":
  core.GetMasterNode().Start()
 case "worker":
  core.GetWorkerNode().Start()
 default:
  panic("invalid node type")
 }
}

運(yùn)行主節(jié)點(diǎn)和工作節(jié)點(diǎn)

啟動(dòng)主節(jié)點(diǎn):

go run main.go master

啟動(dòng)工作節(jié)點(diǎn):

go run main.go worker

使用 Curl 發(fā)送 POST 請(qǐng)求

我們可以使用 curl POST 方法發(fā)送命令,如下所示,我們向本地主機(jī) 9092 發(fā)送一個(gè) touch 命令,路徑設(shè)置為“tasks”,這是主節(jié)點(diǎn)當(dāng)前運(yùn)行的位置。

發(fā)送 touch 命令:

curl -X POST -H "Content-Type: application/json" -d '{"cmd": "touch test.txt"}' http://localhost:9092/tasks

結(jié)論

我們使用 Golang 構(gòu)建了一個(gè)基本的分布式系統(tǒng),該系統(tǒng)采用主從架構(gòu)并使用 gRPC 進(jìn)行高效通信。在實(shí)際場(chǎng)景中,您可以使用更復(fù)雜的任務(wù)分配、負(fù)載均衡和錯(cuò)誤處理來(lái)擴(kuò)展此模型,以處理生產(chǎn)級(jí)別的分布式任務(wù)。

責(zé)任編輯:武曉燕 來(lái)源: 源自開(kāi)發(fā)者
相關(guān)推薦

2019-12-26 08:59:20

Redis主從架構(gòu)

2023-05-29 14:07:00

Zuul網(wǎng)關(guān)系統(tǒng)

2020-07-15 09:20:48

MyCatMySQL分布式

2022-03-08 07:22:48

Redis腳本分布式鎖

2023-11-02 09:33:31

Go語(yǔ)言Raft算法

2023-01-06 16:42:28

2022-05-11 13:55:18

高可用性分布式彈性

2022-01-26 00:03:00

高可用gRPC微服務(wù)

2017-12-20 16:15:30

分布式系統(tǒng)架構(gòu)

2023-08-25 16:26:49

微服務(wù)架構(gòu)

2024-03-19 11:41:12

2015-07-28 10:14:33

HBasehadoop

2023-05-12 08:23:03

分布式系統(tǒng)網(wǎng)絡(luò)

2018-12-14 10:06:22

緩存分布式系統(tǒng)

2018-01-23 15:55:23

分布式系統(tǒng)架構(gòu)

2010-01-15 10:15:34

分布式交換技術(shù)

2016-08-12 15:17:40

分布式

2017-10-19 08:45:15

存儲(chǔ)系統(tǒng)HBase

2023-02-11 00:04:17

分布式系統(tǒng)安全

2024-03-05 09:52:57

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)