Bu örnekte basit bir gRPC istemcisi ve sunucu uygulaması oluşturacağız. Basit bir şekliyle, istemci bir istek gönderiyor ve sunucudan bir yanıt alıyor. Hangi gRPC ve proto dosyalarının ayrıntılarına girmeyeceğim, ancak yazının en altına bazı linkler ekledim.


Burada iki önemli şey var. Birincisi, istemci ve sunucu uygulamaları aynı protobuf dosyasını paylaşır. İkincisi, proto dosyasını güncellerseniz, değişiklikleri *.pb.go dosyasına yansıtacak şekilde yeniden derlemeniz gerekir.


Ön şartlar


go modülünü hazırlama


go mod init github.com/YOU/bank

gRPC kurulumu


go get -u google.golang.org/grpc

protobuf kurulumu


# MacOS
brew install protobuf

protoc-gen-go kurulumu


go get -u github.com/golang/protobuf/protoc-gen-go

Yapı


Bir gRPC uygulaması oluşturduğunuzda, önce bir *.proto dosyası oluşturun ve derleyin, ardından uygulamanızı geliştirmeye başlayın.


├── Makefile
├── client
│   └── main.go
├── go.mod
├── go.sum
├── pkg
│   └── proto
│   └── credit
│   ├── credit.pb.go
│   └── credit.proto
└── server
└── main.go

Dosyalar


Makefile


.PHONY: compile
compile: ## Compile the proto file.
protoc -I pkg/proto/credit/ pkg/proto/credit/credit.proto --go_out=plugins=grpc:pkg/proto/credit/

.PHONY: server
server: ## Build and run server.
go build -race -ldflags "-s -w" -o bin/server server/main.go
bin/server

.PHONY: client
client: ## Build and run client.
go build -race -ldflags "-s -w" -o bin/client client/main.go
bin/client

credit.proto


syntax = "proto3";

package credit;

message CreditRequest {
float amount = 1;
}

message CreditResponse {
string confirmation = 1;
}

service CreditService {
rpc Credit(CreditRequest) returns (CreditResponse) {}
}

credit.pb.go


İçeriği buraya eklemiyorum çünkü yukarıdaki komutla üretiliyor.


make compile

client/main.go


package main

import (
"context"
"log"
"time"

"github.com/YOU/bank/pkg/proto/credit"
"google.golang.org/grpc"
)

func main() {
log.Println("Client running ...")

conn, err := grpc.Dial(":50051", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
log.Fatalln(err)
}
defer conn.Close()

client := credit.NewCreditServiceClient(conn)

request := &credit.CreditRequest{Amount: 1990.01}

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

response, err := client.Credit(ctx, request)
if err != nil {
log.Fatalln(err)
}

log.Println("Response:", response.GetConfirmation())
}

server/main.go


package main

import (
"context"
"fmt"
"log"
"net"

"github.com/YOU/bank/pkg/proto/credit"
"google.golang.org/grpc"
)

type server struct {
credit.UnimplementedCreditServiceServer
}

func main() {
log.Println("Server running ...")

lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalln(err)
}

srv := grpc.NewServer()
credit.RegisterCreditServiceServer(srv, &server{})

log.Fatalln(srv.Serve(lis))
}

func (s *server) Credit(ctx context.Context, request *credit.CreditRequest) (*credit.CreditResponse, error) {
log.Println(fmt.Sprintf("Request: %g", request.GetAmount()))

return &credit.CreditResponse{Confirmation: fmt.Sprintf("Credited %g", request.GetAmount())}, nil
}

Test


$ make server
go build -race -ldflags "-s -w" -o bin/server server/main.go
bin/server
2020/04/04 18:07:37 Server running ...

$ make client
go build -race -ldflags "-s -w" -o bin/client client/main.go
bin/client
2020/04/04 18:07:42 Client running ...
2020/04/04 18:07:42 Response: Credited 1990.01

Yukarıdaki istemci kodunu çalıştırdığınızda, sunucu ayrıca aşağıdaki mesajı da verecektir.


2020/04/04 18:07:42 Request: 1990.01

Referanslar