成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

利用Go傳統(tǒng)RPC和gRPC框架分別實(shí)現(xiàn)一個(gè)RPC服務(wù)端

開發(fā) 前端
RPC(Remote Procedure Call, 遠(yuǎn)程過程調(diào)用) 是一種計(jì)算機(jī)通信協(xié)議, 它允許程序調(diào)用另一個(gè)地址空間(通常是遠(yuǎn)程機(jī)器上的)的過程或函數(shù), 就像本地調(diào)用一樣, 而不需要顯示地處理網(wǎng)絡(luò)通信的細(xì)節(jié)。

1.RPC原理介紹

RPC(Remote Procedure Call, 遠(yuǎn)程過程調(diào)用) 是一種計(jì)算機(jī)通信協(xié)議, 它允許程序調(diào)用另一個(gè)地址空間(通常是遠(yuǎn)程機(jī)器上的)的過程或函數(shù), 就像本地調(diào)用一樣, 而不需要顯示地處理網(wǎng)絡(luò)通信的細(xì)節(jié)。RPC使得分布式系統(tǒng)中的不同模塊能夠相互通信, 而對開發(fā)者而言, 這種通信就像是本地調(diào)用一樣簡單。其調(diào)用原理圖如下:

圖片圖片

上面的步驟看起來很復(fù)雜, 實(shí)際上, 在當(dāng)前的主流RPC框架, 例如:grpc、thrift, 只需要關(guān)心第1步和最后1步即可, 中間過程已經(jīng)由框架進(jìn)行了封裝。在這篇文章中, 將從學(xué)習(xí)的角度自己來實(shí)現(xiàn)一個(gè)RPC的服務(wù)端全流程。

2.實(shí)現(xiàn)RPC服務(wù)端

這里模擬了用戶信息的注冊管理流程, 在服務(wù)端, 保存有多個(gè)用戶信息, 并提供兩個(gè)遠(yuǎn)程調(diào)用接口, 一個(gè)是通過ID獲取對應(yīng)的用戶信息接口, 另一個(gè)是添加新的用戶。參考代碼如下:

// 1. 定義要遠(yuǎn)程調(diào)用的方法
type MathService struct {}

func (m *MathService) Multiply(args *Args, reply *int) error {
    *reply = args.A * args.B
    return nil
}

// 2. 定義請求和響應(yīng)的數(shù)據(jù)結(jié)構(gòu)
type Args struct {
    A, B int
}

在上面的代碼中, 我們定義了一個(gè)MathService結(jié)構(gòu)體,其中包含了一個(gè)Multiply方法,該方法用于實(shí)現(xiàn)兩個(gè)整數(shù)相乘的遠(yuǎn)程調(diào)用。接下來我們需要完成服務(wù)端的服務(wù)端口監(jiān)聽和連接建立, 參考代碼如下:

func main() {
    mathService := new(MathService)
    rpc.Register(mathService)

    listener, err := net.Listen("tcp", ":1234")
    if err != nil {
        log.Fatal("Listen error:", err)
    }

    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Fatal("Accept error:", err)
        }
        go rpc.ServeConn(conn)
    }
}

在上面的main函數(shù)中, 我們注冊了一個(gè)MathService服務(wù),并在本地監(jiān)聽1234端口,當(dāng)接收到客戶端連接后, 使用rpc.ServeConn來處理RPC請求。

3.實(shí)現(xiàn)客戶端連接

客戶端連接服務(wù)端的參考代碼如下:

type Args struct {
  A, B int
}

func main() {
    client, err := rpc.Dial("tcp", "localhost:1234")
    if err != nil {
        log.Fatal("Dial error:", err)
    }

    args := &Args{7, 8}
    var reply int

    err = client.Call("MathService.Multiply", args, &reply)
    if err != nil {
        log.Fatal("MathService.Multiply error:", err)
    }

    fmt.Printf("MathService.Multiply: %d * %d = %d\n", args.A, args.B, reply)
}

先編譯服務(wù)端代碼并啟動(dòng), 然后執(zhí)行客戶端程序,結(jié)果如下:

