gRPC의 기초 지식

22250 단어 networkingapisgogrpc
만약 당신이 나와 매우 비슷하다면, 당신은 이미 수없이 gRPC를 들어 보았지만, 그것이 실제로 무엇인지, 그 용례가 무엇인지, 그리고 왜 모든 사람들이 그것을 이야기하고 있는지 거의 모른다.처음에 나는 이것이 틀림없이 또 다른 유행어라고 생각했다.다행히도 내가 틀렸다😆. 나는 며칠 동안 책을 읽고 더 많은 것을 알게 되었다.이 박문은 내가 배운 모든 것을 총결하였다.나는 네가 좋아하길 바란다!

원격 프로세스 호출은 무엇입니까?


원격 프로세스 호출(RPC)은 웹 서비스 간에 사용되는 통신 프로토콜입니다.RPC의 중심 사상은 클라이언트 응용 프로그램이 서버 응용 프로그램에서 프로세스(함수)를 실행할 수 있도록 하는 것이다. 이 프로세스가 로컬에서 실행되는 것과 같다.네트워크 디테일은 개발자로부터 추상적으로 만들어져 사용하기 쉽다.
구체화를 위해 일반적인 RPC 흐름을 살펴보십시오.
  • 클라이언트 호출 함수
  • 이 함수는 사실상 원격 프로세스 호출이다.서버에 이 프로세스를 실행하기 위한 요청
  • 프로세스에 전달할 매개 변수를 요청
  • 서버에서 수행
  • 클라이언트에게 프로그램 실행 결과를 포함하는 응답
  • 클라이언트의 측면에서 볼 때, 이 과정은 로컬에서 실행되는 것 같다.이것은 매우 좋은 추상적인 개념이지만 함정도 존재한다.Martin Kleppmann은 그의 책Designing Data-Intensive Applications에서 원격 프로세스 호출과 로컬 프로세스 호출 사이의 차이를 강조했다.
  • 국부 함수 호출은 예측할 수 있으며, 그 성공은 당신이 제어하는 요소에 달려 있습니다.반면 인터넷 요청은 예측할 수 없고 여러 가지 이유로 실패했다.
  • 국부 함수가 결과를 되돌려주거나 이상을 일으키거나 되돌려 주지 않습니다.또한 시간 초과로 인해 네트워크 요청이 되돌아올 수 있지만 결과가 없습니다.이런 상황에서 무슨 일이 일어났는지 알 수가 없다.
  • 네트워크 요청을 수신하고 실행할 수 있지만 네트워크 응답만 실패했습니다.네트워크 요청 실패는 보통 재시도를 통해 처리되지만, 불행하게도, 이 함수는 응답만 잃어버리는 것을 모르기 때문에 여러 번 실행됩니다.
  • 국부 함수를 호출할 때마다 이 함수를 실행하는 데 걸리는 시간은 비슷하다.네트워크 특정 문제로 인해 네트워크 요청은 가변 지연 - 네트워크 혼잡, 서버 최대 용량 등.
  • gRPC란 무엇입니까?


    gRPC website는 이를 "어느 곳에서든 실행할 수 있는 현대 소스 원격 프로세스 호출(RPC) 프레임워크라고 기술했다. 클라이언트와 서버 응용 프로그램이 투명하게 통신하고 연결 시스템을 구축하는 것이 더욱 쉬워졌다"고 설명했다.구글이 만든 뒤 2016년에 오픈했다.gRPC는 RPC를 사용하는 통신의 부흥을 추진했다.서비스 구조가 발전함에 따라 서비스에서 서비스 통신까지의 천연적인 귀착점을 찾았다.
    gRPC는 프로토콜 버퍼(protobufs)를 사용합니다. 구조화된 데이터를 정렬/반정렬하는 방법입니다.프로토콜 버퍼 메시지는 이진 형식으로 인코딩됩니다.이것은 전선을 통해 메시지를 보내는 것을 매우 빨리 한다.적어도 JSON과 같은 텍스트 형식보다는프로토콜 버퍼의 사용과 gRPC 주위의 강력하고 사용하기 쉬운 도구를 사용하여 RPC를 실현하는 첫 번째 프레임워크가 됩니다.
    어떤 기술과 마찬가지로 장점과 단점이 있다.마이크로소프트의 이 문장article은 그 중의 일부를 두드러지게 했다.어쨌든
    gRPC의 이점
  • 성능 - 다른 프로토콜
  • 에 비해 gRPC 속도가 빠름
  • 코드 생성 - 서버 및 클라이언트 코드가 단일 파일에서 자동으로 생성됨
  • 흐름 - gRPC 지원 HTTP 흐름
  • gRPC 단점
  • 제한된 브라우저 지원 - 브라우저에서 HTTP/2에 대한 제한된 지원
  • 읽을 수 없음 - gRPC는 바이너리 형식을 사용하기 때문에 읽을 수 없습니다.
  • 프로토콜 버퍼


    위에서 말한 바와 같이 프로토콜 버퍼는 구조화된 데이터를 서열화/반서열화하는 방법입니다.프로토콜 버퍼 메시지는 키 값으로 구성된 패턴 정의를 사용합니다.
    message Person {
      string name = 1;
      int32 id = 2;
      string email = 3;
    }
    
    너는 사람을 하나의 구조체로 볼 수 있다.각 필드는 키 값 쌍이며 각각의 데이터 형식으로 설명됩니다.각 필드에는 키와 연관된 숫자가 있습니다.사실상, 키는 필드 번호와 인코딩 중인 데이터 형식에 대한 정보를 포함하여 값의 길이를 결정합니다.이것은 통상적으로 라벨이라고 불린다.예를 들어, 만약에 우리가protobuf 메시지가 있다면
    message Test2 {
      string b = 2;
    }
    
    b 값을 testing 로 설정하면 해당 인코딩은
    12 07 74 65 73 74 69 6e 67
    
    바이트1207가 표시를 구성합니다.값 12 을 디코딩하여 필드 번호 2와 데이터 형식 문자열을 얻습니다.이 경우 7의 값의 길이를 제공하기 위해 값07을 디코딩합니다.보시다시피 7 바이트가 문자열의 값을 보여 줍니다.관심이 있으시면 official guide 에서 프로토콜 버퍼 인코딩에 대한 더 많은 정보를 찾을 수 있습니다.비록 세부 사항이 훨씬 적지만 이 예는 실제로는 거기서부터 시작된다.

    REST 왜?


    REST는 네트워크 통신의 규범 표준이다.이것은 이미 생산 과정에서 전투 테스트를 거쳤고 대량의 도구가 RESTful 서비스를 실현하는 데 사용되며 대부분의 개발자들은 RESTful 서비스를 설계, 구축, 유지하는 데 만족한다.물론 가장 큰 문제는 gRPC에 무슨 문제가 있어서 우리가 RESTful 서비스 창설을 포기할 수 있느냐는 것이다.답은 매우 간단하다: 성능.gRPC를 사용하면 HTTP/2 또는 양방향 흐름을 사용하는 등 다른 장점이 있지만 표준 용례에 있어서 성능이 그 주요 원인이다.JSON의 서열화/반서열화 속도는 프로토타입보다 훨씬 느리다.규모상, 이것은 전체 시스템의 성능을 현저히 떨어뜨릴 수 있다.프로토타입은 2진 형식이기 때문에 서열화/반서열화 속도가 훨씬 빠르다.일부 글은 5-6배의 개선이 있다고 주장한다.

    gRPC 예


    코드 예시가 없어, 아무것도 완전하지 않아!나는 그것을 가능한 한 쉽게 이해하도록 하려고 한다.만약 어떤 개선이 있으면 저에게 알려주세요.모든 코드here를 찾을 수 있습니다.우리는 gRPC 사이트의 Quick Start 부분에서 이 서비스를 실시할 것이다.나는 이 강좌에서 Golang을 사용한다.
    내가 직면한 장애물 중 하나는 원형 파일에서 자동으로 코드를 생성하는 것이다.프로토타입 컴파일러가 새 Golang 플러그인을 향해 매진하고 있습니다. (자동 코드 생성을 실행합니다.)이전 버전 (내가 사용한) 과 새 버전이 출력한 파일은 약간 다르기 때문에 공식 grpc examples 저장소의 코드를 따를 수 없습니다.간단하게 보기 위해서 이 강좌는 오래된 Golang 플러그인을 사용했습니다.너무 좋아요. 시작합시다.🥳
    서비스는 정말 간단하다. 서비스가 하는 것은 단지 한 사람에게 안부를 묻는 것이다.클라이언트는 서버에 이름을 포함하는 요청을 보낼 수 있습니다.서버에서 간단한 메시지 "Hello <name>" 를 생성합니다.한마디로 서버는 실행 과정을 책임지고 결과를 클라이언트에게 되돌려준다.고객의 관점에서 볼 때, 이 과정은 현지에서 운행된다.
    우선 의존항을 설치해야 한다.
  • Protobuf 컴파일러 - 설치instructions
  • Protobuf 컴파일러용 Golang 플러그인 - 설치instructions
  • protobuf 컴파일러와 Golang 플러그인은 코드 생성에 사용됩니다.그들은 자동으로 서버와 클라이언트 코드를 실현하고 함수 정의를 개발자에게만 남긴다.
    프로토콜 모드 helloworld.proto 를 만들었습니다.
    syntax = "proto3"; // This denotes the protobuf version
    
    // All protobufs have a package name. This is to avoid name clashes with other protocol
    // message types. In Golang, the package name is used as the Go package name for the
    // generated files. This is however overwritten if you specify the go_package option
    package helloworld; 
    
    // This option is specifies the full import path of the Go package that contains
    // the generated code.
    option go_package = "github.com/senyosimpson/tutorials/grokkingrpc/helloworld";
    
    // This defines the service. In a service, you define rpc methods. These are
    // method signatures that contain their request and response types.
    service HelloWorld {
        rpc Greet(HelloRequest) returns (HelloReply) {}
    }
    
    // Messages are defined by specifying their type and name of the variables it holds.
    // These are enumerated from 1 to n.
    message HelloRequest {
        string name = 1;
    }
    
    message HelloReply {
        string message = 1;
    }
    
    이제 Go 파일을 생성할 수 있는 프로토타입이 생겼습니다.이 파일에는 확장자 .pb.go 가 있습니다.이렇게 하려면 명령을 실행하십시오.
    protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld --go_opt=paths=source_relative
    
    기왕 우리가 이미 파일을 생성했으니, 우리는 서버를 만들 수 있다.생성된 파일 helloworld.pb.go 을 보면 HelloWorldServer 이라는 인터페이스를 찾을 수 있습니다.
    // HelloWorldServer is the server API for HelloWorld service.
    type HelloWorldServer interface {
        Greet(context.Context, *HelloRequest) (*HelloReply, error)
    
    우리는 이 인터페이스를 실현하여 우리의 서비스를 정의해야 한다.실행 중, 서버는 수신한 주어진 이름을 출력합니다.그것은 인사말이 담긴 답장 메시지 Hello <name> 를 되돌려줍니다.
    type helloWorldService struct {}
    
    func (s *HelloWorldServer) Greet(ctx context.Context, r *pb.HelloRequest) (*pb.HelloReply, error) {
        log.Printf("Received: %v", r.GetName())
        return &pb.HelloReply{Message: "Hello " + r.GetName()}, nil
    }
    
    참고로 자동 생성 함수GetName.이것은 helloworld.pb.go 파일에서 찾을 수 있습니다.
    나머지 필수 코드는 서버 자체를 실현하는 것이다.전체 코드
    package main
    
    import (
        "context"
        "log"
        "net"
    
        pb "github.com/senyosimpson/tutorials/grokkingrpc/helloworld"
        "google.golang.org/grpc"
    )
    
    type helloWorldServer struct{}
    
    func (s *helloWorldServer) Greet(ctx context.Context, r *pb.HelloRequest) (*pb.HelloReply, error) {
        log.Printf("Received: %v", r.GetName())
        return &pb.HelloReply{Message: "Hello " + r.GetName()}, nil
    }
    
    func main() {
        lis, err := net.Listen("tcp", ":50051")
        if err != nil {
            log.Fatalf("failed to listen: %v", err)
        }
    
        server := grpc.NewServer()
        pb.RegisterHelloWorldServer(server, &helloWorldServer{})
        if err := server.Serve(lis); err != nil {
            log.Fatalf("failed to serve: %v", err)
        }
    }
    
    클라이언트는 매우 간단하다. 나는 단지 예시 라이브러리에서 그것을 복사했을 뿐이다.결과의 주선은 서버에 대한 요청입니다.
    r, err := client.Greet(ctx, &pb.HelloRequest{Name: name})
    
    여기에서 우리는 클라이언트 호출 Greet 방법을 보았다.지정한 이름으로 요청 메시지를 전송합니다.
    package main
    
    import (
        "context"
        "log"
        "os"
        "time"
    
        "google.golang.org/grpc"
        pb "github.com/senyosimpson/tutorials/grokkingrpc/helloworld"
    )
    
    const (
        address = "localhost:50051"
    )
    
    func main() {
        // Set up a connection to the server.
        conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
        if err != nil {
            log.Fatalf("did not connect: %v", err)
        }
        defer conn.Close()
        client := pb.NewHelloWorldClient(conn)
    
        // Contact the server and print out its response.
        name := "Bas"
        if len(os.Args) > 1 {
            name = os.Args[1]
        }
    
        ctx, cancel := context.WithTimeout(context.Background(), time.Second)
        defer cancel()
        r, err := client.Greet(ctx, &pb.HelloRequest{Name: name})
        if err != nil {
            log.Fatalf("could not greet: %v", err)
        }
        log.Printf("Greeting: %s", r.GetMessage())
    }
    
    저희가 지금 테스트를 준비하고 있습니다!터미널에서 서버를 시작합니다.다른 한편, 우리는 클라이언트 코드를 실행하고 서버에 요청할 수 있다.다음 그림에서 서버는 왼쪽에 있고 클라이언트는 오른쪽에 있습니다.클라이언트가 답장 메시지를 되돌려주고 컨트롤러에 메시지를 인쇄하는 것을 볼 수 있습니다.

    이렇게!나는 당신이 gRPC 기초 지식의 연습에서 가치 있는 것을 얻기를 바랍니다.나는 당연히 학습과 창작을 매우 좋아한다.

    공구서류


    RPC

  • Remote Procedure Call - Tutorialspoint
  • Remote Procedure Call - Geeks for Geeks
  • Remote Procedure Call - Wikipedia
  • gRPC 및 REST

  • Migrating APIs from REST to gRPC
  • gRPC 회사

  • gRPC Official Website
  • gRPC - Wikipedia
  • 프로토콜 버퍼

  • Protocol buffers - Wikipedia
  • 5 Reasons to use protocol buffers
  • 좋은 웹페이지 즐겨찾기