doushi4864 2018-03-12 20:38 采纳率: 100%
浏览 1795
已采纳

转到gRPC简单服务异步和同步说明

我试图与gRPC一起了解GoLang“ Go”,并使简单的服务可扩展。 假设我有一个client1,它调用一个service1(加号),再调用service2(确定结果是否为质数),而service2将结果返回给service1,该结果全部通过gRPC返回给client1。 当我使用协议缓冲区“ proto3”并通过protoc生成Go代码时,我得到了以一种特定方式调用服务的生成方法。我认为将这些方法异步称为“ Go”是没有区别的。 而且底层调用似乎是“调用”,我认为它是同步的,一旦收到结果,调用就会返回。 我如何使service1成为“ performant”,我知道我可以在集群中运行它并拥有副本,但这意味着我只能根据集群中实例的数量为客户端提供服务。 我希望“单一”服务能够为多个客户提供服务(例如1000)。 这是一个简单的服务器,我不确定这是否有效:我确实知道 getprime 函数每次都会进行拨号,并且可能会移动它以使该拨号保留并重新使用;但更重要的是,我想提供一个简单的性能可扩展服务,并获得良好的理解。 (A)也许整个设计是不正确的,并且一旦收到指令“ ack”,service1应该立即返回,进行加法运算,然后将下一个请求发送给sercice2,后者确定答案是否是主要的;而且,service2只是以收到请求的确认作为响应。一旦service2确定了准备金,就会通过应答呼叫客户。 如果上面的(A)是更好的方法,那么仍然请解释下面的问题;处理多个客户端时会发生什么?对“ Listen”的调用会执行,“阻止或不阻止”等操作。

package main

import (
    pb "demo/internal/pkg/proto_gen/calc"
    "fmt"
    "golang.org/x/net/context"
    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
    "log"
    "net"
)

const (
    port = ":8080"
)

type service struct {
}

func (s *service) Calculate(ctx context.Context, req *pb.Instruction) (*pb.Response, error) {

    var answer float64
    answer = req.Number1 + req.Number2

    // call service prime
    p := getprime(int(answer))
    pa := pb.PrimeAnswer{Prime: p}
    return &pb.Response{Answer: answer, Prime: &pa}, nil
}

const (
    primeAddress = "127.0.0.1:8089"
)

func getprime(number int) bool {
    conn, err := grpc.Dial(primeAddress, grpc.WithInsecure())
    if err != nil {
        log.Fatalf("Did not connect to prime service: %v", err)
    }
    defer conn.Close()

    client := pb.NewPrimeServiceClient(conn)
    p := pb.PrimeMessage{"", float64(number)}

    r, err := client.Prime(context.Background(), &p)
    if err != nil {
        log.Fatalf("Call to prime service failed: %v", err)
    }
    return r.Prime
}

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

    s := grpc.NewServer()
    pb.RegisterCalculatorServer(s, &service{})
    reflection.Register(s)
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}
  • 写回答

2条回答 默认 最新

  • dsjxgu4759 2018-03-16 23:46
    关注

    Thanks for your question. It is true that gRPC-Go is sync only; that is your Unary RPC(the one in your example) will return only when the RPC has finished (got a response from the server).

    About performance:

    1. The Dial operation establishes an underlying connection which may be expensive. So it not wise to do it every time getprime is called. A better way is to create a client, keep it around and make calls to the prime server on it. This way only first RPC incurs the cost of connection.
    2. For each RPC request a server gets we launch a goroutine to process that request. So in general, this should scale fairly well.

    About (A): It is not uncommon for a service handler to make an RPC call to yet another server and wait for its response before returning back. Note that there's no way for a server to make call to the client.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 我的b站在没有碰到屏幕的情况下偶尔会自动跳出进度条,就像在屏幕上点了一下一样,但我并没有点。而且视频进度并没有变。这可能是什么原因造成的?
  • ¥30 STK matlab python仿真
  • ¥15 关于IMageEnView 图标定位问题
  • ¥20 求解答(matlab)
  • ¥30 ffmpeg库使用过程中遇到的问题
  • ¥15 pyqt5 中python如何通过Qtwebchannel主动发消息给web前端
  • ¥15 关于HTML中title获取xml内容的问题
  • ¥15 fanuc机器人PRIO083数字信号未复原错误,如何解决?
  • ¥20 如何为现有电路板增加远程控制功能
  • ¥15 UE5打包失败,求解决