圖片圖片

客戶端成功調(diào)用了服務(wù)端的遠(yuǎn)程函數(shù)并收到結(jié)果。

4.利用gRPC框架實(shí)現(xiàn)服務(wù)端

gRPC(gRPC Remote Procedure Calls)是由Google開發(fā)的開源RPC(Remote Procedure Call,遠(yuǎn)程過程調(diào)用)框架,其目標(biāo)是在跨網(wǎng)絡(luò)的服務(wù)之間實(shí)現(xiàn)高效的通信。gRPC使用Protocol Buffers(protobuf)作為其接口描述語言,并支持多種編程語言,包括C++, Java, Python, Go, Node.js等。

首先需要安裝gRPC相關(guān)的包,通過以下命令安裝:

go get -u google.golang.org/grpc

接著需要安裝Protocol Buffers工具, 可以從這里直接下載最新版, 根據(jù)自己的操作系統(tǒng)類型選擇:

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

接下來需要安裝兩個(gè)包:

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

緊接著創(chuàng)建proto文件, 內(nèi)容如下:

syntax = "proto3";

package grpcsample;
option go_package = ".";

message User {
  string id = 1;
  string name = 2;
  int32 age = 3;
}

service UserService {
  rpc GetUserById (UserRequest) returns (User);
  rpc AddUser (User) returns (User);
}

message UserRequest {
  string id = 1;
}

將上面的代碼生成文件, 文件名為: user.proto。

我這里將protoc二進(jìn)制程序放到工程根目錄gosample下, 接著在命令行下輸入以下命令:

./protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative ./grpcsample/user.proto

該命令將把.proto文件內(nèi)容生成對應(yīng)的grpc Go代碼, 生成后將在grpcsample目錄下生成user.pb.go和user_grpc.pb.go文件,如圖:

圖片圖片

在grpcsample目錄下新建工程文件userservice.go, 加入以下代碼:

import (
  "context"
  "fmt"
)

var users = map[string]User{
  "1": {Id: "1", Name: "John Doe", Age: 30},
  "2": {Id: "2", Name: "Jane Doe", Age: 25},
}

type UserServer struct {
  UnimplementedUserServiceServer
}

func (s *UserServer) GetUserById(ctx context.Context, req *UserRequest) (*User, error) {
  user, exists := users[req.Id]
  if exists {
    return &user, nil
  }
  return nil, fmt.Errorf("User with ID %s not found", req.Id)
}

func (s *UserServer) AddUser(ctx context.Context, user *User) (*User, error) {
  users[user.Id] = *user
  return user, nil
}

上面的代碼提供了兩個(gè)RPC方法, GetUserById支持通過ID查詢對應(yīng)的用戶信息, AddUser支持添加一個(gè)新的用戶。

接著添加服務(wù)端的主程序代碼:

import (
  "google.golang.org/grpc"
  pb "gosample/grpcsample"
)

func main() {
    listener, err := net.Listen("tcp", ":50051")
  if err != nil {
    log.Fatalf("Failed to listen: %v", err)
  }

  server := grpc.NewServer()
  pb.RegisterUserServiceServer(server, &pb.UserServer{})

  log.Println("gRPC server is running on port 50051")
  if err := server.Serve(listener); err != nil {
    log.Fatalf("Failed to serve: %v", err)
  }
}

在服務(wù)端主程序代碼中, 我們調(diào)用了grpcsample中的RegisterUserServiceServer方法注冊了一個(gè)服務(wù),并在本地的50051端口監(jiān)聽客戶端連接。

5.生成gRPC客戶端

同樣的方式, 新打開一個(gè)工程, 按照服務(wù)端生成gRPC的方式生成客戶端的代碼, 如圖:

圖片圖片

在客戶端的主程序中利用如下代碼進(jìn)行服務(wù)端方法調(diào)用:

package main

import (
  "context"
  "fmt"
  "log"

  "google.golang.org/grpc"
  "google.golang.org/grpc/credentials/insecure"

  pb "sampleclient/grpcsample"
)

