我试图与gRPC一起理解GoLang“Go”并使一个简单的服务可扩展。
假设我有一个client1调用service1(添加数字)调用service2(确定结果是否为prime),service2将结果返回给service1,该结果通过gRPC将结果返回给client1。
当我使用协议缓冲区“proto3”并通过protoc生成Go代码时。 我得到生成的方法,以一种特定的方式调用服务。 我认为没有任何区别可以异步调用方法“Go”。
基础调用似乎是“调用”,我认为它是同步的,一旦收到结果,调用就会返回。
如何使service1“performant”,我知道我可以在群集中运行它并拥有副本,但这意味着我只能按照群集中的实例数量为客户端提供服务。
我希望“单一”服务能够为多个客户端提供服务(例如1000)。
这是一个简单的服务器,我不确定这是否有效:
我知道getprime
函数每次都会拨号,
这可能会被移动,使这个表盘保持不变并重新使用;但更重要的是,我希望制作一个简单的高性能可扩展服务并获得良好的理解。
(A) 也许整个设计是不正确的,service1应该返回 一旦收到指令“ack”,就做加法并向sercice2发送下一个请求,确定答案是否为素数;再次,service2只响应对收到的请求的确认。一旦由服务2确定了素数,就会给答案客户打电话。
如果上述(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)
}
}
答案 0 :(得分:2)
感谢您的提问。确实,gRPC-Go只是同步;那就是你的Unary RPC(你的例子中的那个)只有在RPC完成后才会返回(从服务器得到响应)。
关于表现:
关于(A):服务处理程序对另一台服务器进行RPC调用并在返回之前等待其响应的情况并不少见。 请注意,服务器无法调用客户端。
答案 1 :(得分:1)
说出JimB所说的答案:" Synchronous"表示进行远程调用的函数在继续之前等待回复,而不是整个服务器或客户端进行回复。即使处理同步调用,服务器通常也是多线程的;当它响应第一个电话时,它可以接受并接听第二个电话。
同样,如果客户端有多个并发任务,每个任务都运行gRPC调用,则不会阻止该进程。像这样的客户端可能包括为最终用户提供服务的net/http
服务器,或者处理多个RPC的gRPC服务器。
如果您想要从进行RPC调用的特定函数执行其他操作,可能添加显式go
语句的位置。例如,如果要同时发出多个RPC调用然后等待所有结果进入,则可以在examples of fan-out calls之后编写代码。