func main() {
   conn, err := grpc.Dial("localhost:50051", grpc.WithTransportCredentials(insecure.NewCredentials()))
  if err != nil {
    log.Fatalf("Failed to connect: %v", err)
  }
  defer conn.Close()

  client := pb.NewUserServiceClient(conn)

  // 通過ID查詢用戶
  user, err := client.GetUserById(context.Background(), &pb.UserRequest{Id: "1"})
  if err != nil {
    log.Fatalf("Error getting user: %v", err)
  }
  fmt.Printf("User: %+v\n", user)

  // 添加一個(gè)新用戶
  newUser := &pb.User{Id: "3", Name: "Alice", Age: 28}
  addedUser, err := client.AddUser(context.Background(), newUser)
  if err != nil {
    log.Fatalf("Error adding user: %v", err)
  }
  fmt.Printf("Added User: %+v\n", addedUser)
}

在上面的代碼中, 首先通過grpc包中的Dial函數(shù)連接到本地50051端口, 并調(diào)用gRPC的方法NewUserServiceClient新建一個(gè)客戶端連接, 接著遠(yuǎn)程調(diào)用了服務(wù)端的兩個(gè)方法。首先開啟服務(wù)端, 查看客戶端調(diào)用方法后的返回,如圖:

圖片圖片

可以看到,成功獲取到遠(yuǎn)程的兩個(gè)方法返回的結(jié)果。

責(zé)任編輯:武曉燕 來源: 二進(jìn)制空間安全
相關(guān)推薦

2020-11-02 08:19:18

RPC框架Java

2023-01-29 23:51:07

微服務(wù)框架Go

2022-05-22 13:55:30

Go 語言

2024-01-02 13:58:04

GoREST API語言

2021-10-19 08:58:48

Java 語言 Java 基礎(chǔ)

2018-09-18 09:38:11

RPC遠(yuǎn)程調(diào)用網(wǎng)絡(luò)通信

2020-09-09 07:13:05

RPC框架

2022-03-01 11:38:51

RPC框架后端

2021-02-20 09:45:02

RPC框架Java

2022-11-07 18:36:03

組件RPC框架

2025-05-20 09:39:57

GogRPC微服務(wù)

2021-10-21 08:21:10

Java Reflect Java 基礎(chǔ)

2022-01-07 06:12:08

RPC框架限流

2017-04-11 16:16:48

HTTPS互聯(lián)網(wǎng)服務(wù)端

2023-06-10 23:01:41

GrpcProtobuf數(shù)據(jù)

2021-10-14 08:39:17

Java Netty Java 基礎(chǔ)

2021-06-10 07:49:26

RPCgRPC模式

2021-07-12 06:23:38

抓包gRpcRPC 框架

2012-10-10 09:14:50

PHPRPCPHP框架

2019-06-17 08:21:06

RPC框架服務(wù)
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 337p日韩| 91av精品 | 亚洲中午字幕 | 51ⅴ精品国产91久久久久久 | 情侣av| 色香婷婷 | 国产在线观 | av手机免费在线观看 | 成人av电影网 | 自拍在线 | 99精品一区 | 99re6热在线精品视频播放 | 亚洲一区久久 | 成人精品一区二区三区中文字幕 | 日韩一区精品 | 久久9999久久 | 欧美伊人久久久久久久久影院 | 日韩免| av大全在线观看 | 久久精品| 国产免费一区二区三区 | 成人毛片网站 | 国产精品成人一区二区 | 国产成人91| 久久99精品久久久久久 | 免费 视频 1级 | 一级毛片黄片 | 求个av网址| 成人免费看黄网站在线观看 | 精品免费国产一区二区三区四区 | 国产精品无码专区在线观看 | 久久久一二三区 | 超碰人人插 | 一区视频在线免费观看 | 欧美成年网站 | japanhd美女动 | 亚洲精品成人在线 | 午夜网| 国产精品美女视频 | 亚洲成av片人久久久 | 91秦先生艺校小琴 |